- 更新日: 2014年5月12日
- Rails
Rails ActiveRecordのSQLでLIKE検索をエスケープ
Rails で ActiveRecord を使って LIKE 検索をする際に、LIKE に渡す文字列をエスケープする方法です。ワイルドカードとして使われる ‘%’, ‘_’ の文字、およびデフォルトでのエスケープ用文字である ‘\’(バックスラッシュ)が、LIKE に渡す文字列に含まれる場合にエスケープする必要がある。
例えば、”100%完成” みたいな文字列を LIKE 検索にそのまま渡すと、% がワイルドカードとして使われてしまうので、それを防ぐために “100\\%完成” とエスケープする必要がある。バックスラッシュは文字列でもエスケープ用キャラクタとして使われるので、LIKE検索に渡す際にはバックスラッシュが2つ必要なことにも注意。
— 環境 —
Rails 4.0.1
独自に escape_like メソッドを実装
LIKE 検索時に使える API が Rails では特に用意されていなさそうだったので、以下のメソッドを作りました。
1 2 3 |
def escape_like(string) string.gsub(/[\\%_]/){|m| "\\#{m}"} end |
この escape_like メソッドは、実は Sequel という Ruby 用の別の ORM ライブラリからの拝借です。
Method: Sequel::Dataset#escape_like — Documentation for jeremyevans/sequel (master)
使うコントローラー/モデルの private メソッドとして作成する。あるいは、色んな箇所で使う場合は ApplicationController に定義するか、ActiveRecord::Base そのものにクラスメソッドとして追加したほうが便利です。私は以下の方法で ActiveRecord 自体を拡張しました。
ActiveRecord::Base にクラスメソッドとして追加
ActiveRecord::Base をオープンして escape_like クラスメソッドを追加すると、モデルのクラスメソッドとして利用でき、場所を選ばずどこでも使えます。以下 pry での実行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
pry(main)> ActiveRecord::Base.singleton_methods.grep(/like/) => [] pry(main)> module ActiveRecord pry(main)* class Base pry(main)* def self.escape_like(string) pry(main)* string.gsub(/[\\%_]/){|m| "\\#{m}"} pry(main)* end pry(main)* end pry(main)* end => nil pry(main)> ActiveRecord::Base.singleton_methods.grep(/like/) => [:escape_like] pry(main)> User.escape_like("100%完成") => "100\\%完成" |
アプリケーションのコードとしては、lib 以下にファイルを置いて initializers で require する方法が簡単です。
lib/active_record_extension.rb
1 2 3 4 5 6 7 |
module ActiveRecord class Base def self.escape_like(string) string.gsub(/[\\%_]/){|m| "\\#{m}"} end end end |
config/initiaizers/lib.rb
1 |
require "active_record_extension" |
ActiveRecordをさらに便利にする方法の紹介 – Hello, world! – s21g
escape_like メソッドの使い方
以下のように使います。
1 |
User.where("name LIKE ?", "%#{escape_like(params[:name])}%") |
where メソッドにプレースホルダーで渡す。
または、ActiveRecord に追加した場合は以下。
1 |
User.where("name LIKE ?", "%#{User.escape_like(params[:name])}%") |
これで、Rails で SQL の LIKE を使うのが楽になりました。
- – 参考リンク –
- SQLのLIKE条件に指定する文字列に含まれる%や_のエスケープ | もっとクールにプログラミング
- Railsで検索をSQLで簡単に実装する方法 – Qiita
- MySQLでバックスラッシュの入った文字列を比較する際の注意点 | Groove Labo
- MySQL :: MySQL 5.1 リファレンスマニュアル :: 11.3.1 文字列比較関数
- Rails の関連記事
- RailsでMySQLパーティショニングのマイグレーション
- Rails ActiveRecordでdatetime型カラムのGROUP BY集計にタイムゾーンを考慮する
- RailsプラグインGemの作成方法、RSpecテストまで含めたrails pluginの作り方
- RailsでAMPに対応するgemをリリースしました
- Railsでrequest.urlとrequest.original_urlの違い
- Railsでwheneverによるcronバッチ処理
- Google AnalyticsのRails Turbolinks対応
- Railsアプリにソーシャル・シェアボタンを簡単設置
- Rails監視ツール用にErrbitをHerokuで運用
- Facebook APIバージョンのアップグレード手順(Rails OmniAuth)
Leave Your Message!