2009-04-17 68 views
2

在我當前的rails應用程序中,我將很多數據從數據庫拉入內存,這樣我就可以開始一個長時間運行的後臺任務,我不希望每次都訪問數據庫5秒。更新內存中的急切加載的關聯

這一切都很好,但我有一些不雅的代碼,如果可能,我想擺脫它。

舉個例子,我有這樣的情況,我有一個用戶模型,並且用戶模型可以以聯繫人的形式鏈接到其他用戶模型,而這又可以鏈接回到第一個用戶模型等等。這是仿照如下(感謝米蘭Novota他早些時候的幫助): -

class User < ActiveRecord::Base 
    has_many :contact_records, :foreign_key => :owner_id 
    has_many :contacts, :through => :contact_records, :class_name => "User" 
end 

class ContactRecord < ActiveRecord::Base 
    belongs_to :owner, :class_name => "User" 
    belongs_to :user 
end 

所以,現在我可以輸入

user_a_contacts = user_a.contact_records 
=> [user_b, user_c] 

,並得到所有用戶的聯繫人。現在,讓我們說,我想通過用戶的用戶B的聯繫人(想不出我爲什麼會這樣做,但它只是一個例子!)

user_b_contacts = user_a_contacts.first.contact_records 
=> [user_a, user_c] 

現在,我可以得到用戶的名稱(在一個令人費解的,迂迴的,從來沒有使用現實世界的方式)

user_a_name = user_b_contacts.first.name 
=> "Jamie" 

到目前爲止,這麼好。現在我改變用戶名

user_a.name = "Sandy" 
=> "Sandy" 

如果從數據庫中之前再次訪問用戶的名字,我得到

user_a_name = user_b_contacts.first.name 
=> "Sandy" 

但是,如果我急於加載並在內存中保留了這個值,我得到

user_a_name = user_b_contacts.first.name 
=> "Jamie" 

但這樣做以下給我正確的答案

user_a.name 
=> "Sandy" 

相當明顯,急切加載是爲原始用戶和從ContactRecord對象加載的那些用戶創建不同的用戶對象。

所以,(終於!)我的問題是這樣的: -

此刻,我圍繞着這一使用

@users.each.detect{|user| user == user_b_contacts.first} 

(其中@users是用戶對象的渴望加載列表bodged )。有沒有一種方法可以更新已加載的用戶對象?

請注意: -

一)我用下面

User.find(:all, :include => [ {:contact_records => :contacts] } ]) 

b渴望加載)顯然,這不是說我與工作實際的代碼,但就不會有更解釋和說明,以顯示代碼,我覺得我已經無聊了!相信我,我正在使用的真實例子需要這種結構才能正常工作,就像它看起來那樣怪異!;)

c)我可能在重建示例時引入了錯別字和錯誤,但請忽略這些錯誤。我需要知道的是,是否可以重新加載渴望的用戶而不碰到數據庫。

非常感謝提前!

更新:如下所述,模型數據將不會保存到數據庫,直到流程結束時纔會重新加載,因爲數據庫中的數據不會改變。

回答

4

好的。我將把你的問題壓縮成一個新問題並回答那個問題。如果我誤解了,請原諒我,這不是你要問的。

問題

如果user是我已加載的關聯contacts提前與User.first(:include => :contacts) ActiveRecord模型,我怎麼刷新contacts協會,當它在數據庫中有哪些變化?

回答

您可以用兩種方法,我知道的無效的關聯緩存。首先你可以這樣做:

user.reload 

這將從頭重新加載整個用戶模型。一個稍微不那麼激烈的方式來做到這一點是做

user.clear_association_cache 

,不會重新加載所有的user,但會清除緩存關聯。

無論哪種方式,下一次你做user.contacts它會從數據庫重新加載它們。

0

非常感謝您的回覆,丹尼爾。雖然你沒有得到正確的問題,但你讓我意識到我錯過了一個關鍵點!數據庫記錄將不會更新,因爲我沒有保存!在任何時候。

我正在做的要點是將模型數據拉出到實例變量中,以加快後臺進程。因此,第一次加載的數據將不會保存回數據庫,直到進程運行結束。

我所希望的是一種可以在急切加載時指定一列的值與已加載的另一模型相關的方法。

例如,

User.find(:all, :include => [ {:contact_records => (:contacts as User)] } ]) 

或相似。

據我所知在Rails中沒有這樣的語法,但是我希望我錯了! :)

希望這使得它更清晰一點,並再次感謝答覆。