这是我第一次使用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是否提供了这样做的方法?
答案 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的惊人力量。