2010-09-18 50 views
45

在我project.rb模型,我试图创建一个动态变量的作用域:Rails 3设计,current_user不能在模型中访问?

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 ......模型无法访问它并有获取访问权限的方法吗?此外,这是创建上述范围还是属于控制器的合适位置?

回答

71

这没有多大意义,正如您已经指出的那样。 current_user根本不属于模型逻辑,它应该在控制器级别上进行处理。

但你仍然可以创造这样的范围,只是参数从控制器传递给它:

scope :instanceprojects, lambda { |user| 
    where("projects.instance_id = ?", user.instance_id) 
} 

现在,你可以把它叫做控制器:

Model.instanceprojects(current_user) 
+1

太棒了。现在试试 – AnApprentice 2010-09-18 18:48:30

+0

工作很好。谢谢! – AnApprentice 2010-09-18 19:34:10

+7

我称范围'',所以它会很好地阅读。 'Project.of current_user' – romeroabelleira 2012-04-28 12:58:28

27

已经接受的答案提供了一个真正正确的方法来实现这一点

但这里是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 

可正常工作,但它可以被认为是肮脏的,因为我们基本上在这里定义一个全局变量。

+2

谢谢 - 我有一个特定的情况,我真的需要这个,并没有办法传入它。顺便说一句,这段代码有一些错误 - 你应该使用用户。current_user =来自ApplicationController的方法(否则,为什么它),并且它被设置为:current_user,但读者从以下位置读取:user(让我漫天看到它!) – Jords 2012-08-21 03:41:49

+0

感谢您指出这一点。答案已更新。 – 2012-08-21 10:11:04

+0

我已经尝试过这一点,并且完美。但是在我的开发环境中,没有多用户的情况。我仍然在关注线程安全问题的其他答案中的评论。有没有其他人在生产环境中测试过这个?干杯! – 2012-11-13 19:54:20

8

瑞恩·贝茨,勾画出实现这种策略in this railscast

一个非常安全的方式这是一个付费节目(不下来投我!),但你可以browse the source code for free

在这里,他创建了一个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 

然后在模型中,你可以这样做......

default_scope { where(tenant_id: Tenant.current_id) } 
0

您不需要使用范围。如果你已经在模型中设置了适当的关联关系,那么下面的一段代码放在控制器中应该是诀窍:

@projects = current_user.instance.projects