Если вы наткнулись на эту статью, ваш активный администратор, вероятно, решил подождать минуту, прежде чем показать простую страницу индекса для одной из ваших таблиц. Дайте угадаю: это большая таблица с сотнями тысяч записей. Но почему размер таблицы имеет значение, если все, что нам нужно, это показать пару первых строк?

Что ж, похоже, размер имеет значение не для Active Admin, а для самого PostgreSQL. Точнее - для общего подсчета строк.

Предыстория: модель параллелизма в PostgreSQL реализована с использованием техники под названием MVCC (управление многоверсионным параллелизмом), которая для обеспечения правильности результата в параллельных средах позволяет запускать что-то очень простое, например select count(*) from items;, чтобы просмотреть все строки в items таблице. И это не то, что можно отключить.

Active Admin показывает общее количество строк на каждой странице индекса, что делает производительность неприемлемой. Давай исправим.

Самое простое, что мы можем сделать, - это запретить Active Admin вызывать count в модели:

index(pagination_total: false) do
  # ...
end

Производительность исправляется мгновенно, но вы вообще теряете возможность видеть какие-либо счетчики. Если все в порядке, можете пропустить оставшуюся часть этой статьи и зафиксировать исправление. Но если пользователям вашего приложения нужны цифры (а информация без цифр зачастую бесполезна), вам придется копнуть глубже.

К счастью, в PostgreSQL есть специальная таблица pg_class для хранения некоторых метаданных. Столбец reltuples особенно интересен для нас, потому что он хранит приблизительное количество записей в таблицах. В нашей базе эта оценка отличается от реальных значений не более чем на 2%, что вполне подходит для наших нужд.

Итак, давайте создадим небольшую проблему, которую можно включить в любую модель для поддержки расчетного количества:

Обратите внимание на строку номер 8: PostgreSQL возвращает большие числа в научном формате, и «2.500000E + 06», вероятно, не то, что вы хотите иметь в пользовательском интерфейсе.

Теперь нам нужно отобразить его на индексных страницах. Боковые панели активного администратора отображаются под списком фильтров и кажутся подходящим местом для наших нужд. Давайте создадим вспомогательный метод, который можно использовать на любой странице индекса, чтобы добавить боковую панель со счетчиком:

В приведенном выше коде есть несколько интересных моментов. Прежде всего, параметр dsl (экземпляр ActiveAdmin::ResourceDSL) - это то, что у вас есть как self внутри метода ActiveAdmin.register. У него есть метод sidebar, который (что удивительно) отображает нужную нам боковую панель. Параметр only: :index указывает не отображать боковую панель на странице показа.

Теперь мы должны использовать метод estimated_count только в тех случаях, когда пользователь не применяет никаких фильтров. В противном случае можно использовать простой метод count, потому что фильтрация в любом случае проходит через каждую строку или использует индексы. В обоих случаях count не повлияет на производительность. Чтобы узнать, применяются ли фильтры, мы можем проверить параметр запроса q (используется ransack gem под капотом Active Admin) - строка номер 5. Все, что осталось, - это сформировать строку и поместить ее в диапазон внутри нашей боковой панели.

Давайте вызовем вспомогательный метод:

А вот как это выглядит:

Вот и все. Но если вы перфекционист (или, в моем случае, работаете с очень хорошим QA), вы заметите, что кнопка «последняя» в разделе разбивки на страницы под таблицей на индексных страницах перестала работать должным образом. Ну, общего подсчета нет, поэтому он не знает, сколько страниц существует, и, как следствие, не может ссылаться на последнюю. Вы можете подумать о некоторых грязных хитростях, таких как изменение кода kaminari gem, используемого Active Admin для разбивки на страницы, но сделав это, вы выстрелите себе в ногу раньше, чем вы думаете. Так что давайте просто спрячем неиспользуемые кнопки в active_admin.scss:

.index.admin_items .pagination .last { display: none; }

Теперь мы закончили.

PS. Lifehack: время от времени спрашивайте пользователей вашего активного администратора, как они обычно используют фильтры, и добавляйте индексы в свои таблицы. В 21 веке время намного дороже, чем место на жестком диске или использование процессора в вашем облаке.