2011-04-28 72 views
13

我的問題是以下。我怎樣才能加入belongs_to的關聯從多態模型Rails加入或預加載belongs_to協會從多態模型

有情況

opinion.rb

class Opinion < ActiveRecord::Base 
    belongs_to :opinionable, :polymorphic => true 
    belongs_to :category 
end 

answer.rb

class Answer < ActiveRecord::Base 
    has_many :opinions, :as => :opinionable 
end 

我該怎麼辦以下

Opinion.joins(:opinionabe).all

它會扔

ArgumentError: You can't create a polymorphic belongs_to join without specifying the polymorphic class!

我如何具體哪一類我想加入?

第二個問題。如何預加載它?

Opinion.preload(:opinionable).all

工作正常。它將爲belongs_to中的每個類執行查詢。

但是。如果我想做類似

Opinion.preload(:opinionable => :answer_form).all

有問題,因爲一個模型有這個關聯,第二個沒有。所以它會拋出異常。

所以,我怎麼可以這樣做

Opinion.preload(:answer => :answer_form, :another_belongs_to_model).all

謝謝,大衛!

回答

13

看起來好像您還沒有爲您的意見模型指定opinionable_type:string列。

嘗試以這種方式來更新您的遷移:

class CreateOpinions < ActiveRecord::Migration 
    def self.up 
    create_table :opinions do |t| 
     t.integer :opinionable_id 
     t.string :opinionable_type 

     # ... other fields 

     t.timestamps 
    end 
    end 

    def self.down 
    drop_table :opinions 
    end 
end 

這將解決你的第二個問題,並Opinion.preload(:opinionable).all應該很好地工作。

不能加入多態關聯,因爲它們可以位於不同的表中,在加載模型後會檢測到這些表。那爲什麼模型需要列opinionable_type

如果試圖這樣做,你會得到一個異常

ActiveRecord::EagerLoadPolymorphicError : Can not eagerly load the polymorphic association :opinionable

UPD:增加魔法加入^ _^

class Opinion < ActiveRecord::Base 
    belongs_to :opinionable, :polymorphic => true 

    belongs_to :opinionable_answer, :foreign_key => :opinionable_id, :class_name => "Answer" 

    scope :by_type, lambda { |type| joins("JOIN #{type.table_name} ON #{type.table_name}.id = #{Opinion.table_name}.opinionable_id AND #{Opinion.table_name}.opinionable_type = '#{type.to_s}'") } 
end 

例子:

Opinion.by_type(Answer).to_sql 
    => "SELECT \"opinions\".* FROM \"opinions\" JOIN answers ON answers.id = opinions.opinionable_id AND opinions.opinionable_type = 'Answer'" 
+0

Polyporhic工作正常,我(在表中的id和類型列)。得到你的解釋爲什麼加入不起作用。我錯過了模型不知道belongs_to中的哪些類的事實。 – Schovi 2011-04-28 08:54:42

+0

有想法。有可能是這樣的嗎?我知道班級Opinion.joins([:opinionable,Answer])? – Schovi 2011-04-28 09:03:57

+0

如果你知道具體的類,你可以在'Opinion'模型中添加如'belongs_to:opinionable_answer,:foreign_key =>:opinionable_id,:class_name =>「Answer」'。然後'Opinion.joins(:opinionable_answer)'應該可以正常工作。 – 2011-04-28 09:19:41

15

其實,如果你只是做

belongs_to :opinionable_answer, :foreign_key => :opinionable_id, :class_name => "Answer", conditions: { opinions: { opinionable_type: "Answer"}} 

那麼你可以做

Opinion.joins(:opinionable_answer).where(answers: { awesome: true}) 
+0

非常適合我! – Acco 2013-02-04 01:12:31

+0

謝謝!按預期工作:) – JCorcuera 2014-10-13 16:54:25