Possible to create polymorphic relationship with STI models?

I would like to associate a â??productâ?? model with 3 models inherited from
â??imageâ??: part, action and accessory.

I have it working with Has_many :through relating products to images
through attachments, I then have to determine the â??typeâ?? of the STI
extension. This means i have to go product.images. While this is ok, i
can see it getting tricky when i want to go products.images <<
Part.create(:name => “test”). (im on edge rails so the << should work)

I would like to have the parts, actions or accessories collections
available under products eg products.parts.

I have the following tables: product - attachment - images, each with
their own model.
I also have 3 models that inherit from image eg Part < Image.

Ive been following the hasmanythrough article ‘the other side of
polymorphic’. As well as read most of the other articles…but i just
dont get how this will work.

According to the docs has_many ignores class_name when using :through.
“Options for :class_name and :foreign_key are ignored, as the
association uses the source reflection.”

  1. Attachment tables:

  2. (polymorphic attempt)

  3. create_table “attachments”, :force => true do |t|

  4. t.column “product_id”, :integer

  5. t.column “attachable_id”, :integer

  6. t.column “attachable_type”, :string

  7. t.column “created_at”, :datetime

  8. t.column “created_by”, :integer

  9. end

  10. Models:

  11. class Product < ActiveRecord::Base

  12. has_many :parts, :through => :attachments,

  13. :class_name => :parts,

  14. :conditions => “attachments.attachable_type = ‘Image’”

  15. end

  16. class Attachment < ActiveRecord::Base

  17. belongs_to :product

  18. belongs_to :attachable, :polymorphic => true

  19. belongs_to :part, :class_name => “Part”,

  20. :source => :image,

  21. :foreign_key => “attachable_id”

  22. end

  23. class Part < Image

  24. has_many :attachments, :as => :attachable

  25. has_many :products, :through => :attachments

  26. end

Through the console i can do the following:

  1. Part.find(:first).products.count
  2. 1

But this fails

  1. Product.find(:first).parts
  2. ActiveRecordHasManyThroughSourceAssociationNotFOundError

  3. associations.rb:876: in ‘parts’

This is what i need to work and it doesnt. The many models are the ones
that can access the shared models…but not the reverse…hmmm. Thats a
pain if your shared model

Also, i still have no idea how to create the association with
polymorphism. Its easy with just :through ! Im going to go back to the
:through association as it makes more sense to me.

Would love to hear that im really close and just need to change x and
y… =)

As an update:
With the assistance of the new features of edge rails i ahve been able
to do the follwoing, brilliant !

product = Product.find(:first)
product.images << Part.create(:name => “test part”)

Remembering that part is a STI instance of image.

Which means the only thing i really need to do now is create a way to
get the parts, accessories or actions associated with a product.
Enabling the following to work:

product.parts (returns parts from images table)

i have an idea that it should be some sort of association extension in
the products model…just not sure how to do it. Any ideas ?

GOT IT !!

it was just this… finally !

class Product < ActiveRecord::Base

through

#products - attachments - images
has_many :attachments

has_many :parts, :through => :attachments,
:source => :image,
:conditions => “images.type =‘Part’”

has_many :accessories, :through => :attachments,
:source => :image,
:conditions => “images.type =‘Accessory’”

has_many :actions, :through => :attachments,
:source => :image,
:conditions => “images.type =‘Action’”