ActiveRecord对传递给关联属性方法的参数做了什么?

时间:2014-08-07 17:05:12

标签: ruby-on-rails ruby rails-activerecord

在对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特性,当传入真相时会重新加载缓存属性?

2 个答案:

答案 0 :(得分:3)

是的 - 传递一些truthy告诉activerecord重新加载关联缓存。这是在缓存下记录的here

除非您传递true,否则rails将使用关联的缓存版本(除非您调用始终访问数据库的count

值得注意的是,某些方法(例如firstlastinclude?)永远不会导致加载关联。例如,首先只查询关联的第一项,这不会填充缓存

定义关联访问器方法的位是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方法,用于单数关联。此方法具有与传递给曾经拥有的关联阅读器的真实相同的语义。