Проблема
Ransack — це дуже корисний гем для реалізації функціоналу пошуку в додатках Rails, але пошук з використанням _cont
не завжди працює коректно якщо рядкове поле містить пробіли.
У моєму випадку, рядкове поле name
може містити як звичайні пробіли, так і японські пробіли в базі даних, і користувачі можуть вводити будь-який з цих типів пробілів між іменем та прізвищем.
keyword = params[:keyword] # Може бути "山田 太郎" або "山田 太郎"
@q = User.ransack(name_cont: keyword)
@users = @q.result # Це не завжди працює добре...
Рішення
Я можу вирішити цю проблему, налаштувавши поле name
за допомогою ransacker
та SQL-функції REPLACE
таким чином:
class User < ApplicationRecord
# ...
ransacker :name do |parent|
Arel::Nodes::NamedFunction.new('REPLACE', [
Arel::Nodes::NamedFunction.new('REPLACE', [
parent.table[:name],
Arel::Nodes.build_quoted(' '),
Arel::Nodes.build_quoted('')
]),
Arel::Nodes.build_quoted(' '),
Arel::Nodes.build_quoted('')
])
end
# ...
end
Цей кастомний ransacker
використовує вкладені функції REPLACE
, щоб видалити як звичайні пробіли, так і японські пробіли з поля name
перед виконанням пошуку.
Також необхідно внести зміни до введеного ключового слова, щоб видалити всі пробіли.
keyword = params[:keyword]&.gsub(/[[:space:]]/, '') # "山田 太郎" -> "山田太郎"
@q = User.ransack(name_cont: keyword)
@users = @q.result
Після цих змін пошук працював, як очікувалося 🎉
Питання про продуктивність
Щодо проблеми з продуктивністю при використанні вкладених функцій REPLACE
, вплив на продуктивність зазвичай буде мінімальним для малих та середніх наборів даних.
Однак, якщо ви працюєте з великими наборами даних, продуктивність може постраждати. У такому разі потрібно оптимізувати запити, додати індекси до часто запитуваних колонок або розглянути інші оптимізації продуктивності бази даних.
Якщо ви виявите, що продуктивність вкладених функцій REPLACE
є великою проблемою, вам слід дослідити інші варіанти, такі як повнотекстовий пошук, використовуючи спеціалізовану пошукову систему, наприклад, Elasticsearch.
Джерела
- https://github.com/activerecord-hackery/ransack
- https://activerecord-hackery.github.io/ransack/going-further/ransackers/
Перекладено з: Rails: How to search with Ransack removing all spaces in the name field