Sch*_*ovi 13 polymorphism activerecord join ruby-on-rails preload
我的问题是以下.如何从多态模型加入belongs_to关联
有情况
opinion.rb
class Opinion < ActiveRecord::Base
belongs_to :opinionable, :polymorphic => true
belongs_to :category
end
Run Code Online (Sandbox Code Playgroud)
answer.rb
class Answer < ActiveRecord::Base
has_many :opinions, :as => :opinionable
end
Run Code Online (Sandbox Code Playgroud)
我该怎么办?
Opinion.joins(:opinionabe).所有
它会抛出
ArgumentError:如果不指定多态类,则无法创建多态的belongs_to连接!
我如何具体说明我想加入哪个班级?
第二个问题.如何预加载?
Opinion.preload(:opinionable).所有
工作良好.它将对belongs_to中的每个类进行查询.
但.如果我想做点什么的话
Opinion.preload(:opinionable =>:answer_form).all
有问题,因为一个模型有这种关联,第二个没有.所以它会抛出异常.
那我怎么能做点什么呢
Opinion.preload(:answer =>:answer_form,:another_belongs_to_model).all
?
谢谢,大卫!
小智 15
其实如果你这样做的话
belongs_to :opinionable_answer, :foreign_key => :opinionable_id, :class_name => "Answer", conditions: { opinions: { opinionable_type: "Answer"}}
Run Code Online (Sandbox Code Playgroud)
那么你可以做到
Opinion.joins(:opinionable_answer).where(answers: { awesome: true})
Run Code Online (Sandbox Code Playgroud)
Via*_*kov 14
看起来您没有opinionable_type:string为Opinion模型指定列.
尝试以这种方式更新您的迁移:
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
Run Code Online (Sandbox Code Playgroud)
这将解决你的第二个问题,Opinion.preload(:opinionable).all应该运作良好.
您不能在多态关联上进行连接,因为它们可以位于不同的表中,这些表在Opinion加载模型后检测到.这就是为什么模型需要列opinionable_type.
如果您尝试这样做,您将获得下一个例外
ActiveRecord::EagerLoadPolymorphicError:不能急切地加载多态关联: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
Run Code Online (Sandbox Code Playgroud)
例:
Opinion.by_type(Answer).to_sql
=> "SELECT \"opinions\".* FROM \"opinions\" JOIN answers ON answers.id = opinions.opinionable_id AND opinions.opinionable_type = 'Answer'"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14238 次 |
| 最近记录: |