2009-09-25 40 views
6

这是我第一次使用Rails,我想知道是否有可能在一个SQL查询中加载一个多态关联?这些模型和它们之间的关联是基本够用了:一个资产模型/表可以参考内容(无论是图片,文字或音频)通过一个多态关联,即在ActiveRecord中急切加载多态关联

 
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 
)

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

ActiveRecord是否提供了一种方法来执行此操作?

回答

1

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

所以,如果我指定的资产表中的顺序:

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

生成的SQL会使用一个左外连接,并在一个声明中的一切。我本来希望有一个内部连接,但我想现在会这样做。

1

我碰到了这个问题我自己。 ActiveRecord更倾向于使Rubyists(可能甚至不太熟悉SQL)与数据库接口相比,更容易实现与优化数据库调用的接口。您可能必须与较低级别的数据库(例如DBI)交互以提高性能。使用ActiveRecord一定会影响你如何设计你的模式。

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

+0

我通常不再使用ORM。这是一个抽象,我没有做得很好。 – Mario

1

(这是为Rails 3语法。)

MetaWhere是用于制造复杂的查询是ActiveRecord的通常的域容易和红宝石等的室外一个真棒宝石。 (@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的惊人力量。