Якщо ви натрапили на цю статтю, то, ймовірно, ваш Active Admin вирішив трохи «зависнути», перш ніж показати просту сторінку індексу для однієї з ваших таблиць. Дозвольте здогадатися: це велика таблиця з сотнями тисяч записів. Але чому розмір таблиці має значення, якщо нам потрібно лише показати кілька перших рядків?
Здається, що розмір має значення не для Active Admin, а для самого PostgreSQL. Якщо бути точнішими — для підрахунку всіх рядків.
Передісторія: модель одночасного доступу (concurrency model) у PostgreSQL реалізована за допомогою техніки, яка називається MVCC (multiversion concurrency control), яка, щоб забезпечити коректність результатів у середовищах з паралельними запитами, змушує виконання такого простого запиту, як select count(*) from items;
перевіряти всі рядки в таблиці items
. І це не те, що можна вимкнути.
Active Admin показує загальну кількість рядків на кожній сторінці індексу, що робить продуктивність неприязною. Давайте виправимо це.
Найпростіше, що ми можемо зробити — це заборонити Active Admin викликати count
для моделі:
index(pagination_total: false) do
# ...
end
Це миттєво покращує продуктивність, але ви втратите можливість бачити будь-які підрахунки. Якщо це прийнятно — можете пропустити решту цієї статті і зафіксувати своє виправлення. Але якщо користувачам вашого застосунку потрібні числа (а інформація без чисел часто є безглуздою), вам доведеться копати глибше.
На щастя, PostgreSQL має спеціальну таблицю під назвою pg_class
, де зберігаються метадані. Стовпець reltuples
є особливо цікавим для нас, оскільки він зберігає оцінену кількість записів у таблицях. У нашій базі даних ця оцінка відрізняється від реальних значень не більше ніж на 2%, що абсолютно підходить для наших потреб.
Отже, давайте створимо невеликий concern, який можна включити до будь-якої моделі, щоб підтримати оцінену кількість:
Зверніть увагу на рядок номер 8: PostgreSQL повертає великі числа у науковому форматі, і «2.500000E+06» — це, ймовірно, не те, що ви хочете бачити в інтерфейсі.
Тепер нам потрібно показати це на сторінках індексу. Бічні панелі Active Admin рендеряться під списком фільтрів і здаються чудовим місцем для нашої мети. Створимо допоміжний метод, який можна використовувати на будь-якій сторінці індексу для додавання бічної панелі з кількістю:
У коді вище є кілька цікавих моментів. По-перше, параметр dsl
(екземпляр ActiveAdmin::ResourceDSL
) — це те, що ви маєте як self
всередині методу ActiveAdmin.register
. Він має метод sidebar
, який (на диво) рендерить потрібну нам бічну панель. Параметр only: :index
вказує, щоб не рендерити бічну панель на сторінці перегляду.
Тепер ми повинні використовувати метод estimated_count
тільки для випадків, коли користувач не застосовує фільтри. В іншому випадку можна використовувати простий метод count
, оскільки фільтрація все одно проходить через кожен рядок або використовує індекси. В обох випадках метод count
не збільшить навантаження на продуктивність. Щоб дізнатися, чи застосовані фільтри, ми можемо перевірити параметр запиту q
(який використовується гемом ransack
під капотом Active Admin) — рядок номер 5. Все, що залишається, — це сформувати рядок і помістити його в елемент <span>
у нашій бічній панелі.
Давайте викличемо допоміжний метод:
І ось як це виглядає:
Ось і все. Але якщо ви перфекціоніст (або, як у моєму випадку, працюєте з дуже хорошою QA-командою), ви помітите, що кнопка «останній» у секції пагінації під таблицею на сторінках індексу більше не працює належним чином. Виходить, що без загальної кількості неможливо зрозуміти, скільки сторінок існує, і тому неможливо перейти до останньої. Ви можете придумати якісь «брудні» хаки, наприклад, змінити код гема kaminari
, який використовується Active Admin для пагінації, але таким чином ви «підстрелите себе» швидше, ніж думаєте. Тому давайте просто сховаємо непотрібні кнопки в active_admin.scss
:
.index.admin_items .pagination .last { display: none; }
Тепер ми завершили.
PS. Лайфхак: Час від часу запитуйте у користувачів вашого Active Admin, як часто вони використовують фільтри, і додавайте індекси до своїх таблиць.
У 21 столітті час значно дорожчий, ніж місце на жорсткому диску або використання процесора в хмарі.
Перекладено з: How to Make Ruby on Rails Active Admin and Large PostgreSQL Tables Friends Again