ActiveRecord::Relation#orのworkaround
先日書いた記事の付け足しになりますね。or
を利用して検索ロジックを書いていましたが
merge
や、where
を利用することで構造に不一致になるケースがあり、HACK
,WORKAROUND
で対処しました。
原因はなんとなくイメージできているんですが、詳しい方いましたら、教えて頂きたいです。
- 完全に再現できるソースではなく、イメージです。
models
まず、モデルはこの親子関係になります。
# app/models/user.rb class user < ApplicationRecord has_many :shops end # app/models/shop.rb class shop < ApplicationRecord belongs_to :user end
controller
app/controllers/users.rb class Users < ApplicationController def search relations = user.joins(:shop).where(name: 'hoge') relations = if params[:conditions] == 'or' relations.or(relations.where(age: 19) else # relations.joins_valuesが更新される relations.merge(relations.where(age: 19)) end render json: relations.to_json({ include: :shops }) end end
relations.joins_values
これで、引数とレシーバーの構造が一致しているか検証しています。
joins
の引数(上記のサンプルコードでは、:shop)が入っていますので、これが一致するか見ています。
捕捉ですが、limit
, offset
, distinct
も見ています。
WORKAROUND
修正したのは下記。
app/controllers/users.rb class Users < ApplicationController def search relations = user.joins(:shop).where(name: 'hoge') relations = if params[:conditions] == 'or' relations.joins_values = relatoins.joins_values.uniq # HACK: relations.or(relations.where(age: 19) else relations.merge(relations.where(age: 19) end render json: relations.to_json({ include: :shops }) end end
joins_values
を上書きすることで対応した。これmerge
をしているからjoins_values
の値も追加されているのかと思い、where
に変えてみたが、
joins_values
の値は変わらず。githubで調べるのはこのぐらいにして一時的な対応です。