2010-09-18 32 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