Railsの.whereに渡せるもの
RailsのActiveRecordで条件を絞るメソッドといえば.where
ですが、いったいどれだけの形式の値を渡せるのでしょうか。
なお、手元にあったという理由でRails 4.2.7.1で検証を行っています。
where
の定義場所と、処理の流れ
まずは、ActiveRecord内部でのwhere
の処理を追いかけてみることにします。
where
自体はActiveRecord::Relation
のメソッドですが、実体はinclude
元のActiveRecord::QueryMethods
にあります。どのように処理が進むのか、流れを辿ってみました。
- 引数がハッシュだった場合、(必要なら)JOIN先の
references
をセットしておく -
build_where
で条件を整えておく -
where_values
に整えたものを追加
where
を実行した段階ではここまでですが、実際に取り出す段となると、以下のように処理が動いて、クエリが走ります。
-
ActiveRecord::Relation#load
でリレーションのロードを起動する -
ActiveRecord::Relation#exec_queries
でクエリの処理を開始する -
ActiveRecord::QueryMethods#build_arel
で、今までに積み重なったwhere_values
をArelに起こす -
find_by_sql
でクエリを投げる - Eager load関係の処理
ということで、各所でどのような処理が行われるか追いかけていく必要があります。
String
、Array
これらの場合は、与えられたパラメータがActiveRecord::Sanitization::ClassMethods#sanitize_sql_array
に渡ります(1つ、あるいは複数の文字列を配列で渡しても、まとめて配列で渡す形となります)。そして、以下のどれかのパターンで引数をエスケープして代入する処理が行われます。なお、1番目に来たパターン自体には何もエスケープが入りませんので、むやみに変数代入したりしてしまわないように気をつけましょう。
-
:name
形式で埋めたものを、2番めに渡したハッシュの同じキーに入った値で置き換え -
?
の入った箇所を、後に続く配列の値で順に置き換え -
'%s'
のような文字列を入れておいて、sprintf
で置き換え(※単純な文字列置換で、クオートされないので要注意)
なお、上2つの場合、ActiveRecord::Relation
を渡すとSQLに変換して埋め込む、なんて機能もあるようです(うまく使わないとややこしそうですが)。
Hash
引数にハッシュを渡すと、ActiveRecord::PredicateBuilder.build_from_hash
が呼び出されて、キーごとに処理が進んでいきます。ハッシュの値の型によって、どんな処理になるかが違ってきます。
- スカラー値…完全一致(
nil
もIS NULL
に変換) - モデルオブジェクト…
id
の一致 -
Range
オブジェクト…範囲検索(なお、..
はBETWEEN
に変換されますが、...
もきちんと不等号で再現してくれます) -
ActiveRecord::Relation
…指定された列(指定がなければ主キーの列)をSELECT
した結果をサブクエリにしたIN
クエリ - 配列…配列の要素によって、
- スカラー値…
nil
以外全部まとめてIN
(nil
は別途でIS NULL
にしてくれる) - モデルオブジェクト…
id
の一致 -
Range
オブジェクト…範囲検索
- スカラー値…
- ハッシュ…JOINしたテーブルへの条件(ハッシュの中身は親のハッシュと同様)
その他(Arelノード)
build_where
では、これまでに挙げなかった型の変数が来てもそのまま通すようになっていますが、あとでbuild_arel
してエラーにならないもの、ということで、事実上はArelノードに限られます。
Author And Source
この問題について(Railsの.whereに渡せるもの), 我々は、より多くの情報をここで見つけました https://qiita.com/jkr_2255/items/245533f606efabbf1b8f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .