渴望在ActiveRecord中加载多态关联

时间:2009-09-25 04:37:58

标签: ruby-on-rails activerecord polymorphic-associations

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

class Asset < ActiveRecord::Base
  :belongs_to :content, :polymorphic => true
end

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

class Image < ActiveRecord::Base
  :has_one :asset, :as => :content
end

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

Image.first(
      :conditions => {:id => id},
      :include => :asset
)

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

ActiveRecord是否提供了这样做的方法?

3 个答案:

答案 0 :(得分:2)

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

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

Image.first(
      :conditions => {:id => id},
      :include => :asset,
      :order => "asset.id"
)

生成的SQL将在一个语句中使用左外连接和所有内容。我本来希望有一个内连接,但我想现在这样做了。

答案 1 :(得分:1)

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

对SQL效率的渴望让我想到了使用其他ORM。我没有找到一个适合我的需求。即使那些更倾向于转换SQL本身(例如Sequel)的人也有很多Ruby API。我会满足于没有类似Ruby的API,只需手动编写我的T-SQL。我使用ORM的真正好处是M,将结果集(一个或多个表)映射到对象中。

答案 2 :(得分: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

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

这仅适用于ActiveRecord 3,因为您可以获得AREL的惊人力量。