Rails渴望加载解释

时间:2013-08-29 04:37:52

标签: ruby-on-rails ruby

我已经简化了我的项目,所以我可以理解RoR 3.2.13的热切加载部分。这些是我的课程:

class Person < ActiveRecord::Base
  attr_accessible :name
  has_many :posts
end

class Post < ActiveRecord::Base
  attr_accessible :name, :person_id
  belongs_to :person
end

当我做

之类的事情
people_data = Person.includes(:posts)

IRB显示以下SQL:

Person Load (1.3ms)  SELECT `people`.* FROM `people` 
Post Load (0.7ms)  SELECT `posts`.* FROM `posts` WHERE `posts`.`person_id` IN (1, 2)

结果对象如下:

=> [#<Person id: 1, name: "Ernie">, #<Person id: 2, name: "Bert">] 

请注意,只有2个人对象,没有帖子。如何通过人员及其帖子获得简单的数据结构。我想在一条指令中做到这一点,我不想在人员阵列中做一个foreach。

我期待这样的事情:

[#<Person id: 1, name: "Ernie">, [#<Array 0 => #<Post id:1, name: "Hi">, 1 => #<Post id:2, name: "Hello"> > ....

3 个答案:

答案 0 :(得分:3)

Eager loading 正在运作。它正在急切地检索所有帖子(在一个查询中)。急切加载构建包含所有帖子和人员的数组。

# With eager loading
people_data = Person.includes(:posts) # 2 queries: 1 for persons, 1 for posts
people_data.first.posts.each do |post|
  # No queries
end

# Without eager loading
people_data = Person.all # 1 query for persons
people_data.first.posts.each do |post|
  # Query for each post
end

请注意,在这两种情况下,people_data都将包含(看起来类似的)ActiveRecord::Relation对象。 (它不是数组!)当您开始使用相关记录时,您只会看到热切加载的好处。

除非你有特殊的理由想要建立一个包含所有人和帖子的数组,否则你应该像使用它一样使用预先加载。这比尝试构建自己的数组更有效。

答案 1 :(得分:1)

您的查询结果急切地加载帖子作为Person#posts方法的结果。我不太清楚你期望的输出格式。如果你只想要两个人,一个人和一个人,你可以把它分成两个查询。

@people = Person.where(...)
@posts = Post.where(person_id: @people)

这是通过急切加载完成的相同查询,但它将返回自己数组中的帖子。

答案 2 :(得分:1)

您可以将结果映射到接收预期的数组

Person.includes(:posts).all.map{|person| [person, person.posts]}