3

我正在使用 Devise 对用户进行身份验证。我需要根据我所有表中的 global_location_id 列显示/隐藏数据。当前 global_location_id 的值将来自 current_user.global_location_id。我尝试将以下默认范围添加到我的一个模型中:

class Artifact < ActiveRecord::Base
default_scope where(:global_location_id => current_user.global_location_id)

但它给出了以下错误:

undefined local variable or method `current_user' for #<Class:0x8721840>

为了规避 current_user 在模型中的不可用性,我在我的应用程序控制器中添加了以下内容

class ApplicationController < ActionController::Base
   def set_global_location_id
    @global_location_id = current_user.global_location_id
   end

并从我的控制器调用该方法

class ArtifactsController < ApplicationController
   #Check to see if the user is logged in first
   before_filter :authenticate_user!
   before_filter :set_global_location_id

更改模型中的默认范围以添加 @global_location_id

class Artifact < ActiveRecord::Base
  default_scope where(:global_location_id => @global_location_id)

但这也不起作用。@global_location_id 已在应用程序控制器中正确设置。但它在模型中是空的。如何使它工作。

4

1 回答 1

3

不幸的是,您将无法与模型实例共享控制器中设置的实例变量(没有一些线程黑客)。这实际上是一件好事,因为否则它会像一个全局变量一样,这会给你带来更多的伤害而不是好处。

我实际上很难理解你为什么要这样做,因为它会在当前登录用户的状态和你的模型之间增加一些令人讨厌的耦合。如果您尝试在控制台中查找 Artifact,则 current_user 不存在,并且该实例变量将不可用,因此您会遇到一些严重的问题。

这是你退后一步,问问自己你真正想要做什么的时候。是否有任何理由需要根据当前用户的 global_location_id 隐式创建 default_scope?您可以只创建一个常规范围并在您的控制器中使用它吗?

class Artifact < ActiveRecord::Base
  scope :by_global_location_id, lambda {|id| where(:global_location_id => id) }
end

class ArtifactsController < ApplicationController
  def index
    @artifacts = Artifact.by_global_location_id(current_user.global_location_id)
  end
end

这种方法的一个好处是阅读您的代码的人不必花费大量时间来跟踪 default_scope 是如何工作的。

于 2012-12-20T02:03:07.850 回答