1

モデルの関連付けを多用するプロジェクトに取り組んでいますが、has_manyまたはhas_one through機能が:conditions機能と競合するケースを見つけたようです。一言で言えば、問題は、throughアソシエーションがhas_onethrough関係の中間テーブルのテーブルエイリアスを作成することです。しかし、そのテーブルエイリアスを定義した条件で表示する方法がわかりません。それを理解するのが難しい場合は、コードが役立つ可能性があります。

class Event < ActiveRecord::Base
  has_one :event_intake, :conditions => ['event_intakes.is_draft = 1']
  has_many :product_instances, :through => :event_intake
end

class EventIntake < ActiveRecord::Base
  belongs_to :event
  has_many :product_instances, :conditions => ['is_deleted = ?', '0']
end

class ProductInstance < ActiveRecord::Base
  belongs_to :event_intake
end

これが私が得ているMySQLクエリとエラーです:

Mysql2::Error: Unknown column 'event_intakes.is_draft' in 'on clause': 

SELECT DISTINCT `events`.id FROM `events` 
  LEFT OUTER JOIN `event_intakes` product_instances_events_join ON (`events`.`id` = `product_instances_events_join`.`event_id`) 
  LEFT OUTER JOIN `product_instances` ON (`product_instances`.`event_intake_id` = `product_instances_events_join`.`id`) AND event_intakes.is_draft = 1 
WHERE (product_instances.serial_number = '313') ORDER BY events.id DESC LIMIT 0, 50

スルーアソシエーションは、event_intakesテーブルを「product_instances_events_join」としてエイリアスします。ただし、条件event_intakes.is_draftのテーブルは、それに一致するように変更されません。

レール2.3.11を使用していますが、問題はレール3にも同様に当てはまると思います。スルーアソシエーションはhas_oneではなくhas_manyでのみ使用する必要があることを読みましたが、これが原因ではないと思います。問題。

条件を「product_instances_events_join.is_draft=1」に変更した場合、この特定のケースの問題は修正されますが、テーブルエイリアスがない場合は問題が発生します。has_one条件で文字列補間を使用して、正しいテーブル名を取得できれば便利です。次のようなもの:has_one:event_intake、:conditions => ["#{EventIntake.table_name} .is_draft = 1"]エイリアシングが発生してもEventIntakeのtable_nameは変更されないため、上記のコードは機能しないと思います。

私が試したもう1つのことは、クエリを実行する直前に、エイリアシングが発生する前に、has_manyアソシエーションをオンザフライで再定義することです。Event.has_one:event_intake、:conditions => ['product_instances_events_join.is_draft=1']信じてくださいこれでwebrickの問題は実際に修正されましたが、他のスレッドに影響を与える可能性のあるグローバル変数を変更するのと同じだと思うので、マルチスレッドの乗客環境でこのアプローチを使用することを躊躇しています。その上、それはハックです。

誰かがこれを修正する方法について何か提案がありますか?どんな助けでも大歓迎です。

4

1 に答える 1

1

条件を:product_instancesに置くことができます

class Event < ActiveRecord::Base
  has_one :event_intake 
  has_many :product_instances, :through => :event_intake,
               :conditions => ['event_intakes.is_draft = 1']
end

実際にはevent_intakesをフィルタリングするのではなく、関連付け全体をオンまたはオフにするため、has_oneに条件を設定するのは少し厄介なようです。しかし、それはここでのポイントの脇にあると思います。

また、中間の条件でフィルタリングしたい後続の「スルー」アソシエーションがいくつかある場合、これはあまり乾燥していないことを理解しています。それが私がここで偶然見つけた方法です。

于 2013-04-25T00:28:32.713 に答える