-1

我已经将我的项目简化为这样,所以我可以更好地理解 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 个人员对象,没有帖子。我怎样才能得到一个简单的数据结构,其中包含人员及其帖子。我想在一条指令中执行此操作,我不想在 people 数组中执行 foreach。

我期待这样的事情:

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

3 回答 3

3

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

# 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对象。(它不是一个数组!)当您开始使用相关记录时,您只会看到预先加载的好处。

除非您有特殊原因想要构建一个包含所有人员和帖子的数组,否则您应该像使用它一样使用急切加载。这比尝试构建自己的阵列更有效。

于 2013-08-29T05:01:23.700 回答
1

您的查询结果急切地加载帖子作为该Person#posts方法的结果。我不太清楚您期望的输出格式。如果您只想要两个数组,一个是人员,一个是这些人的所有帖子,您可以将其拆分为两个查询。

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

这与通过预先加载完成的查询相同,但它将以自己的数组返回帖子。

于 2013-08-29T04:57:41.600 回答
1

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

Person.includes(:posts).all.map{|person| [person, person.posts]}
于 2013-08-29T04:57:52.973 回答