baronyan's blog

linux,macでruby、railsでの開発をしていく中で知ったこと、備忘的なことなどを書いていきます。

rails3のAR(Arel)でIN句を使った条件をAND、ORで連結する方法

rails3のAR(Arel)でIN句を使った条件をAND、ORで連結する方法

 

AND、ORを使わずにIN句を使うには、
下記のように第二引数で配列を指定すれば良いです。簡単ですね。

scope :magazine, where("type_id in (?)", BookType.has_magazine_code.map{|ele| ele.id })

一方、IN句をANDやORで他の条件と連結するには
women = User.women.where_values.reduce(:and) boys = User.boys.where_values.reduce(:and) User.where(women.or boys).to_sql
のようにします。
(参考:http://qiita.com/ichi_s/items/22f3535c3e8adb901902

ところが、上の2つを組み合わせた場合、望む結果が得られません。
例えば、

magazine = Book.magazine.where_values.reduce(:and)
novel = Book.novel.where_values.reduce(:and)
Book.where(magazine.or novel).to_sql
とした場合、where句が
where 'type_id IN (1,2)' OR 'type_id IN (3,4,5)'
といった形の不要な文字列化がなされた状態になってしまいます。

これは
IN句を使ったscope次のように書き換えることで回避できます。
scope :magazine, where(arel_table[:type_id].in(BookType.has_magazine_code.map{|ele| ele.id }))