如何在Rails中的ActiveRecord回调中获取Devise的current_user?

时间:2014-01-02 10:46:27

标签: ruby-on-rails ruby-on-rails-3 devise ruby-on-rails-3.2 ruby-on-rails-4

我正在使用Devise和Rails 3.2.16。我想自动插入创建记录的人和更新记录的人。所以我在模特中有这样的东西:

before_create :insert_created_by
before_update :insert_updated_by

private
def insert_created_by
  self.created_by_id = current_user.id
end
def insert_updated_by
  self.updated_by_id = current_user.id
end

问题是我收到错误undefined local variable or method 'current_user',因为current_user在回调中不可见。如何自动插入创建和更新此记录的人员?

如果在Rails 4.x中有一个简单的方法,我将进行迁移。

3 个答案:

答案 0 :(得分:10)

编辑@HarsHarl的答案可能更有意义,因为这个答案非常相似。

使用Thread.current[:current_user]方法,您必须进行此调用才能为每个请求设置User。你已经说过,你不喜欢为每一个只能很少使用的请求设置变量的想法;您可以选择使用skip_before_filter来跳过设置用户,或者将before_filter放在ApplicationController中,而不是将current_user设置在您需要created_by_id的控制器中。

模块化方法是将updated_by_id# app/models/concerns/auditable.rb module Auditable extend ActiveSupport::Concern included do # Assigns created_by_id and updated_by_id upon included Class initialization after_initialize :add_created_by_and_updated_by # Updates updated_by_id for the current instance after_save :update_updated_by end private def add_created_by_and_updated_by self.created_by_id ||= User.current.id if User.current self.updated_by_id ||= User.current.id if User.current end # Updates current instance's updated_by_id if current_user is not nil and is not destroyed. def update_updated_by self.updated_by_id = User.current.id if User.current and not destroyed? end end 的设置移至关注点并将其包含在您需要使用的模型中。

可审核模块:

#app/models/user.rb
class User < ActiveRecord::Base
  ...

  def self.current=(user)
    Thread.current[:current_user] = user
  end

  def self.current
    Thread.current[:current_user]
  end
  ...
end

用户模型:

#app/controllers/application_controller

class ApplicationController < ActionController::Base
  ...
  before_filter :authenticate_user!, :set_current_user

  private

  def set_current_user
    User.current = current_user
  end
end

应用程序控制器:

auditable

示例用法:在其中一个模型中包含# app/models/foo.rb class Foo < ActiveRecord::Base include Auditable ... end 模块:

Auditable

Foo模型中包含created_by_id关注点会在初始化时将updated_by_idFoo分配给foos的实例,因此您可以在以后使用这些属性初始化,它们被持久存储在after_save回调的{{1}}表中。

答案 1 :(得分:2)

另一种方法就是这个

class User
class << self
  def current_user=(user)
    Thread.current[:current_user] = user
  end

  def current_user
    Thread.current[:current_user]
  end
end
end

class ApplicationController
  before_filter :set_current_user

  def set_current_user
    User.current_user = current_user
  end
end

答案 2 :(得分:1)

无法从Rails中的模型文件中访问current_user,只能访问控制器,视图和帮助程序。虽然,通过类变量你可以实现,但这不是好方法,所以你可以在他的模型中创建两个方法。当从控制器创建动作调用时,然后将当前用户和字段名称发送到该模型ex:

Contoller code
def create
  your code goes here and after save then write
  @model_instance.insert_created_by(current_user)
end

并在模型中编写此方法

def self.insert_created_by(user)
  update_attributes(created_by_id: user.id)
end

其他方法相同