急切加载多态 [英] Eager load polymorphic
问题描述
使用 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_type
和 reviewable.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.
- ActiveRecord 无法在没有附加信息的情况下构建连接.
- 没有名为 reviewable 的表
要解决这个问题,需要明确定义Review
和Shop
的关系.
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.
我相信这比在 Review
和 Shop
之间显式定义 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屋!