Inheritance design question

I’m new to ruby rails and am trying to design my first real rails web
app.

The app is intended to model a shareware business. It will provide a
place where users can learn about new projects, track their progress,
and provide feedback. Here’s a simplified list of the model objects that
I’ll need:

Project - has title, description, creation, modification.
Release - has title, description, creation, modification belongs to
project, has tasks
Task - has title, description, creation, modification belongs to
project, belongs to release
Forum - has title, description, creation, modification has topics
Topic - has title, description, creation, modification

The key requirement is that I want these models to share some common
behavior:

  • they all have a title, description, creation date, and modification
    date
  • i want a site wide rss feed that will include changes to Projects,
    Releases, Tasks… all mixed together
  • i want to maintain a full text search index accross all of these
    models. So the search results will include Projects, Releases, Tasks…
  • i want to do this the “right” way, and want to make it easy for other
    people to extend the system and add their own model objects that will
    also share the same common behavior.

Inheritance seems like the perfect answer. I can add a page class that
all of the above models inherit from. The page class would have these
attributes and behaviors:

Page

  • has title
  • has description
  • knows how to turn self into rss feed item
  • knows how to turn self into string for text indexing

The knows how behaviors would need to be polymorphic since a subclass
might define new attributes that would also need to show up in the full
text index.

So that’s what I want, but I’m not sure what the best way to model this
in rails is. I don’t think single-table inheritance will work in this
cases because the number of subclasses should be open ended and will
each add many of their own attributes.

It might be that (I’m getting these terms from the Agile Web D.
with Rails book) strait inheritance using the “abstract_class” method is
the right solution. As I understand it that would allow each concrete
class to have it’s own table. But it would require a lot of duplication,
for example I think in my db.schema each concrete model would need to
define all the common attributes (title, description, creation,
modification) and that would be painful if I wanted to add additional
common attributes such as created_by (id of some user). I’m also not
really sure if using strait inheritance will allow me to say things like
Page.find_by_title(“some title”) and return a mixed list of matching
subclass instances.

The last option is to use polymorphic associations. So I would change my
Page model to look like this:

Page

  • has title

  • has description

  • knows how to turn self into rss feed item

  • knows how to turn self into string for text indexing

The last option is to use polymorphic associations. So I would change my
Page model to look like this:

Page

  • has title

  • has description

  • knows how to turn self into rss feed item

  • knows how to turn self into string for text indexing

Grrg… accidentally hit the entry key and my above post was posted
before I finished…I’ll post more in a sec.

… continuing from above.

Using polymorphic associations I could associate each page with a
delegate Model object that the page would use to modify it’s behavior.
Page class have one model model to look like this:

Page

  • has title
  • has description
  • has one delegate
  • delegate id
  • delegate type
  • knows how to turn self into rss feed item
  • knows how to turn self into string for text indexing

And each of the models would declare themselves as (Project for
example)

Project

  • delegate of page
    Release
  • delegate of page

This approach would mean that Pages are real model objects that I’m sure
can be searches and even uses without having a delegate set. But it also
makes many of my models a bit more complicated since models such as
Project, Release… will require two objects (a Page and the delegate
model) instead of one.

Thank you very much if you’ve read this far. And please point me in the
right direction.

  • what am I not thinking about that I should be thinking about?
  • am i reinventing the wheel, are there other ruby rails projects that
    are already doing something similar that I could learn from?

Thank you very much for any thoughts that you can offer.

Jesse

inheritance is overused… it should be used when the subclass is a more
specific instance of the base class in a natural way.

Ferrari < Car
Dog < Animal
Tennis < Sport

A [Project] is not naturally related to a [Page], it’s only displayed on
it
but there is no logical relationship of any kind.

In your case I would use a ruby module

module PageItem
attr_accessor :title, :description
def to_rss
#
end

end

for example like this:

class Release < ActiveRecord::Base
include PageItem
belongs_to :project

end

2007/2/6, Jesse G. [email protected]:

Peter E. wrote:

inheritance is overused… it should be used when the subclass is a more
specific instance of the base class in a natural way.

Ferrari < Car
Dog < Animal
Tennis < Sport

A [Project] is not naturally related to a [Page], it’s only displayed on
it
but there is no logical relationship of any kind.

Peter,

Thanks… I really do know this stuff, but in all the confusion of a new
language and programming model I got subclass happy. Thanks for getting
me back on track. In your example what would the final database schema
look like?

create_table “project”, :force => true do |t|
t.column “title”, :string
t.column “description”, :text
end

or more like:

create_table “project”, :force => true do |t|
end

create_table “page_item”, :force => true do |t|
t.column “tagged_id”, :integer
t.column “tagged_type”, :string
t.column “title”, :string
t.column “description”, :text
end

Am I correct that it could be implemented either way?

In this case it seems to make the most sense to just store the data in
the project table since title and description are important parts of the
project.

But on the other hand that means that I’ll have a lot of model objects
that are all declaring the same basic set of attributes over and over
again (title, description, created_at…). I could get rid of that by
storing things in the database the second way, but it’s a bit more
complex and slower I would imagine.

So are their any suggestions or rules of thumb to help with this kind of
decision?

Thanks,
Jesse