CollectionAssociation.include?检查数据库中是否存在记录?

时间:2012-09-06 07:23:57

标签: ruby-on-rails activerecord

我一直在阅读Rails 3 Way并正在检查CollectionAssociation.include?

的行为

根据书中的描述:

  

检查关联中是否存在提供的记录   集合,它仍然存在于底层数据库中   表

我做了几个测试来检查DB是否已经过检查,但看起来它没有检查。

> book = Book.first
=> #<Book id: 1, title: "Programming Ruby"...
> last_chapter = book.chapters.last
=> #<Chapter id: 2, title: "Chapter 2", book_id: 1, 
> b.chapters.include?(last_chapter)
=> true 
> last_chapter.destroy
  DELETE FROM "chapters" WHERE "chapters"."id" = ?  [["id", 2]]
=> #<Chapter id: 2, title: "Chapter 2", book_id: 1, 
> b.chapters.include?(last_chapter)
=> true         
> book.chapters.reload
=> [#<Chapter id: 1, title: "Chapter 1", book_id: 1,...]
> b.chapters.include?(last_chapter)
=> false 

我检查了源代码并找到了一行load_target if options[:finder_sql],它似乎有条件地加载了记录。

您是否知道何时访问DB以检查DB中是否存在记录?

1 个答案:

答案 0 :(得分:1)

Rails使用延迟加载和memoization。

这意味着b.chapters在您第一次调用getter之前不会加载任何章节。

之后,由于记忆,销毁章节不会改变include?测试。 Rails不会重新加载本书中的章节。因此,它不会知道书中不再存在这一章。

请注意,include?(在Enumerable / Array个对象上定义,但未直接在ActiveRelation对象上实现)将自动导致Rails强制转换{{1}对象ActiveRelation到数组。因此,book.chapters将首先获取章节数组,然后检查该章节是否包含在数组中。

显式调用include?(在任何reload对象上)强制rails重新加载该特定对象,以便丢弃书中章节的缓存,并重新加载实际章节。 / p>

  • 您无法关闭备忘录,只需在需要重新加载的地方调用ActiveRecord即可。
  • 你可以使用reload告诉Rails急切加载而不是延迟加载,例如。 includes。这意味着Rails将在加载书籍的同时加载所有章节。

要删除章节,同时确保book = Book.includes(:chapters).first是最新的,您可以致电book.chaptersbooks.chapters.delete(book.chapters.last)。使用此方法,Rails不需要再次查询数据库以确定它不再在集合中。