Стендап Сьогодні 📢 Канал в 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
викликатиметься стандартна логіка, а не скоуп.