在我目前的rails应用程序中,我将大量数据从数据库中提取到内存中,这样我就可以开始一个长时间运行的后台任务,我不想每5秒就打一次数据库。
这一切都很好但我有一些不太优雅的代码,如果可能我想摆脱它。
举个例子,我的情况是我有一个User模型,User模型可以以Contacts的形式链接到其他User模型,而后者又可以链接回第一个User模型,依此类推。这模仿如下(感谢Milan 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]
并获取用户a的所有联系人。现在让我们说我希望通过用户a获取用户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"
显然,热切加载是为原始用户创建不同的User对象,以及从ContactRecord对象中加载的用户对象。
所以(终于!)我的问题是: -
目前,我已经使用
来解决这个问题@users.each.detect{|user| user == user_b_contacts.first}
(其中@users是用户对象的急切加载列表)。有没有办法可以更新急切加载的用户对象?
请注意: -
a)我正急着使用以下
加载User.find(:all, :include => [ {:contact_records => :contacts] } ])
b)显然这不是我正在使用的实际代码,但为了展示代码会有更多的解释和说明,我觉得我已经厌倦了你!相信我使用DOES的真实示例需要这种结构才能正常工作,尽管看起来很奇怪! ;)
c)我可能在重构示例时引入了拼写错误和错误,但请忽略它们。我需要知道的是,是否可以在不命中数据库的情况下重新加载热切的用户。
非常感谢提前!
更新:如下所述,在流程运行结束之前,模型数据不会保存到数据库中,因此重新加载将无法正常工作,因为数据库中的数据不会发生变化。
答案 0 :(得分:4)
行。我将把你的问题浓缩成一个新问题并回答那个问题。如果我误解了,请原谅我,这不是你要问的。
<强>问题强>
如果
user
是一个ActiveRecord模型,我在contacts
之前加载了User.first(:include => :contacts)
关联,那么当contacts
关联更改时,如何刷新user.reload
关联数据库?
<强>答案强>
您可以通过我所知的两种方式使关联缓存无效。首先你可以做到:
user.clear_association_cache
将从头开始重新加载整个用户模型。一个稍微不那么激烈的方法是做
user
不会重新加载所有user.contacts
,但会清除缓存的关联。
无论哪种方式,下次执行{{1}}时,都会从数据库中重新加载它们。
答案 1 :(得分:0)
非常感谢你的回复,丹尼尔。虽然你没有得到正确的问题,但你让我意识到我错过了一个关键点!数据库记录不会更新,因为我没有保存!在任何时候。
我正在做的主要是将模型数据拉出到实例变量中,以加快后台进程。因此,在流程运行结束之前,第一次加载的数据将不会保存回数据库。
我希望的是一种方法,您可以在急切加载时指定一列的值与已加载的另一个模型相关。
例如,
User.find(:all, :include => [ {:contact_records => (:contacts as User)] } ])
或类似的。
据我所知,Rails中没有这样的语法,但是我希望我错了! :)
希望这会让它更清晰一些,再次感谢你的回复。