where句で「_」を検索する方法
ユーザーの検索でSQL文を使い、_(アンダースコア)から始まるユーザーネームを検索しようとした際に、少し困ったので書いておきます。
なんで困ったの?
まずスコープを作って検索の共通化をしました。
class User < ApplicationRecord scope :search_user, ->(name) { where('name like?', "#{name}%") } end
こんな感じのスコープで、任意の場所で検索をかけます。
@users.search_user('_')
と記述したところ、結果は全検索となりました。
欲しい結果はアンダースコアから始まるユーザーです。
原因を考えていたところ、そういえばSQLにはワイルドカードなんてのがあったなと思い出し調べてみました。
ワイルドカード
LIKE句で使えるワイルドカードは2種類あります。
%……0文字以上の任意の文字列
_…任意の1文字
なるほど。ワイルドカードで検索をしてしまったようです。
@users.search_user('_')
の意味するところは、任意の1文字を何もない文字に指定したので、結果的に全検索になっていました。
解決策
アンダースコアから始まる名前を検索するにはエスケープ文字を使ってあげれば良いです。
ワイルドカードである「_」の前に、バックスラッシュを書いてあげれば正しく検索できます。
@users.search_user('\_')
これで欲しい結果を得ることができました。
参考
http://www.sql-reference.com/select/like.html
https://rooter.jp/programming/ruby/rails_use_where_or_sanitize_sql_methods_to_avoid_sql_injection/
https://itsakura.com/sql-select-like