使用Rails 3.2,这段代码有什么问题?
@reviews = @user.reviews.includes(:user, :reviewable)
.where('reviewable_type = ? AND reviewable.shop_type = ?', 'Shop', 'cafe')
它引发此错误:
如果我删除了
reviewable.shop_type = ?
条件,它将起作用。如何根据
reviewable_type
和reviewable.shop_type
(实际上是shop.shop_type
)进行过滤? 最佳答案
我的猜测是您的模型如下所示:
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提供完成连接所需的信息。