急切加载多态 [英] Eager load polymorphic

查看:27
本文介绍了急切加载多态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Using Rails 3.2, what's wrong with this code?

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

它引发了这个错误:

不能急切加载多态关联:reviewable

Can not eagerly load the polymorphic association :reviewable

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

If I remove the reviewable.shop_type = ? condition, it works.

如何根据 reviewable_typereviewable.shop_type(实际上是 shop.shop_type)进行过滤?

How can I filter based on the reviewable_type and reviewable.shop_type (which is actually shop.shop_type)?

推荐答案

我猜你的模型是这样的:

My guess is that your models look like this:

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

由于多种原因,您无法执行该查询.

You are unable to do that query for several reasons.

  1. ActiveRecord 无法在没有附加信息的情况下构建连接.
  2. 没有名为 reviewable 的表

要解决这个问题,需要明确定义ReviewShop的关系.

To solve this issue, you need to explicitly define the relationship between Review and 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的表.

Notice that the table name is shops and not reviewable. There should not be a table called reviewable in the database.

我相信这比在 ReviewShop 之间显式定义 join 更容易和更灵活,因为它允许你预先加载除了按相关字段查询.

I believe this to be easier and more flexible than explicitly defining the join between Review and Shop since it allows you to eager load in addition to querying by related fields.

之所以有这个必要,是因为ActiveRecord不能单独建立基于reviewable的join,因为多个表代表join的另一端,而SQL,据我所知,不允许你join一个名为存储在列中的值.通过定义额外的关系 belongs_to :shop,您将向 ActiveRecord 提供完成连接所需的信息.

The reason that this is necessary is that ActiveRecord cannot build a join based on reviewable alone, since multiple tables represent the other end of the join, and SQL, as far as I know, does not allow you join a table named by the value stored in a column. By defining the extra relationship belongs_to :shop, you are giving ActiveRecord the information it needs to complete the join.

这篇关于急切加载多态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆