views:

653

answers:

2

This is my first time using Rails and I was wondering if it's possible to load a has one polymorphic association in one SQL query? The models and associations between them are basic enough: An Asset model/table can refer to a content (either an Image, Text, or Audio) through a polymorphic association, i.e.

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

and the Image, Text, Audio are defined like this:

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

When I try to load an Image, say like this:

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

It specifies two queries, one to retrieve the Image and another to retrieve the Asset (FYI, this happens also if I specify a :joins). Based on my understanding, ActiveRecord does this because it doesn't know there's a one-to-one association between Image and Asset. Is there a way to force a join and retrieve the 2 objects in one go? I've also tried using join with a custom select, but I end up having to create the ActiveRecord models manually and their associations.

Does ActiveRecord provide a way to do this?

A: 

After digging through the Rails source I've discovered that you can force a join by referencing a table other than the current model in either the select, conditions or order clauses.

So, if I specify an order on the Asset table:

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

The resulting SQL will use a left outer join and everything in one statement. I would have preferred an inner join, but I guess this will do for now.

Wayne See
A: 

I ran up against this issue myself. ActiveRecord leans more toward the end of making it easy for Rubyists (who may not even be all too familiar with SQL) to interface with the database, than it does with optimized database calls. You might have to interact with the database at a lower level (e.g. DBI) to improve your performance. Using ActiveRecord will definitely affect how you design your schema.

The desire for SQL efficiency got me thinking about using other ORMs. I haven't found one to suit my needs. Even those that move more toward transact SQL itself (e.g. Sequel) have a heavy Ruby API. I would be content without a Ruby-like API and just manually writing my T-SQL. The real benefit I'm after with an ORM is the M, mapping the result set (of one or more tables) into the objects.

Mario