标题已经不知道怎么写了, 我想要的是进行一个动作后, 记录下 log. 并且同时记录下是谁进行了这个动作 ( 使用 devise 认证 )
遇到的问题是在 model 里面不能调用 current_user
, 所以无法记录下是谁进行的操作. 按照我的想法. 这种功能应该是实现在 observer 里面的, 但是在 observer 中如何才能确定现在登陆的用户呢..?
用代码来说下这个问题是这样的:
class ProjectObserver < ActiveRecord::Observer
def after_save(proj)
Event.create(
:project => self,
:type => xxx,
:author => current_user #怎么获得这个用户, devise 的 current_user helper 用不了
)
end
end
如果有另外的方法解决这个问题也行...我是觉得这个逻辑不应该放进 controller 里 ( controller 里面可以用 current_user) , 所以把自己卡住了.
有在 model 里取得 current_user 的 hack 方法(http://qichunren.iteye.com/blog/551968),不过我觉得不好。并且有些实现还不是线程安全的。
我比较推荐的使用方法是下面两种:
一般这种 observer 都是和用户相关的,比如你这个例子,用户创建了一个 project,project 一定要有 user_id,在 callback/observer 里就可以直接取这个 user_id,而不是去找 current_user,current_user 的含义是和会话相关的。
class ProjectObserver < ActiveRecord::Observer
def after_save(proj)
Event.create(
:project => self,
:type => xxx,
:author => proj.user
)
end
end
如果你觉得有些时候在 project 这个表里加 user_id 会是冗余的,可以通过虚拟属性还解决,比如 Model 里:
class Project < AR
attr_accessor :user_id
end
Controller 里:
Project.create :user_id => current_user.id, ...
Observer 里:
class ProjectObserver < ActiveRecord::Observer
def after_save(proj)
Event.create(
:project => self,
:type => xxx,
:author => proj.user_id
)
end
end
还有些时候会考虑到性能,其实是不必要的,像这样的主键查询永远也成为不了瓶颈。而且,还有 AR 的 query cache 会帮你挡一下。
@hooopo的方法应该是很优的方法 thread 的方式也许会存在不安全的问题.因为一般的 rails server 的 ruby 进程会一直开着.thread 的变量需要每次都覆盖或使用后清理掉,不然就有可能拿到的上次或上上次的请求的数据.
翻出了旧帖子... @hooopo 的方法不错,不过具体到楼主的这个问题,更合理的方式是在 controller 上做事。 这是一个典型的操作日志的需求,而操作日志是来自用户的行为,放在 model 层进行 observe 是有问题的,比如会多记录一些日志(应该是一次操作一条日志,而不是一次模型变更一条日志)