views:

735

answers:

2

Is there a way to directly reference (using rails directly, without resorting to a lot of custom SQL) a relation that is nested behind a polymorphic relation? In the below example, is there a way to define a has_many relation in User that references LayerTwo?

I'd like to do (in User)

has_many :layer_twos, :through => layer_ones

but this approach doesn't take into the account of the previously specified has_many relations through the polymorphic relation. Any suggestions? It may not be possibly through the existing rails conventions, but figured I'd defer the question to people smarter then myself.

class CreateOwners < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.timestamps
    end
    create_table :owners do |t|
      t.timestamps
      t.references :owned, :polymorphic => :true
      t.references :user
    end     
    create_table :layer_ones do |t|
    end
    create_table :layer_twos do |t|
      t.references :layer_one
    end
  end
end


class Owner < ActiveRecord::Base
  belongs_to :user
  belongs_to :owned, :polymorphic => true
end

class User < ActiveRecord::Base
  has_many :owners
  has_many :layer_ones, :through => :owners, :source => :owned, :source_type => 'LayerOne'
end

class LayerOne < ActiveRecord::Base
  has_many :owners, :as => :owned
  has_many :layer_twos
end

class LayerTwo < ActiveRecord::Base
  belongs_to :LayerOne
end
+1  A: 

As far as I know, ActiveRecord does not support :through a :through relationship. You can work around this using some tricks and hacks, such as creating a VIEW which remaps the relationship into a more direct one, which can simplify your ActiveRecord model at the expense of database complexity.

Polymorphic associations are particularly ornery.

tadman
Thanks just wanted to be verify that with someone else.
Scott Markwell
+1  A: 

I'm not sure of its support for nesting through polymorphic asociations but it might be worth checking out the nested_has_many_through plugin, which from the README:

…makes it possible to define has_many :through relationships that go through other has_many :through relationships, possibly through an arbitrarily deep hierarchy. This allows associations across any number of tables to be constructed, without having to resort to find_by_sql (which isn't a suitable solution if you need to do eager loading through :include as well).

fractious
Yes, this will work. You just have to be careful not to nest too deeply and bog down your app. I wrote a blog post showing the step-by-step: http://kconrails.com/2010/01/28/nesting-has_many-through-relationships-in-ruby-on-rails/
Jaime Bellmyer