是不是在观察者中访问会话?

Jar*_*ryl 7 ruby session logging ruby-on-rails observers

我想在Ruby on Rails应用程序中记录用户的操作.

到目前为止,我有一个模型观察器,它在更新和创建后将日志插入数据库.为了存储哪个用户执行了记录的操作,我需要访问会话,但这是有问题的.

首先,它打破了MVC模型.其次,技术范围从hackish到outlandish,甚至可能甚至将实现绑定到Mongrel服务器.

什么是正确的方法?

Ori*_*rds 6

嗯,这是一个棘手的情况.你几乎必须违反MVC才能让它运行良好.

我会做这样的事情:

class MyObserverClass < ActiveRecord::Observer
  cattr_accessor :current_user # GLOBAL VARIABLE. RELIES ON RAILS BEING SINGLE THREADED

  # other logging code goes here
end

class ApplicationController
  before_filter :set_current_user_for_observer

  def set_current_user_for_observer
    MyObserverClass.current_user = session[:user]
  end
end
Run Code Online (Sandbox Code Playgroud)

它有点hacky,但它并不比我见过的许多其他核心轨道更糟糕.

所有你需要做的就是使它成为线程安全的(这只在你运行jruby时才有意义)是将cattr_accessor改为一个合适的方法,并让它将它的数据存储在线程本地存储中

  • 嗨猎户座,刚刚发现这个,因为我正在寻找这种类型的解决方案.已经有几年了!你还在用这个解决方案吗?好奇如果遇到任何Threaded类型的问题? (2认同)

Mat*_*att 3

我觉得这是一个非常有趣的问题。我要在这里大声思考一下......

最终,我们面临的是为了实现一组特定的功能而违反设计模式可接受的实践的决定。所以,我们必须问自己

1)有哪些可能的解决方案不会违反MVC模式

2)有哪些可能违反MVC模式的解决方案

3)哪个选项最好?我认为设计模式和标准实践非常重要,但同时如果坚持它们会使您的代码变得更加复杂,那么正确的解决方案很可能是违反实践。有些人可能不同意我的观点。

让我们首先考虑#1。

我突然想到以下可能的解决方案

A)如果您真的对谁在执行这些操作感兴趣,那么这些数据是否应该以任何方式存储在模型中?它将向您的观察者提供此信息。这也意味着 ActiveRecord 类的任何其他前端调用者都可以获得相同的功能。

B) 如果您并不是真正有兴趣了解谁创建了条目,而是对记录 Web 操作本身更感兴趣,那么您可能会考虑“观察”控制器操作。自从我研究 Rails 源代码以来已经有一段时间了,所以我不确定他们的 ActiveRecord::Observer “观察”模型是谁,但您也许能够将其调整为控制器观察者。从这个意义上说,您不再观察模型,并且向该观察者提供会话和其他控制器类型数据信息是有意义的。C) 最简单的解决方案,具有最少的“结构”,就是简单地将日志代码放在您正在观看的操作方法的末尾。

现在考虑选项#2,打破 MVC 实践。

A)正如您所建议的,您可以找到让模型观察者访问会话数据的方法。您已将模型与业务逻辑耦合起来。

B)这里想不出其他的了:)

在不了解有关您的项目的更多详细信息的情况下,我个人的倾向是要么是 1A(如果我想将人员附加到记录),要么是 1C(如果只有少数地方我对此感兴趣)。如果您确实想要为所有控制器和操作提供强大的日志记录解决方案,您可以考虑 1B。

让模型观察者找到会话数据有点“臭”,如果您尝试在任何其他项目/情况/上下文中使用您的模型,则可能会中断。