6

这是我第一次使用 Rails,我想知道是否可以在一个 SQL 查询中加载一个多态关联?它们之间的模型和关联足够基本:资产模型/表可以通过多态关联来引用内容(图像、文本或音频),即

资产类 < ActiveRecord::Base
  :belongs_to :content, :polymorphic => true
结尾

图像、文本、音频定义如下:

类图像 < ActiveRecord::Base
  :has_one :asset, :as => :content
结尾

当我尝试加载图像时,这样说:

图像.first(
      :条件 => {:id => id},
      :include => :asset
)

它指定了两个查询,一个用于检索图像,另一个用于检索资产(仅供参考,如果我指定 a 也会发生这种情况:joins)。根据我的理解,ActiveRecord 这样做是因为它不知道 Image 和 Asset 之间存在一对一的关联。有没有办法强制加入并一次性检索 2 个对象?我也尝试过将 join 与自定义选择一起使用,但我最终不得不手动创建 ActiveRecord 模型及其关联。

ActiveRecord 是否提供了一种方法来做到这一点?

4

3 回答 3

2

在挖掘 Rails 源代码后,我发现您可以通过在 select、conditions 或 order 子句中引用当前模型以外的表来强制连接。

所以,如果我在 Asset 表上指定一个订单:

图像.first(
      :条件 => {:id => id},
      :include => :asset,
      :order => "asset.id"
)

生成的 SQL 将使用左外连接和一条语句中的所有内容。我更喜欢内部连接,但我想现在就可以了。

于 2009-09-25T08:30:50.020 回答
1

我自己遇到了这个问题。与优化数据库调用相比,ActiveRecord 更倾向于使 Rubyists(他们甚至可能对 SQL 不太熟悉)更容易与数据库交互。您可能必须在较低级别(例如 DBI)与数据库交互以提高性能。使用 ActiveRecord 肯定会影响您设计架构的方式。

对 SQL 效率的渴望让我开始考虑使用其他 ORM。我还没有找到适合我需要的。即使是那些更倾向于事务 SQL 本身的(例如 Sequel)也有一个沉重的 Ruby API。如果没有类似 Ruby 的 API,我会满足于手动编写我的 T-SQL。我使用 ORM 的真正好处是 M,将(一个或多个表的)结果集映射到对象中。

于 2009-10-04T14:24:19.677 回答
1

(这是针对 Rails 3 语法的。)

MetaWhere 是一个很棒的宝石,可以让 ActiveRecord 的常用域之外的复杂查询变得简单且类似于 ruby​​。(@wayne:它也支持外连接。)

https://github.com/ernie/meta_where

多态连接有点棘手。以下是我使用 MetaWhere 的方法:

Image.joins(:asset.type(AssetModel)).includes(:asset)

事实上,我在我的多态关联类中做了一个方便的方法:

  def self.join_to(type)
    joins(:asset.type(type)).includes(:asset)
  end

所以它总是会查询并急切加载特定类型的资产。我没有尝试在一个查询中将它与多种类型的连接混合。因为多态性使用相同的外键来引用不同的表,所以在 SQL 级别上,您必须将其指定为单独的连接,因为一个连接只连接到一个表。

这仅适用于 ActiveRecord 3,因为您可以使用 AREL 的惊人功能。

于 2011-04-13T21:07:20.883 回答