In config/routes.rb:
resources :posts do
resources :comments
end
resources :pictures do
resources :comments
end
I would like to allow for
Ryan Bates covered polymorphic associations in Railscasts #154, but the example was for Rails 2 and Active Record. I managed to get his example working using Rails 3 and Mongoid by making a few changes.
In the Post and Picture models, add the following line:
embeds_many :comments, :as => :commentable
According to the Mongoid associations documentation, all embedded_in
associations are polymorphic. You don't need the commentable_id
and commentable_type
columns mentioned in the Railscast when using Mongoid, because the comment is a child of the commentable. In the Comment model, add the following line:
embedded_in :commentable, :inverse_of => :comment
Setup the routes in config/routes.rb like this:
resources posts do
resources comments
end
resources pictures do
resources comments
end
Add the following method to your comments controller as a private
method. This is identical to Ryan's method:
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
In each of your comments controller actions where you need to find the comment, call the find_commentable method first to get the parent. Once the parent has been found, you can find the comment by ID, by searching through the commentable's comments. For example, in the edit action the code to find the comment would look like this:
@commentable = find_commentable
@comment = @commentable.comments.find(params[:id])
To reduce the repetition of calling find_commentable at the start of every action, you could put a before filter at the top of the controller like this:
class CommentsController < ApplicationController
before_filter :find_commentable
...
And then change the return call in the find_commentable method to:
return @commentable = $1.classify.constantize.find(value)
I haven't encountered any problems using this method, but if you come across any issues please point them out.