我猜你的模特是这样的:
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
由于几个原因,您无法执行该查询.
- 如果没有其他信息,ActiveRecord无法生成联接.
- 没有称为reviewable的表
要解决这个问题,需要明确定义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的表.
我认为这比显式地定义Review
到Shop
之间的join
更容易、更灵活,因为除了通过相关字段进行查询之外,它还允许您快速加载.
之所以有必要这样做,是因为ActiveRecord无法仅基于reviewable构建联接,因为多个表代表联接的另一端,而据我所知,SQL不允许您联接以列中存储的值命名的表.通过定义额外关系belongs_to :shop
,您为ActiveRecord提供了完成连接所需的信息.