在对this question感兴趣之后,我正在研究ActiveRecord如何定义关联属性方法。我注意到在Rails控制台中,如果我有一个Chapter
has_many :videos
的实例,当我将各种参数传递给chapter.videos
时,我会得到以下行为。我试图追踪属性方法在ActiveRecord源代码中的定义方式,但我很难跟进。
> chapter.videos
Video Load (0.5ms) SELECT `videos`.* FROM `videos` ...
=> #<ActiveRecord::Associations::CollectionProxy [videos...]>
第二次打电话似乎缓存/记住了视频
> chapter.videos
=> #<ActiveRecord::Associations::CollectionProxy [videos...]>
传入false没有任何区别,它也使用缓存
> chapter.videos(false)
=> #<ActiveRecord::Associations::CollectionProxy [videos...]>
然而,传入任何真实的总是查询数据库
> chapter.videos(true)
Video Load (0.5ms) SELECT `videos`.* FROM `videos` ...
=> #<ActiveRecord::Associations::CollectionProxy [videos...]>
> chapter.videos(42)
Video Load (0.5ms) SELECT `videos`.* FROM `videos` ...
=> #<ActiveRecord::Associations::CollectionProxy [videos...]>
> chapter.videos("hello")
Video Load (0.5ms) SELECT `videos`.* FROM `videos` ...
=> #<ActiveRecord::Associations::CollectionProxy [videos...]>
ActiveRecord在幕后使用这些参数做什么?有没有人知道源代码在这里发生了什么,以及如何,或者这只是一些Ruby特性,当传入真相时会重新加载缓存属性?
答案 0 :(得分:3)
是的 - 传递一些truthy告诉activerecord重新加载关联缓存。这是在缓存下记录的here。
除非您传递true,否则rails将使用关联的缓存版本(除非您调用始终访问数据库的count
)
值得注意的是,某些方法(例如first
,last
,include?
)永远不会导致加载关联。例如,首先只查询关联的第一项,这不会填充缓存
定义关联访问器方法的位是here。您可以看到它只是委托给关联上的reader
方法。
对于集合关联,这最终会在collection_association.rb中,您可以看到读者的参数称为“force_reload”。那里的代码很有希望直截了当。
对于单数关联,singular_association.rb中有类似的代码
答案 1 :(得分:3)
注意:这在Rails 5中已弃用,将在5.1中删除。现在,您应该使用chapter.videos.reload
而不是chapter.videos(true)
。来自the changelog:
通过传递一个truthy参数来重新强制强制关联重新加载 关联方法。
对于集合关联,您可以在关联代理上调用#reload 强行重装:
@user.posts.reload # Instead of @user.posts(true)
在相关的说明中,在同一个更改日志中:
介绍
Model#reload_<association>
以恢复Article.category(true)
的行为,其中类别是单一关联。#20888中不推荐使用关联阅读器的强制重新加载。不幸的是,
article.reload.category
的建议替代方案不会暴露相同的行为。此补丁添加了一个带有前缀
reload_
的reader方法,用于单数关联。此方法具有与传递给曾经拥有的关联阅读器的真实相同的语义。