【问题标题】:How to get Devise's current_user in ActiveRecord callback in Rails?如何在 Rails 的 ActiveRecord 回调中获取 Devise 的 current_user?
【发布时间】:2014-01-02 10:46:26
【问题描述】:

我正在使用 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 中有一种简单的方法,我会进行迁移。

【问题讨论】:

  • @vee,我可以使用另一种机制来自动更新created_by_idupdated_by_id 属性吗?
  • 我做了类似于 HarsHarl 建议的事情,即Thread.current。如果你愿意走那条路,我可以给出答案。
  • @vee,我很想看看你的建议
  • at.,按承诺交付:)。

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


【解决方案1】:

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

使用Thread.current[:current_user] 方法,您必须进行此调用才能为每个请求设置User。您说过您不喜欢为每个很少使用的请求设置一个变量的想法;您可以选择使用skip_before_filter 来跳过设置用户,或者不将before_filter 放在ApplicationController 中,而是将其设置在您需要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

用户模型:

#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

Foo 模型中包含Auditable 关注点将在初始化时将created_by_idupdated_by_id 分配给Foo 的实例,因此您可以在初始化后立即使用这些属性,并将它们持久化到@987654340 @table 上的 after_save 回调。

【讨论】:

  • after_save 销毁对象时调用回调?
  • @at。我复习了两次答案,没有看到任何地方暗示当对象被销毁时会调用after_save 回调。 after_save 仅应在对象为 createdupdated 时调用。
  • 在您的 auditable.rb 列表中,最后一行倒数第 3 行您写道:` 并且未销毁?. That would always be true since the update_updated_by` 销毁时不会调用回调。对吗?
  • @at.,哦,那是处理实例它deleted使用foo.delete的情况。尽管它已从数据库中删除,但实例仍然可用;虽然它被冻结但可用。如果您在控制台中执行foo = Foo.create(...) 然后foo.delete 然后foo,您将看到已删除的实例foo 仍然可用。
  • 感谢@vee 的出色解决方案!
【解决方案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

【讨论】:

  • 这似乎更好,但我想我不喜欢为每个很少使用的单个请求设置一个变量的想法。
【解决方案3】:

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

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

其他方法相同

【讨论】:

  • 很遗憾,因为这样做,您将记录写入两次而不是一次......
  • 我不确定我是否理解这一点。它不会自动设置create_by_id。我还不如简单的在create方法中添加那个属性,不需要类方法。
  • 是的,我同意,您可以将其添加到简单的创建时间,无需创建单独的方法。但我只是根据您的问题给出答复。同样在您上面的代码中,如果您使用这种方法,则无需回调。
  • 这是错误的 def self.insert_created_by(user) update_attributes(created_by_id: user.id) end 映射类而不是类的实例,以便更新哪个记录。再想想
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多