Стремительная загрузка ассоциаций на экземпляры ActiveModel в Rails - PullRequest
12 голосов
/ 18 декабря 2011

В RoR для новых людей довольно распространенной ошибкой является загрузка класса и подобных атак # решение для активной загрузки

# The bellow generates an insane amount of queries
# post has many comments
# If you have 10 posts with 5 comments each
# this will run 11 queries 
posts = Post.find(:all)
posts.each do |post|
  post.comments
end

Решение довольно простое для загрузки

# should be 2 queries
# no matter how many posts you have
posts = Post.find(:all, :include => :comments) # runs a query to get all the comments for all the posts
posts.each do |post|
  post.comments # runs a query to get the comments for that post
end

Но что, если у вас нет доступа к методам класса, а есть доступ только к коллекции методов экземпляра.

Тогда вы застряли с интенсивной ленивой загрузкой запроса.

Есть ли способ минимизировать запросы, чтобы получить все comments для коллекции posts из коллекции экземпляров?

Добавление для ответа (также добавлено в приведенный выше код)


Итак, чтобы загружать то, что я вижу в rdoc для rails, это метод класса на любом расширении ActiveRecord :: Ассоциации, проблема в том, что у вас нет возможности использовать метод классатак что вам нужно использовать какой-то метод экземпляра

пример кода, который, как я думаю, будет выглядеть, будет выглядеть примерно так:

post = Posts.find(:all)
posts.get_all(:comments) # runs the query to build comments into each post without the class method.

Ответы [ 3 ]

24 голосов
/ 20 декабря 2011

В Rails 3.0 и более ранних версиях вы можете сделать:

Post.send :preload_associations, posts, :comments

Вы можете передавать массивы или хэши ассоциативных имен, например: 1004 *

Post.send :preload_associations, posts, :comments => :users

В Rails 3.1 это было перемещено, и вы используете Preloader следующим образом:

ActiveRecord::Associations::Preloader.new(posts, :comments).run()

А после Rails 4 его вызов изменился на:

ActiveRecord::Associations::Preloader.new.preload(posts, :comments)
0 голосов
/ 18 декабря 2011

Как вы получаете свою коллекцию экземпляров модели и какую версию Rails вы используете?

Вы говорите, что у вас абсолютно нет доступа ни к контроллерам, ни к самим моделям?

дать вам лучший ответ зависит от знания этих вещей.

0 голосов
/ 18 декабря 2011

Мне кажется, я понимаю, что вы спрашиваете.

Однако я не думаю, что вам нужно беспокоиться о том, к каким методам у вас есть доступ.Отношения внешнего ключа (и ассоциации ActiveRecord, такие как has_many, belongs_to и т. Д.) Позаботятся о том, чтобы выяснить, как загрузить связанные записи.

Если вы можете предоставить конкретный примерчто, по вашему мнению, должно произойти, и фактический код, который не работает, было бы легче увидеть, к чему вы стремитесь.

...