Ruby
Rails

ActiveRecord::Relationを結合する

More than 1 year has passed since last update.

別々の条件で取得したActiveRecord::Relationを1つにまとめようとしたら、思いの外苦労したので備忘録。
他にいい方法があれば、ぜひコメントをお願いします!

Rails 5.0以降ならorメソッド、それ以外は一度Arrayにして結合

別々の条件で取得したActiveRecord::Relationを1つにまとめる場合、mergeだとAND条件になってしまい、意図とは違う結果に。

orというメソッドを使えばすんなり結合できるが、手元の環境はRails 4.0だったため、他の方法を模索。

+ で2つのActiveRecord::Relationを結合し、一度Arrayにした状態で再度ActiveRecord::Relationするという方法で実現。ちょっと回りくどいですが、ちゃんと書けば可読性もそこまで落ちないので、一旦この方法で落ち着きました。

users = User.where(id: [1,2,3])
another_users = User.where(name: 'John Doe')

another_users.pluck(:id) #=> [4]

# combined with AND
users.merge(another_users).to_sql
#=> SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2, 3) AND `users`.`name` = 'John Doe'

# combined with OR (only available in Rails 5.0~)
users.or(another_users).to_sql
#=> "SELECT `users`.* FROM `users` WHERE (`users`.`id` IN (1, 2, 3) OR `users`.`name` = 'John Doe')"

# combined with OR (through Array, available in Rails ~4.0)
User.where(id: (users + another_users).map(&:id)).to_sql
#=> SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2, 3, 4)

参考

Combine two ActiveRecord::Relation objects
[Ruby on Rails] 配列を ActiveRecord::Relation に変換する