2009-07-22 51 views
14

說我想在我的控制器中存儲一些變量。我想在一個動作中初始化它,在另一個動作中增加它,並在另一箇中讀取它。只是聲明這個變量@foo不起作用,因爲@foo在創建它的操作被呈現後死亡。
我不希望這個變量存儲在模型中。如何在控制器中的多個操作中存儲實例變量?

有沒有辦法保存這個變量,除了將它存儲在會話中?
看起來好像我已經遇到了這個簡單的問題幾次,我想知道解決它的最好方法。

回答

22

不是。每個對控制器動作的調用都是無狀態的。控制器操作完成後沒有任何東西可用。爲每個請求創建一個新的控制器實例,然後在請求結束時丟棄該實例。

如果您不想將它存儲在會話或數據庫模型中,如果您希望該變量特定於特定會話,則沒有多個選項。

如果是跨所有會話全局的,你可以把它放在一個@@class_variable而非@instance_variable,但是這會導致混亂,一旦你開始有多個Rails進程(每個進程都會有自己的它複印件),或者如果你正在線程安全模式下運行,你可能會遇到討厭的併發錯誤。

我想你可以看看像memcached的,但你仍然需要密鑰的一些USER_ID或其他會話標誌(除非它是全球)

7

你可以利用內置的Rails.cache機制來存儲值,但正如第一個答案中提到的,您必須將其鍵入user_id之類的值。這是一個不錯的方式,因爲您可以使用不同的存儲機制來備份它。你可以看看

Rails.cache.write(:foo) 
# in later action 
Rails.cache.read(:foo) 

的另一件事是閃光的哈希,它提供了一個保持方法,使最後比一個後續請求更多閃光價值。

所以在行動1,你可以創造的價值:

flash[:foo] = some_value 
flash.keep(:foo) 

在行動2,你可以訪問它,並調用如果你想活命更多的後續行動再次保持。

flash[:foo] #use it for something 
flash.keep(:foo) # keep it for another request 

在http請求的上下文中乾淨地執行是件棘手的事情。

+0

緩存是一個好主意,但我認爲如果您有多個Web服務器,則Flash方法將不起作用。 – Scott 2009-07-23 14:19:51

+0

這取決於您的會話存儲,因爲閃存散列實際上存儲在會話中 - 例如,如果會話被禁用,只有flash.now可以運行 – paulthenerd 2009-07-23 17:04:24

1

如果它是一個簡單的計數或字符串,我認爲最好的解決方案是將它存儲在會話中。這樣,如果您使用多個Web服務器,它將在那裏。

你爲什麼反對使用這個會話?

11

我也想知道爲什麼你反對使用會議?如果您不喜歡直接在操作中使用會話,則可以使用篩選器模擬存活的@foo實例變量。這樣的事情可能嗎?

class FooController < ApplicationController 
    before_filter :load_foo 
    after_filter :save_foo 

    private 
    def load_foo 
     @foo = session[:foo] || 0 
    end 

    def save_foo 
     session[:foo] = @foo 
    end 

end 

你的行動將能夠操縱通過@count實例變量的值,這將被自動保存到會話。

1

別擔心,會議不會咬人。

此外,會話可能是這樣做的最佳方式。

相關問題