Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

24.04.2023

Розширення та знущання з Ransack

Сьогодні половину дня намагався зробити новий фільтр для Ransack. То є така бібліотека для Ruby on Rails, щоб будувати запити до бази з користувацьких форм. Використовується для всілякого пошуку; в тому числі пошук в ActiveAdmin використовує саме його.

Власне, шляхів розширення в Ransack вистачає, але майже всі вони мають відповідати закладеній абстракції: до деякого атрибута прикладається деякий оператор, можливо — зі значенням. Наприклад: {"name_eq": "Grigory"}. Оператор має бути виражений в Arel, тому якщо це не вдається, вони пропонують манкіпатчити Arel, щоб доповнити його власними предикатами.

Але в мене задача вийшла ще складніше. Мені треба було поміняти поведінку оператора equals, але тільки для одного поля. Тобто зовнішній інтерфейс залишити без змін. Гарного способу це зробити я не знайшов; негарний складався з того, що перед запитом я підміняю оператор на інший, custom_field_eq. Але як можна було помітити в попередньому параграфі, запит склеює поле та оператор, тобто остаточно фільтр виглядає як {"custom_field_custom_field_eq": "Grigory"}.

Потім, висловити цей оператор у формі оператора Arel теж вийшло непросто, оскільки перевіряється значення алгебраїчного виразу. Тоді знайшов трохи прихований, але дуже зручний вихід — можна як фільтр використати скоуп. Залишається в моделі оголосити скоуп custom_field_custom_field_eq, та робити в ньому що завгодно.

Можна подумати, що якщо так, то не треба було додавати оператора. Але ні — здається. скоупи мають нижчий пріоритет, тому на фільтр custom_field_eq викликатиметься стандартна логіка, а не скоуп.