Нетерпеливая загрузка связанных моделей в SQL-запрос ActiveAdmin

У меня есть индексная страница ActiveAdmin

ActiveAdmin.register Bill

И я пытаюсь отобразить ссылки на связанные модели

index do
  column "User" do |bill|
   link_to bill.user.name, admin_user_path(bill.user)
  end
end

Но я столкнулся с проблемой запроса N+1 — есть запрос для получения каждого пользователя.

Есть ли способ нетерпеливой загрузки пользователей счетов?


person tomblomfield    schedule 14.12.2011    source источник


Ответы (4)


В другом посте есть ответ, но он хорошо описывает, что вам нужно сделать здесь.

  controller do
    def scoped_collection
      Bill.includes(:user)
    end
  end

Здесь вам нужно будет убедиться, что вы следуете масштабу. Поэтому, если ваш контроллер имеет значение scope_to'ed, вам нужно будет заменить указанное выше имя модели параметром scope_to'ed.

person Jeff Ancel    schedule 29.01.2012
comment
он не разбит на страницы = результат может быть огромным - person okliv; 05.12.2012

Способ сделать это - переопределить метод scoped_collection (как указано в ответе Джеффа Анселя), но вызвать super, чтобы сохранить существующую область. Таким образом, вы сохраняете любую разбивку на страницы/фильтрацию, примененную ActiveAdmin, а не начинаете с нуля.

ActiveAdmin.register Bill do
  controller do
    def scoped_collection
      super.includes :user
    end
  end

  index do
    column "User" do |bill|
     link_to bill.user.name, admin_user_path(bill.user)
    end
  end
end

Как указано в официальной документации по адресу http://activeadmin.info/docs/2-resource-customization.html

person Jay    schedule 27.06.2016

Существующие ответы были правильными в то время, но ActiveAdmin теперь поддерживает активную загрузку с гораздо более удобным синтаксисом:

ActiveAdmin.register Bill do
  includes :user
end

См. документацию по настройке ресурсов.

person Thilo    schedule 13.10.2019

ВАЖНОЕ ЗАМЕЧАНИЕ ПО РЕДАКТИРОВАНИЮ: то, что следует ниже, на самом деле ложно, смотрите комментарии для объяснения. Однако я оставляю этот ответ там, где он есть, потому что кажется, что я не единственный, кто запутался в руководствах, поэтому, возможно, кто-то еще найдет его полезным.

я предполагаю, что

class Bill < ActiveRecord::Base
  belongs_to :user
end

поэтому согласно руководствам RoR он уже загружен:

Нет необходимости использовать :include для непосредственных ассоциаций — то есть, если у вас есть Order own_to :customer, то клиент будет загружаться автоматически, когда это необходимо.

вы должны проверить свой журнал SQL, если это правда (сам не знал этого, я просто проверял что-то о :include, чтобы ответить вам, когда увидел это... дайте мне знать)

person m_x    schedule 14.12.2011
comment
я думаю, что это очень сомнительно, но кто знает? - person m_x; 15.12.2011
comment
клиент загружается автоматически, когда это необходимо. Это просто означает, что если у вас есть 1000 заказов и вы выполняете итерацию по ним, вы вызываете order1.customer, и customer1 загружается, потому что это необходимо. Затем вы получаете доступ к order2.customer, но, эй, вы не сказали, что вам это понадобится, поэтому выполняется еще один запрос к базе данных. Но он по-прежнему не знает, что вам понадобится customer3 на следующей итерации, поэтому вы получите 1000 запросов вместо 1. - person RocketR; 16.03.2012
comment
спасибо, что прояснили это. Я нахожу этот способ изложения вещей сбивающим с толку, но английский не мой родной язык. - person m_x; 19.03.2012
comment
Речь идет о добавлении :include к определению ассоциации и о том, что ассоциация не должна включаться сама по себе. Я считаю, что это отличается от добавления вызова include в область, которая должна с нетерпением загружать добавленные модели. (Я говорю «должен», потому что... угадайте, почему я сейчас на этом сайте) - person elc; 12.02.2013