【问题标题】:Separation of concerns dilemma in RailsRails 中的关注点分离困境
【发布时间】:2010-07-06 12:02:59
【问题描述】:

我正在尝试为我的 rails 应用程序进行日志记录,但对 rails 中使用的哲学存在一些困境。我的应用程序有 Link 模型 has_many Hits:

class Link < AR::Base
  has_many :hits
end

class Hit < AR::Base
  belongs_to :link
end

现在每次点击链接时,我都会调用hit! 方法来记录链接上的请求(为了保持控制器瘦我让模型变胖):

class LinksController < ApplicationController
  def hit
    link = Link.find(params[:id])
    link.hit!(request)
  end
end

class Link < AR::Base
  def hit!(request)
    params = extract_data_from_request(request)
    hits.create(params)
  end
end

现在我很困惑。我想记录 request 对象附带的数据(如远程 ip、referrer、用户代理等),因此我需要将请求对象向下传递给模型,但我认为这不符合“关注点分离” " 并且模糊了 MVC 设计模式中的责任界限(当然,如果我错了,请纠正我)。另外,如果我要在控制器本身中创建一个Hit 对象,那么我正在制作瘦模型和胖控制器:

class LinksController < ApplicationController
  def hit
    hit_params = extract_data_from_request(request)
    Hit.create(hit_params.merge(:link_id => params[:id])
  end
end

虽然后一种情况使测试更容易(我不需要在模型规范中模拟请求) - 它似乎并不正确。

对此的任何建议 - 非常感谢。

附: extract_data_from_request(req) 方法放置在需要的适当位置。它返回 Hit 对象所需属性的哈希值。

【问题讨论】:

    标签: ruby-on-rails separation-of-concerns


    【解决方案1】:

    就我个人而言,我会警惕过度思考这些事情。

    点击的概念与网站或 Web 应用程序密切相关,(HTTP)请求的概念也是如此。胖控制器反模式更多是关于具有冗长的控制器操作,其中包含 ActiveRecord 查找语句和业务逻辑(通常以if/elsif/else 块为特征),可以轻松提取到模型中。

    控制器有一定的编排职责。在一个人体内创造一个物体并不是令人发指的罪行。毕竟,我们一直在 create 操作中这样做。

    【讨论】:

      【解决方案2】:

      是的,我同意约翰的观点。请求的概念通常是“控制器事物”,但在这种情况下,您的模型是建模请求,因此在这种情况下它绝对属于模型领域。实际上,一旦请求对象跨越了从控制器到模型的边界,它就只是另一个对象,没有特殊属性:它不再关心获取和响应 html 请求的过程,它只是一个你可以随心所欲地做任何事情的对象。

      不过,需要注意的一点是,在 ruby​​ 中,参数是通过引用传递的。这意味着您在模型中操作的请求对象与控制器中正在处理的请求对象相同。我可能过于偏执(或完全错误),但您可能希望将其副本传递给模型而不是实际请求本身。即

      class LinksController < ApplicationController
        def hit
          link = Link.find(params[:id])
          link.hit!(request.dup)
        end
      end
      

      【讨论】:

      • 很好的答案,但不需要dup request,只要它没有被修改也不应该被修改。
      • 就像我说的,偏执狂 :) 我会担心以后有人(例如我)可能会出现并在模型方法中对请求对象进行一些更改,而不知道后果。但是,是的,不是绝对必要的。
      • 那么您的代码将被dup 调用所淹没。这称为防御性编程。你最好明智地使用freeze
      • Request 上没有任何方法可以修改它,所以这个调用是多余的。
      猜你喜欢
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-22
      • 2018-08-13
      • 1970-01-01
      相关资源
      最近更新 更多