Rails: Як здійснити пошук за допомогою Ransack, видаляючи всі пробіли в полі імені

pic

Проблема

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.

Джерела

Перекладено з: Rails: How to search with Ransack removing all spaces in the name field