ActiveRecordで複数カラムに対し複数キーワードで探す
割と汎用的かと思ったので載せてみようかと。
orの引数にnilがきたらそのままなのがミソ。
class ActiveRecord::Base def self.search_with_multi(columns:, keywords:) where(columns_keywords_cond(columns, keywords)) end def self.columns_keywords_cond(columns, keywords) columns .product(keywords) .reduce(nil) do |cond, (column, keyword)| arel_table[column].matches("%#{keyword}%").or cond end end end Book.search_with_multi(columns: [:title, :description], keywords: ["夏", "休み"])
追記
これだと%と_の文字が埋もれてしまうのと、nilが条件を汚染していたので、以下に修正。 sanitize_sql_likeはRails4.2からは標準で入ってるメソッドとのこと。
class ActiveRecord::Base def self.search_with_multi(columns:, keywords:) where(columns_keywords_cond(columns, keywords)) end def self.columns_keywords_cond(columns, keywords) columns .product(keywords) .map { |column, keyword| arel_table[column].matches("%#{sanitize_sql_like(keyword)}%") } .reduce(&:or) end def self.sanitize_sql_like(string, escape_character = "\\") pattern = Regexp.union(escape_character, "%", "_") string.gsub(pattern) { |x| [escape_character, x].join } end end