Polymorphic associations in Rails
and the hoops you sometimes have to jump through...
Recently I've run across this strange error in Rails:
ActiveRecord::HasManyThroughAssociationPolymorphicThroughError:
Cannot have a has_many :through association 'Info#shares' which goes through the polymorphic association 'Info#content'.
To explain what gives rise to this, let me shed some more light on the models involved.
class Info < ActiveRecord::Base
#...
belongs_to :content, :polymorphic => true
#...
end
class SomeInfo < ActiveRecord::Base
#...
has_one :info, :as => :content
has_many :shares, :as => :shareable
#...
end
#...
has_one :info, :as => :content
has_many :shares, :as => :shareable
#...
end
class Share < ActiveRecord::Base
#...
belongs_to :shareable, :polymorphic => true
#...
end
So it turns out you can't do this:
class Info < ActiveRecord::Base
#...
belongs_to :content, :polymorphic => true
has_many :shares, :through => :content
#...
end
class Info < ActiveRecord::Base
#...
belongs_to :content, :polymorphic => true
#...
belongs_to :shareable, :polymorphic => true
#...
end
So it turns out you can't do this:
class Info < ActiveRecord::Base
#...
belongs_to :content, :polymorphic => true
has_many :shares, :through => :content
#...
end
Which is a bit wierd. Rails has no problem loading the intermediatry model:
Info.content works just fine
Similarly, Content.shares works fine. I fail to see why Info.shares should be a problem.
To get around this is actually quite simple, given that content.shares works. Simply delegate...
#...
belongs_to :content, :polymorphic => true
delegate :shares, :to => :content, :prefix => false, :allow_nil => true
#...
end
#...
end
that's it. Now info.shares works fine.
You can also define a method like this inside Info:
def shares
content.shares
end
but I find the delegate cleaner and less obtrusive.




