Rails 3的devise,current_user不能在模型中访问?
在我的project.rb模型中,我试图创build一个dynamicvariables的作用域:
scope :instanceprojects, lambda { where("projects.instance_id = ?", current_user.instance_id) }
我得到以下错误:
undefined local variable or method `current_user' for #<Class:0x102fe3af0>
在控制器中,我可以访问current_user.instance_id
…有没有原因模型无法访问它,并获得访问的方式? 此外,这是创build一个像上面的范围,还是属于控制器的正确的地方?
正如你已经指出的那样,这没有什么意义。 current_user根本不属于模型逻辑,应该在控制器级别上进行处理。
但是您仍然可以创build这样的范围,只需从控制器传递参数即可:
scope :instanceprojects, lambda { |user| where("projects.instance_id = ?", user.instance_id) }
现在你可以在控制器中调用它:
Model.instanceprojects(current_user)
已经接受的答案提供了一个非常正确的方法来实现这一点。
但是这里是User.current_user
技巧的线程安全版本。
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
这个按预期工作,但是可以被认为是肮脏的,因为我们在这里基本上定义了一个全局variables。
瑞安·贝茨(Ryan Bates) 在这个railscast中提出了一个非常安全的方法来实现这种策略
这是一个付费插曲(不投票给我!),但你可以免费浏览源代码
在这里他创build了一个current_tenant
方法,但是您可以轻松replacecurrent_user
。
这里是代码的关键位…
#application_controller.rb around_filter :scope_current_tenant private def current_tenant Tenant.find_by_subdomain! request.subdomain end helper_method :current_tenant def scope_current_tenant Tenant.current_id = current_tenant.id yield ensure Tenant.current_id = nil end #models/tenant.rb def self.current_id=(id) Thread.current[:tenant_id] = id end def self.current_id Thread.current[:tenant_id] end
那么在模型中,你可以做一些像…
default_scope { where(tenant_id: Tenant.current_id) }
你不需要使用范围。 如果你已经在模型中设置了适当的关联,那么在控制器中放置一段代码就可以做到这一点:
@projects = current_user.instance.projects