我要登录用户的行动,在我的红宝石在轨道上应用程序。

迄今为止,我有一个模型观察员,插入日志之后的数据库的更新和创造。为了存储用户进行的行动记录的,我需要访问的会议,但这是有问题的。

首先,它打破了视模式。第二,技术范围从予以解决了对稀奇古怪的,也许甚至绑执行情况的杂种服务器。

什么是正确的做法?

有帮助吗?

解决方案

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

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

1)违反MVC模式

的可能解决方案是什么?

2) 违反MVC模式

的可能解决方案是什么?

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

让我们先考虑#1。

在我的脑海中,我会想到以下可能的解决方案

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

B)如果你真的不想了解谁创建了一个条目,但是对自己记录网络动作更感兴趣,那么你可以考虑“观察”。控制器动作。我已经用了一段时间来探索Rails源代码,所以我不确定他们的ActiveRecord :: Observer是什么“观察”的。模型,但您可以将其调整为控制器观察者。从这个意义上说,您不再观察模型了,将会话和其他控制器类型的数据信息发送给该观察者是有意义的。 C)最简单的解决方案,具有最少的“结构”,只需在你正在观察的动作方法结束时删除你的记录代码。

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

A)正如您所建议的那样,您可以找到让模型Observer访问Session数据的方法。您已将模型与业务逻辑相结合。

B)在这里想不到任何其他人:)

我个人的倾向,在不知道有关你的项目的任何细节的情况下,是1A,如果我想将人们附加到记录上,或者如果我只有少数几个地方我有兴趣这样做的话。如果您真的想要为所有控制器和操作提供强大的日志记录解决方案,您可以考虑使用1B。

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

其他提示

嗯,这是一个棘手的情况。你几乎要违反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

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

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

你打破MVC是对的。我建议在你的控制器中使用回调,主要是因为有些情况(比如一个调用了save的模型,但验证失败),你不希望观察者记录任何东西。

我找到了一个干净的方法来做我选择的答案所建议的内容。

http://pjkh.com /物品/ 2009/02/02 /创建-一个审计日志功能于导轨

此解决方案使用AuditLog模型和TrackChanges模块为任何模型添加跟踪功能。当您更新或创建时,它仍然需要您向控制器添加一行。

在过去的时候做的事情是这样的,我们往往往延伸的用户模型,以包括思想"当前用户"

看在以前的答案,我看到的建议储存的实际活动的记录用户在本届会议。这有几个缺点。

  • 它存储的一个可能大的对象在会议数据库
  • 这意味着,复制用户是高速缓存'的所有时间(或者直至注销是被迫的).这意味着任何变化的状况,这不会被用户的认可,直到用户登录和日志。这意味着例如,试图禁止的用户将等待他,关闭日志记录和回。这可能是不行你想要的。

因此,在开始一个请求(在一个过滤器)你把user_id自的会议和阅读使用,设置用户。subject.

像这样的东西...

class User
  cattr_accessor :current_user
end

class Application
  before_filter :retrieve_user

  def retrieve_user
    if session[:user_id].nil?
      User.current_user = nil
    else
      User.current_user = User.find(session[:user_id])
    end
  end
end

从那时起,它应该是微不足道的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top