ActiveRecord::Relation#or
弊社の新規プロジェクトでは、Rails5が使われていてそのおかげで、or
が利用できた。
今日は、その辺りをまとめてみる。
ActiveRecord::Relation#or
Rails 4系では、sqlのor
をアプリで実装しようとするとfind_by_sql
、where
、joins
などに直接sqlを書くか。Arel
を利用して実装を進めていた。
Rails 5系からor
が利用できるようになっているので、直接sql
を記述することなく、ActiveRecord
の操作で完結できる。
# A || B Model.where(name: 'hoge').or(Model.(name: 'fuga')) # A && B || C Model.where(name: 'hoge').where(age: 10).or(Model.where(name: 'fuga')) # A ‖ B && C Model.where(name: 'hoge').or(Model.where(age: 10)).where(name: 'fuga'))
という結果が返ってくる。
must be structurally compatible
構造互換性が必要なので、orに指定するActiveRecord::Relation
とレシーバの構造は統一する。
互換性がなければ、下記のArgumentError
が発生する。
ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:limit]
サンプル
Model.joins(:hoges) .merge(Model.where(name: nil) .or(Hoge.where(fuga: nil) => SELECT "model".* FROM "model" INNER JOIN "hoges" ON "hoges"."model_id" = "models"."id" WHERE ("models"."name" IS NULL OR "hoges"."fuga" IS NULL)
これで、and
とor
の条件を切り換えられるロジックを書くことが容易になった。