Polymorphic Association?

Hi there-

I'm a newbie to this board, RoR, and web development in general. So
please forgive me if this is in the wrong place or if the solution is
really simple...

I'm trying to conceptualize the relationships between a series of
models for a page creation function. What I'd like is to have a
Content Page which consists of a series of Content Blocks. The
Content Blocks act as a list relative to the Content Page. And each
Content Block can be assigned one of 3 types of content: TextContent,
ImageContent, or FileContent. So my current thinking is this:

ContentPage
  has_many :content_blocks, :order => :position

ContentBlock
  belongs_to :content_page
  acts_as_list :scope => content_page_id
  has_one :text_content
  has_one :image_content
  has_one :file_content

TextContent
  belongs_to :content_block

ImageContent
  belongs_to :content_block

FileContent
  belongs_to :content_block

But when I envision looking up a Content Page and its associated
Content Blocks, I feel like it will be difficult to keep going and
find the actual Text, Image, or File data for each Content Block. I
researched polymorphic associations a little bit, but it seems like
that would be a backwards way to approach this, with the Content
Blocks having to belong to the Text, Image, and File Contents.

Anyway, I'm having a really hard time conceptualizing this for some
reason and any help would be greatly appreciated!

Thanks,

Jeff

Hi there-

I'm a newbie to this board, RoR, and web development in general. So
please forgive me if this is in the wrong place or if the solution is
really simple...

I'm trying to conceptualize the relationships between a series of
models for a page creation function. What I'd like is to have a
Content Page which consists of a series of Content Blocks. The
Content Blocks act as a list relative to the Content Page. And each
Content Block can be assigned one of 3 types of content: TextContent,
ImageContent, or FileContent. So my current thinking is this:

ContentPage
  has_many :content_blocks, :order => :position

ContentBlock
  belongs_to :content_page
  acts_as_list :scope => content_page_id
  has_one :text_content
  has_one :image_content
  has_one :file_content

TextContent
  belongs_to :content_block

ImageContent
  belongs_to :content_block

FileContent
  belongs_to :content_block

But when I envision looking up a Content Page and its associated
Content Blocks, I feel like it will be difficult to keep going and
find the actual Text, Image, or File data for each Content Block. I
researched polymorphic associations a little bit, but it seems like
that would be a backwards way to approach this, with the Content
Blocks having to belong to the Text, Image, and File Contents.

Anyway, I'm having a really hard time conceptualizing this for some
reason and any help would be greatly appreciated!

Yes, it would.

Another way to approach it would be with STI (single table
inheritance). You create a Content model (and contents table) and then
subclass it to form your specific content classes:

   class ContentBlock < ActiveRecord::Base
      has_one :content
   end

   class Content < ActiveRecord::Base
      belongs_to :content_block
   end

   class TextContent < Content
   end

   class FileContent < Content
   end

   class ImageContent < Content
   end

You need a "type" column (and a content_block_id of course) in your
contents table.

The nice thing is that content_block.content is polymorphic; it will
be a TextContent, FileContent, or ImageContent object, depending on
what you've assigned to it. You can also put common methods in the
Content class to be shared across all the specific classes.

The downside is that there is only one physical table, so all the
attributes have to go there.

Thanks Bob, I appreciate the response. If I went this direction,
would I be able to bypass the Content model altogether and just have
TextContent, etc. be subclasses of the ContentBlock model?

I guess I'm also interested in how to do this in separate tables as
well, since TextContent, ImageContent, and FileContent will all hold
differing types of information.