2013-08-29 2 views
-1

Я упростил свой проект, чтобы я мог лучше понять, насколько интересна загрузочная часть RoR 3.2.13. Это мои классы:Rails Eager loading объяснение

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 в массиве people.

Im ожидая что-то вроде этого:

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

что он дал 'Person.first.posts' с' include' в вашей модели? –

+0

@ Rajarshi Das. Конечно, но мне нужен весь массив с сообщениями в каждой позиции массива, включенного в объект person. Мне нужен весь список, а не только один элемент списка. :( –

+0

Яркая загрузка работает. Он получает все сообщения с нетерпением (в одном запросе), не так ли? – Mischa

ответ

1

Вы можете отобразить результаты получить Ожидаемый массив

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

Отличный это сделал. Как я могу выполнить это очиститель или без карты? –

+1

@DavidMauricio, это действительно создает желаемый массив, но действительно ли это то, что вам нужно? Зачем вам этот массив со всеми людьми и сообщениями. Как я пытаюсь объяснить: нетерпевая загрузка * работает *. Просто используйте его так, как он должен был использоваться. – Mischa

+0

Действительно, он работает, как я могу отправить эту структуру в другой контекст и пройти через сообщения, для каждого человека? Это другой вопрос, но он, безусловно, нуждается в интенсивной загрузке внутри одной структуры во внешней области. –

1

Результат запроса рвутся загружает посты как результат метода Person#posts. Я не совсем понимаю формат вывода, который вы ожидаете. Если вам просто нужны два массива, один из людей и один из всех сообщений этих людей, вы можете разделить его на два запроса.

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

Это тот же запрос, выполненный по электронной загрузке, но он будет возвращать сообщения в своем собственном массиве.

+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

yes right ..... он хочет что-то другое, не связанное с нетерпеливой нагрузкой –

+0

можно ли использовать метод 'eager_load'? ..... –

+0

Я пробовал eager_load, но получил такие же результаты, я сделал это вот так: http: // blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html без везения –