Rails3以降、ActiveRecordによるDB検索は「Arel」という中間ライブラリを利用して行われています。
・・・最近知りました。
以前と同じインタフェースで利用していました。
ということで現在はArelによるメソッドチェインを利用した形でコーディングしているのですが、
タイトルにも挙げた通り、OR条件のつなげ方で悩んだので解決法を載せておきます。
※今回はRails3.2.3を利用しました。ネット上で見かけるRails4の実装では上手くいかないものがあったのでご注意を。
以下のサイトでは(たぶん)Rails4での使い方の例が載っています。
第43回 Rails 3を支える名脇役たち その1 - Arel -:Ruby Freaks Lounge|gihyo.jp … 技術評論社
Rails 3&4: Arel::Tableを使ってなるべく生のSQLを書かずに済ます方法
観察から知る Rails3 ActiveRecord + Arel の特徴と使い方 - tashenの日記
悩んだ経緯
例えば「複数のキーワドのいずれかに該当するデータ」を取りたいとなったら、
配列に格納した文字列を繰り返し処理で、メソッドチェインしたいわけです。
その時にANDは簡単に出来たのですが、ORが上手くいかなかった・・・
AND条件のチェイン
まずは簡単にできたAND条件のチェインの例を載せます。
#ActiveRecordからArel::Tableインスタンスを取得 users = User.arel_table #キーワード配列 keyword_arr = {'a','b',.....'z'} #1つ目を条件に格納して最初のActiveRecord::Relationを取得 users_rel = users.where(users[:name].eq(keyword_arr[0])) #あとはこれに好きなだけつなげていきます for i in 1..users_rel.length-1 users_rel = users_rel.where(users[:name].eq(keyword_arr[i])) end #出来上がったSQL(実際にこんな条件成立しませんが。) puts users_rel.to_sql #=> SELECT `users`.* FROM `users` WHERE `users`.`name` = 'a' AND `users`.`name` = 'b' OR ... AND `users`.`name` = 'z'
基本的にwhereメソッドはActiveRecord::Relationインスタンスを返し、そのインスタンスからさらにwhereメソッドを呼び出すことでAND条件がチェインされます。
OR条件のチェイン
ではorの場合どうするか。
#ActiveRecordからArel::Tableインスタンスを取得 users = User.arel_table #キーワード配列 keyword_arr = {'a','b',.....'z'} #最初のArel::SelectManager取得 users_sel = users[:name].eq(keyword_arr[0]) #このusers_selにorメソッドで条件をチェインしていく for i in 1..users_sel.length users_sel = users_sel.or(users[:name].eq(keyword_arr[i])) end #この時点でSQLの「条件部」だけが完成 puts users_sel.to_s #=> `users`.`name` = 'a' OR `users`.`name` = 'b' OR ... `users`.`name` = 'z' #whereメソッドへ完成した条件を渡してActiveRecord::Relationが完成 users_rel = users.where(users_sel) #出来上がったSQL puts users_rel.to_sql #=> SELECT `users`.* FROM `users` WHERE `users`.`name` = 'a' OR `users`.`name` = 'b' OR ... OR `users`.`name` = 'z'
わかってしまえば簡単です。
Relation(users)のwhereメソッドは、
引数に条件を示すオブジェクトであるSelectManager(users[:name].eq()とかの戻り値)が渡ったとき、
それが複数あるとANDでチェインします。
それと同等のOR機能は残念ながらないため、SelectManagerのor(andもある)メソッドを使って、
条件だけを先に組み立てて最後にRelationを生成してみました。
※すべて動作を見ただけで書いています。ソースコードを読んでないので正確ではありません。
whereとorの戻り値について理解が足りずに苦しんだのでした。
Ruby on Rails 4 アプリケーションプログラミング
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2014/04/11
- メディア: 大型本
- この商品を含むブログ (6件) を見る