在我当前的 Rails 应用程序中,我将大量数据从数据库中提取到内存中,以便我可以启动一个长时间运行的后台任务,我不想每 5 秒访问一次数据库。
这一切都很好,但我有一些不雅的代码,如果可能的话,我想去掉它们。
例如,我有一个用户模型,并且用户模型可以以联系人的形式链接到其他用户模型,而联系人又可以链接回第一个用户模型,依此类推。建模如下(感谢 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]
现在我可以得到用户 a 的名字(以一种复杂的、迂回的、从未在现实世界中使用的方式)
user_a_name = user_b_contacts.first.name
=> "Jamie"
到目前为止,一切都很好。现在我更改用户 a 的名称
user_a.name = "Sandy"
=> "Sandy"
如果像以前一样从数据库中再次访问用户 a 的名称,我会得到
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 是预先加载的用户对象列表)。有没有办法可以更新预先加载的用户对象?
请注意: -
a)我正在使用以下内容进行急切加载
User.find(:all, :include => [ {:contact_records => :contacts] } ])
b) 显然这不是我正在使用的实际代码,但为了显示该代码,会有更多的解释和说明,我想我已经让你厌烦了!相信我,我使用的真实示例确实需要这种结构才能正常工作,尽管看起来很奇怪!;)
c) 我可能在重构示例时引入了拼写错误和错误,但请忽略这些。我只需要知道是否可以在不访问数据库的情况下重新加载热切的用户。
提前谢谢了!
更新:如下所述,模型数据在流程运行结束之前不会保存到数据库中,因此重新加载将不起作用,因为数据库中的数据不会改变。