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

at.*_*at. 6 ruby-on-rails devise ruby-on-rails-3 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
Run Code Online (Sandbox Code Playgroud)

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

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

vee*_*vee 10

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

使用此Thread.current[:current_user]方法,您必须进行此调用以设置User每个请求.你已经说过,你不喜欢为每一个只能很少使用的请求设置变量的想法; 你可以选择使用skip_before_filter跳过设置用户或代替放置before_filterApplicationController集它在您需要的控制器current_user.

模块化方法是移动设置created_by_idupdated_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
Run Code Online (Sandbox Code Playgroud)

用户模型:

#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
Run Code Online (Sandbox Code Playgroud)

应用控制器:

#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
Run Code Online (Sandbox Code Playgroud)

示例用法:auditable在其中一个模型中包含模块:

# app/models/foo.rb
class Foo < ActiveRecord::Base
  include Auditable
  ...
end
Run Code Online (Sandbox Code Playgroud)

包括Auditable在关注Foo模型将分配created_by_idupdated_by_idFoo在初始化的情况下让你拥有这些属性初始化之后使用权,他们坚持到foos桌子上的after_save回调.