Answers:
我的猜测是您的模型如下所示:
class User < ActiveRecord::Base
has_many :reviews
end
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :reviewable, polymorphic: true
end
class Shop < ActiveRecord::Base
has_many :reviews, as: :reviewable
end
由于某些原因,您无法执行该查询。
为了解决这个问题,你需要明确定义之间的关系Review和Shop。
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :reviewable, polymorphic: true
# For Rails < 4
belongs_to :shop, foreign_key: 'reviewable_id', conditions: "reviews.reviewable_type = 'Shop'"
# For Rails >= 4
belongs_to :shop, -> { where(reviews: {reviewable_type: 'Shop'}) }, foreign_key: 'reviewable_id'
# Ensure review.shop returns nil unless review.reviewable_type == "Shop"
def shop
return unless reviewable_type == "Shop"
super
end
end
然后您可以像这样查询:
Review.includes(:shop).where(shops: {shop_type: 'cafe'})
请注意,表名称是shops和不是reviewable。数据库中不应有一个称为reviewable的表。
我相信,这比显式定义join之间的方法更容易,更灵活Review,Shop因为它不仅使您可以按相关字段进行查询,而且还渴望加载。
之所以需要这样做,是因为ActiveRecord无法单独基于可审阅来建立联接,因为多个表代表了联接的另一端,据我所知,SQL不允许您联接以存储的值命名的表在列中。通过定义额外的关系belongs_to :shop,可以为ActiveRecord提供完成连接所需的信息。
:reviewable是Shop。照片属于网店。
belongs_to :shop, foreign_type: 'Shop', foreign_key: 'reviewable_id'
reviews包括急于加载相关的shop使用代码时Review.includes(:shop) ,belongs_to定义 belongs_to :shop, -> { where(reviews: {reviewable_type: 'Shop'}) }, foreign_key: 'reviewable_id' 抛出错误提示missing FROM-clause entry for table "reviews"。我通过以下方式更新belongs_to定义来修复它: belongs_to :shop, -> { joins(:reviews) .where(reviews: {reviewable_type: 'Shop'}) }, foreign_key: 'reviewable_id'
如果收到ActiveRecord :: EagerLoadPolymorphicError,这是因为当仅支持多态关联时includes决定调用。在此处的文档中:http : //api.rubyonrails.org/v5.1/classes/ActiveRecord/EagerLoadPolymorphicError.htmleager_loadpreload
因此,始终preload用于多态关联。需要注意的是:您不能在where子句中查询多态关联(这很有意义,因为多态关联表示多个表。)
@reviews = @user.reviews.includes(:user, :reviewable)
.where('reviewable_type = ? AND reviewable.shop_type = ?', 'Shop', 'cafe').references(:reviewable)
当您将SQL片段与WHERE一起使用时,必须有引用才能加入关联。
作为附录的顶部答案,这是个很好的答案,您也可以:include在关联上指定由于某种原因,如果您所使用的查询不包括模型的表,并且您收到未定义的表错误。
像这样:
belongs_to :shop,
foreign_key: 'reviewable_id',
conditions: "reviews.reviewable_type = 'Shop'",
include: :reviews
如果没有该:include选项,则如果您仅review.shop在上面的示例中访问该关联,则将收到UndefinedTable错误(在Rails 3中进行测试,而不是在4中测试),因为关联会这样做SELECT FROM shops WHERE shop.id = 1 AND ( reviews.review_type = 'Shop' )。
该:include选项将强制执行JOIN。:)
@reviews = @user.reviews.joins("INNER JOIN shops ON (reviewable_type = 'Shop' AND shops.id = reviewable_id AND shops.shop_type = '" + type + "')").includes(:user, :reviewable => :photos)