使用Rails 3.2,这段代码有什么问题?

@reviews = @user.reviews.includes(:user, :reviewable)
.where('reviewable_type = ? AND reviewable.shop_type = ?', 'Shop', 'cafe')

它引发此错误:



如果我删除了reviewable.shop_type = ?条件,它将起作用。

如何根据reviewable_typereviewable.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

由于某些原因,您无法执行该查询。

如果没有其他信息,
  • ActiveRecord无法建立联接。
  • 没有称为可审核的表

  • 要解决此问题,您需要显式定义ReviewShop之间的关系。
    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的表。

    我认为,这比在joinReview之间显式定义Shop更加容易和灵活,因为它除了让您通过相关字段查询之外,还使您急于加载。

    之所以需要这样做,是因为ActiveRecord无法单独基于可审阅来建立联接,因为多个表代表了联接的另一端,据我所知,SQL不允许您联接以存储的值命名的表在列中。通过定义额外的关系belongs_to :shop,可以为ActiveRecord提供完成连接所需的信息。

    09-19 00:43