技術ブログ

(技術系中心)基本自分用備忘録なので、あくまで参考程度でお願いします。

大文字小文字を区別しないでActiveRecord(where)で取得する方法

大文字小文字を区別しないでActiveRecord(where)で取得する方法

■ モデル構造

スクリーンショット 2019-12-10 14.40.52.png

Personテーブルから名前がstevejobsのレコードを検索取得したい場合

モデルクラス.where("列名 LIKE ?", "%値%")  # 値(文字列)を含む

で取得できるので以下のように実装します。

Person.where("name like ?", "%stevejobs%")  # 値(文字列)を含む

これでnameがstevejobsのレコードが取得できます。

しかし検索する時に英語の大文字小文字を区別したいケースに遭遇しました。

例) 人物テーブルからステーブジョブスを検索したい場合

Aさん -> "SteveJobs"と検索
Bさん -> "stevejobs"と検索

現在の実装ではstevejobsと検索しているのでBさんの検索方法でしかヒットしません。

arel_tableを利用する。

色々調査した結果、Active Recordの内部で使用されるSQL生成ライブラリArelを利用すれば実現可能ということがわかりました。

Arelを使うと文字列でSQLを書くことなく、Rubyのコードとしてクエリを書くことができます。

arelではmatchesを使う事でlikeクエリが書けるので以下のように変更します。

persons = Person.arel_table
persons.where(persons[:name].matches("%name%"))

matchesメソッドではデフォルトでcase_sensitive = falseと設定されているので大文字小文字を区別しません。

def matches(other, escape = nil, case_sensitive = false)
  Nodes::Matches.new self, quoted_node(other), escape, case_sensitive
end

これで、AさんパターンBさんパターンのどちらもヒットします。

環境

Rails 6.0.1
ruby 2.6.5p
postgres:11.2

参考

https://cbabhusal.wordpress.com/2015/06/04/ruby-on-rails-case-insensitive-matching-in-rails-where-clause/