2011-03-04 27 views
5

我正在使用Ruby on Rails 3,並且我正在嘗試使用中間件來設置稍後可在控制器中訪問的變量@variable_name如何在中間件中設置一個可在所有應用程序中訪問的變量?

比如我中間件

class Auth 

    def initialize(app) 
     @app = app 
    end 

    def call(env) 
     @account ||= Account.find(1) 

     @app.call(env) 
    end 
    end 

上面的代碼正確設置@account變量,但在我的應用程序不可用(在控制器,模型,視圖,...)。那麼,我該如何做到這一點?


我看到this answer這是一個辦法做到我需要什麼,但我想有@account變量「直接訪問」。也就是說,不使用這種方式,但使提供的內容,例如在我的意見,像這樣:

<%= debug @account %> 
+1

我不認爲這可以在中間件中完成。你在'ApplicationController'中用'before_filter:set_my_var'試了一下嗎? – Wukerplank 2011-03-04 10:05:39

+0

@Wukerplank我需要在中間件。 – user502052 2011-03-04 10:06:36

+1

你可以嘗試一些骯髒和可能有害的東西,比如將它存儲在'Thread.current [:my_var] = Account.find(1)'中。 – Wukerplank 2011-03-04 10:16:13

回答

15

您可以使用 'ENV' 來表示。因此,在您的中間件你這樣做:

def call(env) 
    env['account'] = Account.find(1) 
    @app.call(env) 
end 

你可以在你的應用程序中使用「請求」獲得的價值:

request.env['account'] 

請不要使用全局變量或類屬性像某些人在這裏建議。這是一個讓你陷入困境並確實是一個壞習慣的好方法。

+0

謝謝你的回答。在你回答之後,我立即想起了omniauth,它使用了相同的做法。另外我注意到,你可以從路由約束中做同樣的事情(在我的情況下,對數據庫的請求數減少特別有用)......你可以將任何值傳遞給request.env並在動作中捕獲它或控制器。 – 2011-08-10 12:24:59

1

我不知道這是否可以用Middelware來完成。我的建議是這樣的:

class ApplicationController < ActionController::Base 

    protect_from_forgery 

    before_filter :set_my_var 

private 
    def set_my_var 
    @account ||= Account.find(1) 
    end 

end 

這樣所有的控制器和視圖訪問@account

+0

這種方法存在的一個問題是,當你計算中間件本身的任務時,需要進行分配。 – Ashish 2011-03-04 10:14:30

-4

你可以有一個cattr_accessor:my_var任何模型和

 
    MyModel.my_var = 'something' 
設置從中間件這個變量

而且你可以在應用程序的任何地方訪問它。

+0

我聽不懂。你能舉一個真實的例子嗎? – user502052 2011-03-04 10:18:57

+0

在模型文件的某處添加「cattr_accessor:my_var」。這爲MyModel.my_var創建了一個setter和getter:http://pastie.org/2345283 – 2011-08-09 14:57:47

+1

非線程安全,甚至不是主要問題的答案,如何將變量從中間件傳遞給控制器​​操作。 – 2011-08-09 21:24:31

-5

您是否嘗試過創建Ruby全局變量?

def call(env) 
    $account ||= Account.find(1) 

    @app.call(env) 
end 

<%= debug $account %> 
+1

在100個案例中,全局變量不是答案。 – 2015-02-26 10:48:29

相關問題