2010-07-06 58 views
1

我正在尝试为我的rails应用程序进行日志记录,并且在rails中使用哲学时遇到了一些困境。我的应用程序有Link模型,has_manyHit S:Rails中的关注点困境的分离

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,引用,用户代理等)的数据,所以我需要传递请求对象到模型,但我认为这不符合“分离关注”和模糊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 

虽然后一种情况下,使测试更容易(我并不需要模拟模型请求规格) - 它看起来不正确。

对此有任何意见 - 非常感谢。

P.S.方法被放置在需要的地方。它返回Hit对象所需属性的散列。

回答

2

就我个人而言,我会过于担心这些事情太多。

命中的概念与网站或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 
+0

好的答案,但不需要'重复'请求'只要它没有被修改,它不应该。 – PhilT 2016-03-18 16:49:28

+0

就像我说的,偏执狂:)我担心有人(例如我)可能会迟一些来,并对模型方法内的请求对象进行一些更改,而不会意识到后果。但是,不是绝对必要的。 – 2016-03-18 16:51:00

+1

然后你的代码就会被'dup'调用所抛弃。这被称为防御性编程。你最好明智地使用'freeze' – PhilT 2016-03-18 16:54:57