views:

113

answers:

4

I'm trying to make a comment system, identical to the stackoverslow's one. There's a 1-st level comment, and a bunch of a second level comments, attached to it. The first straightforward idea that came up in order to do that, was to create a separate model, sub_comment. But I still got this feeling, that I should inherit the initial comment's properties, only adding a simple comment-id joint.

I'm still a Rails newbie, so the question is - can I do that? How? Is it a simple

class sub_comment < comment

model inheritance? But of course, I'm gonna need all the controller methods in order to add/delete these sub-comments. Or should I make a single comment model, where the 1-st level comment will have a nil as a parent?

What would be the right solution?

PS. Fell free to advice any book that covers the subject. I'm on a self education here, so I'd love to read everything that could clarify any future app architecture question.

+2  A: 

I find it easier to have a simple tree structure with two pointers to make back-tracking easier:

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  acts_as_tree
  belongs_to :post

  named_scope :top_level, :conditions => { :parent_id => nil }
end

This makes it easy to retrieve all comments for a particular Post:

@comments = @post.comments.top_level

You can even pull up multiple levels of comments using AJAX or by fetching one layer after the next:

# Repeat while comments are found
loop do
  level = @post.comments.find(:all, :conditions => { :parent_id => @comments.collect(&:id) })

  if (level.empty?)
    break
  else
    @comments += level
  end
end

These can be sorted as required for presentation purposes.

tadman
A: 

One option is to have two separate classes, and put the shared behavior in a module. That way you're not doing Single Table Inheritance (which is what your inheritance example would mean, and it's something I have had problems with) but you also aren't duplicating code.

Michael Sofaer
> put the shared behavior in a moduleI' not sure I understand what do you mean. Could you explain, please?
gmile
A: 

Conceptually, you're trying to create a self referencing association. This is certainly the cleanest way to go as you don't have extra tables and models to worry about, though it can be complex to setup.

I'd recommend checking out the Self Referential Association Railscast, it will walk you step by step how to get started.

Mike Buckbee
A: 

The short and sweet answer is that I would go with your "parent id is nil" methodology for top-level comments and clearly sub comments would have parent id's. Remember, DRY rules the day in the Rails world. If you can use one class (in this case it makes sense), you should.

MattC