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

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

它引发了这样一个错误:

无法Eager 加载多态关联:可查看

如果我删除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

由于几个原因,您无法执行该查询.

  1. 如果没有其他信息,ActiveRecord无法生成联接.
  2. 没有称为reviewable的表

要解决这个问题,需要明确定义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的表.

我认为这比显式地定义ReviewShop之间的join更容易、更灵活,因为除了通过相关字段进行查询之外,它还允许您快速加载.

之所以有必要这样做,是因为ActiveRecord无法仅基于reviewable构建联接,因为多个表代表联接的另一端,而据我所知,SQL不允许您联接以列中存储的值命名的表.通过定义额外关系belongs_to :shop,您为ActiveRecord提供了完成连接所需的信息.

Ruby-on-rails相关问答推荐

在Ruby on Rails中获取堆栈级别太深错误(&Q)

无法在 Rails 中使用 wkhtmltopdf 写入临时文件

Rails:关于yields

Heroku 应用程序上的远程 mysql 数据库

Rails 3 应用程序的 MySQL 集群 (NDB) 与 MySQL 复制 (InnoDB):优点/缺点?

rails 3.2 迁移无法在更改方法中向 create_table 添加索引

Rails - 设计 - 登录时出现错误消息?

有没有办法在模型而不是视图中使用复数()?

Rails 3 中图像路径的完整 url

为什么我要使用 unicorn 或 thin 而不是 WEBrick 用于开发目的?

如何将变量传递给render_to_string?

关于在不适合任何地方的 Rails 应用程序中放置类的指南

Ruby on Rails:调试 rake 任务

Rails:立即渲染并退出

按周/月/等和 ActiveRecord 分组?

从 Rails 中的 ActiveRecord::RecordNotFound 救援

如何在 Rails 迁移中判断数据库类型?

Ruby 中有与 slice 函数相反的函数吗?

Ruby 1.87 与 1.92 Date.parse

是否可以输出rake db:migrate产生的 SQL 更改脚本?