3

我知道教条说不要在模型中访问 c​​urrent_user,但我并不完全同意。例如,当通过 rails 回调发生操作时,我想编写一组日志记录函数。或者当一个对象可以有多个人写入它时,简单地写谁写了一个更改(不像消息只有一个所有者)。在许多方面,我将 current_user 更多地视为应用程序的配置 - 换句话说,让这个应用程序响应这个用户。我宁愿通过模型 DSL 进行日志记录,而不是在看起来真的不合适的操作中。我错过了什么?

这个想法似乎相当不雅访问模型中的 current_user

这样做:http ://rails-bestpractices.com/posts/47-fetch-current-user-in-models

谢谢

编辑#1 所以我的问题不是是否有可以进行审计/日志记录的宝石。我目前使用的是 paper_trail (虽然不再使用它,因为我可以在大约 10 行 ruby​​ 代码中完成相同的功能);它更多的是关于是否永远不应该在模型中访问 c​​urrent_user - 我本质上想减少我的控制器代码并将逻辑下推到应该在的模型中。部分原因可能是由于 ActiveRecord 的历史,它本质上是一个围绕数据库表的包装器,RoR 多年来为其添加了很多功能。

4

2 回答 2

1

您已经给出了几个您想要完成的示例,我将分别介绍每个示例的解决方案:

当通过 Rails 回调发生操作时,我想编写一组日志记录函数

取决于您想要记录的方式(数据库与写入记录器)。如果你想记录到数据库,你应该有一个单独的记录模型,它从控制器获得适当的信息,或者简单地使用belongs_to :user类型设置。如果您想写入记录器,您应该在应用程序控制器中创建一个方法,您可以从您的创建和更新方法(或您想要回调的任何其他操作)调用该方法。

或者当一个对象可以有多个人写入它时,简单地写谁写了一个更改

class Foo < ActiveRecord::Base
  belongs_to :user, as: :edited_by
end

class FooController < ApplicationController
  def update
    @foo = Foo.find(params[:id])
    @foo.attributes = params[:foo]
    @foo.edited_by = current_user
  end
end

我认为您误解了 Rails 中的模型的作用。它的范围是数据库。它不能访问current_user的原因,是因为当前用户没有存储在数据库中,它是一个会话变量。这与模型完全无关,因为这是没有浏览器就无法存在的东西。

ActiveRecord::Base 不是一个设计用于浏览器的类,它是与数据库一起工作的东西,而且只与数据库一起工作。您将浏览器用作该模型的接口,但该层需要访问浏览器特定的内容,例如会话变量,因为您的模型正在扩展一个实际上无法这样做的类。

这不是教条或风格选择。这是您的模型所扩展的类的限制的一个事实。这意味着您的选择基本上归结为从其他东西扩展,在控制器层中处理它,或者从控制器层将其传递给模型。在这种情况下,ActiveRecord 不会做你想做的事。

于 2012-08-14T22:47:09.753 回答
0

您显示的两个链接(每个链接都显示相同的方法)与我仍然使用的方法非常相似。我将 current_user 存储在某个地方(实际上线程上下文是最安全的),然后在观察者中,我可以创建一种对观察模型的所有更改的审计日志,并且仍然记录用户。

这是一种非常干净的方法。

另一种更明确、更简洁但更 MVC 的替代方法是让控制器创建审计日志,有效地记录用户的操作,并减少对不同模型的影响。这可能也很有用,在一个网站上我们两者都做了。在控制器中,您知道当前用户,并且您知道操作,但它更冗长。

我相信您担心的是,这个提议的解决方案在某种程度上不够好,或者 MVC 不够,或者......什么?

另一个相关问题:如何在 Rails 中为每个表创建完整的审计日志?

还可以查看经过审核的gem,它也非常干净地解决了这个问题。

希望这可以帮助。

于 2012-08-14T23:05:01.330 回答