AnA*_*ice 46 activerecord ruby-on-rails ruby-on-rails-3
在我的project.rb模型中,我正在尝试使用动态变量创建一个范围:
scope :instanceprojects, lambda {
where("projects.instance_id = ?", current_user.instance_id)
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
undefined local variable or method `current_user' for #<Class:0x102fe3af0>
Run Code Online (Sandbox Code Playgroud)
在控制器中我可以访问的位置current_user.instance_id......模型是否有理由无法访问它以及获取访问权限的方法?此外,这是创建上述范围的正确位置,还是属于控制器?
mdr*_*iel 73
正如你已经指出的那样,这没有多大意义.current_user根本不属于模型逻辑,应该在控制器级别处理.
但你仍然可以创建这样的范围,只需从控制器传递参数:
scope :instanceprojects, lambda { |user|
where("projects.instance_id = ?", user.instance_id)
}
Run Code Online (Sandbox Code Playgroud)
现在你可以在控制器中调用它:
Model.instanceprojects(current_user)
Run Code Online (Sandbox Code Playgroud)
Mic*_*jbe 32
已经接受的答案提供了一种非常正确的方法来实现这一点.
但这是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
Run Code Online (Sandbox Code Playgroud)
这按预期工作,但它可以被认为是脏的,因为我们基本上在这里定义一个全局变量.
Ryan Bates 在这个railscast中提出了一种非常安全的方法来实现这种策略
这是付费剧集(不要向我投票!)但您可以免费浏览源代码
在这里,他创建了一个current_tenant方法,但您可以轻松替换current_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
Run Code Online (Sandbox Code Playgroud)
然后在模型中你可以做类似......
default_scope { where(tenant_id: Tenant.current_id) }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
39926 次 |
| 最近记录: |