0

With Rails 3 out I was wondering if there was some new way of doing a has_many :through association with a polymorphic model? If not what is the best way of doing it?

Here's what I'm working with

class Page < ActiveRecord::Base
end

class Text < ActiveRecord::Base
end

class Picture < ActiveRecord::Base
end

Text and pictures are content that belong to one or more pages -- Each page has one or more content elements (either Text or Picture). I'd like to be able to do this:

page.content => ["text item 1", "text item 2", "picture 1"]
picture.pages => ["page 3", "page 7"]

As I mentioned above I'm working with Rails 3. Any ideas?

LDK
  • 2,555
  • 5
  • 27
  • 40

2 Answers2

1

There's no difference in Rails 3 and 2.

class Page < ActiveRecord::Base
  belongs_to :text  # foreign key - text_id
  belongs_to :picture     # foreign key - picture_id
end
class Text < ActiveRecord::Base
  has_many : pictures
  has_many :pictures, :through => :pages
end
class Picture < ActiveRecord::Base
  has_many :assignments
  has_many :texts, :through => :pages
end

Second Idea

Your last comment got me thinking that you might have a ton of content_types, or moreso, that the content_types might be able to be generated client-side.

Here's an alternative, why not make just one model, Page - And make it so that it has attributes to reflect its content_type. Then you can make relations with them like so..

@show_texts = Page.find(:all).select{ |p| p.text != nil }.collect{|p| p.id}.inspect

And so on and so forth.. Just an idea. To be honest, I would try and refactor that code above for a SQL friendly version because that's quite a few methods to hit the DB with.

Trip
  • 26,756
  • 46
  • 158
  • 277
  • That's only a one-to-many. I need a many-to-many. I should also note that in the example above I only have 2 content types, but I could have many more... – LDK Sep 07 '10 at 00:48
  • It may be best to just ignore the polymorphic way, and do as you suggest above. However, as I add more content types, Page will have lots of "belongs_to" statements... – LDK Sep 07 '10 at 01:22
  • I'm not sure I understand your bigger picture. Are the models themselves going to be generated client side? How many 'content_types' will you have? This will at least serve you well for quite a few. I'm going to update above for an alternative. – Trip Sep 07 '10 at 01:42
  • The above solution is certainly an interesting idea, I'll give it some thought. – LDK Sep 07 '10 at 02:22
1

I'd use HMT and STI:

class Page < ActiveRecord::Base
  has_many :assets, :through => :page_components

  def content
    self.assets
  end
end

class PageComponent < ActiveRecord::Base
  # could also use HABTM
  belongs_to :page
  belongs_to :asset
end

class Asset < ActiveRecord::Base
  has_many :pages, :through => :page_components
end

class Text < Asset
  # inherits .pages association method from Asset
end

class Picture < Asset
  # so does this.
end

# class Video < Asset...
Eric
  • 2,539
  • 18
  • 23