2009-04-17 43 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中没有这样的语法,但是我希望我错了! :)

希望这使得它更清晰一点,并再次感谢答复。