【问题标题】:What does ActiveRecord do with arguments passed in to association attribute methods?ActiveRecord 对传递给关联属性方法的参数做了什么?
【发布时间】:2014-08-07 17:05:11
【问题描述】:

在对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 功能,当传入一些真实的东西时会重新加载缓存的属性?

【问题讨论】:

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


    【解决方案1】:

    注意:这在 Rails 5 中已弃用,将在 5.1 中删除。现在您应该使用chapter.videos.reload 而不是chapter.videos(true)。来自the changelog

    通过传递一个真实的参数来弃用强制关联重新加载 关联方法。

    对于集合关联,您可以在关联代理上调用#reload 强制重新加载:

    @user.posts.reload   # Instead of @user.posts(true)
    

    在相关说明中,在同一个变更日志中:

    引入Model#reload_&lt;association&gt; 以恢复Article.category(true) 的行为,其中类别是单一关联。

    关联阅读器的强制重新加载已在 #20888 中弃用。不幸的是,article.reload.category 的建议替代方案没有公开相同的行为。

    此补丁添加了一个带有前缀reload_ 的读取器方法,用于单数关联。此方法与将 true 传递给过去的关联读取器具有相同的语义。

    【讨论】:

    • 有一个 gem 重新引入了用于强制重新加载关联的基于参数的语法,称为 rails-force-reload
    【解决方案2】:

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

    除非您传递 true,否则 rails 将使用关联的缓存版本(除非您调用 count,它总是命中数据库)

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

    定义关联访问器方法的位是here。您可以看到它只是委托给关联上的reader 方法。

    对于集合关联,这最终会出现在collection_association.rb 中,您可以在其中看到给读者的参数称为“force_reload”。那里的代码希望很简单。

    对于奇异关联,singular_association.rb 中有类似的代码

    【讨论】:

      猜你喜欢
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 1970-01-01
      • 2021-02-05
      • 1970-01-01
      相关资源
      最近更新 更多