失礼いたします。
先に質問の要点だけまとめてしまいますと、
- ActiveRecordでINNER_JOINになってほしいところがなぜかLEFT_OUTER_JOINになってしまう理由。 - has_oneの使い方として、そもそもこのようなケースはありなのか?
という点です。
以下質問内容です。
Railsの4.2.6で開発しているものなのですが、特定のモデルのhas_oneも含んだ検索ロジックを組もうとすると、思った通りの挙動をしてくれないのです。
現在の状況としましては、親から順に1対多の関係となっている三つのモデルが以下のようにありまして
ruby
1# 一番親のモデル 2class First < ApplicationRecord 3 has_many :seconds, dependent: :destroy 4end 5 6 7# 二番目のモデル 8class Second < ApplicationRecord 9 belongs_to :first 10 has_many :thirds, dependent: :destroy 11 12 # 設計上、is_lastがtrueとなるモデルは、各Secondモデルに一つだけなので 13 has_one :special_third, -> { where(Third.arel_table[:is_last].eq(true)) }, class_name: 'Third' 14 15 # special_thirdを持っているsecondを返す 16 scope has_special_third, -> { 17 joins(:special_third) 18 } 19end 20 21 22# 三番目のモデル 23class Third < ApplicationRecord 24 belongs_to :second 25 26 # プロパティにboolean 「is_last」を持っている 27end
「Firstモデルのうち、is_lastプロパティがtrueのThirdモデル
を持っているもの」という条件で検索したいのです。
私の今のロジックはFirst.joins(:seconds).merge(Second.has_special_third)
としているのですが、検索結果をみても、最後のis_lastの部分が効いていないのです。
SQLをみたところ
SELECT "firsts".* FROM "firsts" INNER JOIN "seconds" ON "seconds"."first_id" = "firsts"."id" LEFT OUTER JOIN "thirds" ON "thirds"."second_id" = "seconds"."id" AND "thirds"."is_last" = 't'
このように一部LEFT OUTER JOIN
になっているのが原因とは思うのですが、だとしたらどこをどのように変えたらINNER JOIN
に変えることができるのでしょうか?
そして、もう一つお伺いしたいのは、今回のプロジェクトではhas_oneがみたことない特殊な使われ方(?)をしていて、今回のように検索の絞り込みに使うのはどうなのだろうか?という点です。
ややこしくなってしまいましたが、ご回答いただけると誠に幸いです。宜しくお願い致します。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/01 07:31