Rails3 では、それぞれが異なるインクルードを持つ 2 つのスコープ (ActiveRelations) をチェーンするときに問題があるようです。
次の 2 つのスコープを考えてみましょう。どちらも単独で問題なく動作します。
最初のスコープ:
scope :global_only, lambda { |user|
includes(:country)
.where("countries.area_id <> ?", user.area) }
Work.global_only(user) => (読みやすくするために SQL からフィールドのリストを切り取ります)
SELECT * FROM "works" LEFT OUTER JOIN "countries" ON "countries"."id" = "works"."country_id" WHERE (countries.area_id <> 3)
次に、2 番目のスコープ:
scope :not_belonging_to, lambda { |user|
includes(:participants)
.where("participants.user_id <> ? or participants.user_id is null", user) }
Work.not_belonging_to(user) => (読みやすさのために SQL からフィールドのリストをカット)
SELECT * FROM "works" LEFT OUTER JOIN "participants" ON "participants"."work_id" = "works"."id" WHERE (participants.user_id <> 6 or participants.user_id is null)
したがって、これらは両方とも個別に適切に機能します。
次に、それらを連鎖させます。
Work.global_only(user).not_belonging_to(user)
SQL:
SELECT (list of fields) FROM "works" LEFT OUTER JOIN "countries" ON "countries"."id" = "works"."country_id" WHERE (participants.user_id <> 6 or participants.user_id is null) AND (countries.area_id <> 3)
ご覧のとおり、2 番目のスコープからの結合は完全に無視されます。したがって、SQL は「no such column 'participants.user_id」で失敗します。スコープを逆の順序でチェーンすると、「参加者」結合が存在し、「国」結合が失われます。失われるのは常に 2 番目の結合です。
これは ActiveRecord のバグのように見えますか、それとも私が何か間違ったことをしているのですか、それともこれは「機能」ですか :-)
(追伸。はい、知っています。両方のテーブルを結合するスコープを作成すると、必要な結果が正しく得られます。それは既にあります。しかし、さまざまな方法でチェーンできるよりも小さなスコープを作成しようとしていました。単純な sql に対する activerecord の利点であると考えられています。)