views:

377

answers:

3

In my Rails application, I have two models, Articles and Projects, which are both associated with a user. I want to add comments to each of these models. What's the best way to structure this?

Here's my current setup:

class Comment < ActiveRecord::Base
  belongs_to :article
  belongs_to :project
end

class Article < ActiveRecord::Base
  belongs_to :user
  has_many :comments
end

class Project < ActiveRecord::Base
  belongs_to :user
  has_many :comments
end

class User < ActiveRecord::Base
  has_many :articles
  has_many :projects
  has_many :comments, :through => :articles
  has_many :comments, :through => :projects
end

Is this the right way to handle the structure? If so, how do I manage the CommentsController to have an article_id if it was created through an Article, and a project_id if it was created through a Project? Are there special routes I should set up?

One final comment: Comments don't always have to have a user. Since this if for my website, I want anonymous viewers to be able to leave comments. Is this a trivial task to handle?

A: 

You could have ArticleComments and ProjectComments with similar structure but stored separately, then create a method that returns both types of comments.

Ben Alpert
+4  A: 

Make Comment a polymorphic model. Then create a polymorphic association.

Here's an example of polymorphic relationship from the Rails wiki and here's a Railscast from the screencast-men Ryan Bates.

Simone Carletti
This seems almost perfect, but how do I handle the creation of a Comment? It's the Controller code that has me confused, and that example doesn't touch on it. For instance, say I have a form on a Project page to leave a comment -- upon submission, how do I associate the comment with that specific Project?
NolanDC
p = Project.find(...); p.comments.create(...)
Simone Carletti
Ah, ok -- I think I understand. Thanks!
NolanDC
You can use separate controllers for article comments and project comments. Find the entity with which the comment is associated and create it in the controller through the entity's #comments association. @project = Project.find(params[:project_id]) @project.comments.create!(params[:comment])
Duncan Beevers
Duncan: So that would go in the ProjectsController, in a new action?
NolanDC
I added the link to a screencast.
Simone Carletti
+1  A: 

You can check out - acts_as_commentable plugin http://github.com/jackdempsey/acts_as_commentable/tree/master

Or you can proceed with polymorphic relation

Ed