Ruby-on-rails Rails 3 设计,在模型中无法访问 current_user ?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3742785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails 3 devise, current_user is not accessible in a Model ?
提问by AnApprentice
in my project.rb model, I'm trying to create a scope with a dynamic variable:
在我的 project.rb 模型中,我试图创建一个具有动态变量的范围:
scope :instanceprojects, lambda {
where("projects.instance_id = ?", current_user.instance_id)
}
I get the following error:
我收到以下错误:
undefined local variable or method `current_user' for #<Class:0x102fe3af0>
Where in the controller I can access current_user.instance_id... Is there a reason the model can't access it and a way to get access? Also, is this the right place to create a scope like the above, or does that belong in the controller?
我可以访问控制器中的哪个位置current_user.instance_id......模型无法访问它是否有原因以及获得访问权限的方法?另外,这是创建上述范围的正确位置,还是属于控制器?
回答by mdrozdziel
This doesn't make much sense, as you already pointed. The current_user doesn't belong to model logic at all, it should be handled on the controller level.
正如您已经指出的那样,这没有多大意义。current_user 根本不属于模型逻辑,它应该在控制器级别处理。
But you can still create scope like that, just pass the parameter to it from the controller:
但是你仍然可以像这样创建作用域,只需从控制器传递参数给它:
scope :instanceprojects, lambda { |user|
where("projects.instance_id = ?", user.instance_id)
}
Now you can call it in the controller:
现在你可以在控制器中调用它:
Model.instanceprojects(current_user)
回答by Micha? Szajbe
The already accepted answer provides a really correct way to achieve this.
已经接受的答案提供了一种真正正确的方法来实现这一目标。
But here's the thread-safe version of User.current_usertrick.
但这是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
This works as expected, however it can be considered dirty, because we basically define a global variable here.
这按预期工作,但是它可以被认为是脏的,因为我们在这里基本上定义了一个全局变量。
回答by Mark Locklear
Ryan Bates lays out a pretty safe way to implement this kind of strategy in this railscast
瑞安·贝茨 (Ryan Bates)在这个 railscast 中提出了一种非常安全的方法来实施这种策略
This a paid episode (don't down vote me!) but you can browse the source code for free
这是付费剧集(不要给我投票!)但您可以免费浏览源代码
Here he creates a current_tenantmethod, but you could easily substitute current_userinstead.
在这里,他创建了一个current_tenant方法,但您可以轻松替换current_user。
Here are the key bits of code...
这是代码的关键部分......
#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
Then in the model you can do something like...
然后在模型中,您可以执行以下操作...
default_scope { where(tenant_id: Tenant.current_id) }
回答by sampi
You don't need to use scopes. If you have set the appropriate associations in models, following piece of code placed in controller should do the trick:
您不需要使用范围。如果您在模型中设置了适当的关联,则控制器中的以下代码应该可以解决问题:
@projects = current_user.instance.projects

