THE CHALLENGE: How would you do this: has_many :through & polymorphic associations

Hi,

I have a category model and several other models that I want to
categorize.
Categories are organised in a hierarchy.

class Category < ActiveRecord::Base
  acts_as_tree
end

class User < ActiveRecord::Base
end

class Image < ActiveRecord::Base
end

I am quite sure that I am going to have additional models (like User
and Images) that I want to categorize later on.
It should be possible to assign a category to more than one object.
For example I have a category "new" and I want to assign this category
to several user and image records.

So many Images and Users could have many categories and vice versa.

I thought maybe it is possible to implement this with a
has_many :through association in combination with polymorphic => true,
but until now I could not fiqure out how to declare this in the models
and how my migrations have to look like...

Thanks for your help.

Feurio

I believe you'll want to add an addition model for the join table that
uses polymorphic associations like this:

class CategorizedItem < ARec::Base
  belongs_to :category
  belongs_to :categorizable, :polymorphic=>true
end

class Category < ARec::Base
  acts_as_tree
  has_many :categoriezed_items

has_many :categorizables, :through=>:categorized_items, :source=>:categorizable
end

class User < ARec::Base
  has_many :categorized_items, :as=>:categorizable # could be has_one
end

class Image < ARec::Base
  has_many :categorized_items, :as=>:categorizable # could be has_one
end

You can use the :source option (as in Categories has_many :through) to
identify which association to use from the join table.

HTH,
AndyV

I created the model like described by you above.

For the CategorizedItem model I used the following migration:

class CreateCategorizedItems < ActiveRecord::Migration
  def self.up
    create_table :categorized_items do |t|
      t.references :categorizable, :null => false, :polymorphic =>
true
      t.timestamps
    end
  end

  def self.down
    drop_table :categorized_items
  end
end

use the has_many_polymorphs plugin

You're missing the 'category' half of the references:

class CreateCategorizedItems < ActiveRecord::Migration
  def self.up
    create_table :categorized_items do |t|
      t.references :categorizable, :null => false, :polymorphic =>true
      t.references :category, :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table :categorized_items
  end
end

Sorry, still not working...

c = Category.find(943302162)
=> #<Category id: 943302162, name: "computer_science", description:
"Informatik", parent_id: 2061879279, created_at: "2008-03-18
09:53:21", updated_at: "2008-03-18 09:53:21">

c.categorizables
ActiveRecord::HasManyThroughAssociationPolymorphicError: Cannot have a
has_many :through association 'Category#categorizables' on the
polymorphic object 'Categorizable#categorizable'.
        from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/reflection.rb:187:in `check_validity!'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/associations/has_many_through_association.rb:6:in
`initialize'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/associations.rb:1032:in `new'
        from /usr/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/associations.rb:1032:in `categorizables'
        from (irb):9

What I have now...

The migration files:

Hi,

thanks everybody for the help.
I got it working now with the plugin has_many_polymorphs.

Would have been nice to get it working with standard rails, too. But
also I was googling and used some reference books like the rails way
or agile webdevelopment with rails I could find a working solution...

Feurio