If you watched both Akira on Rails' Easy Restful Rails screencast and his earlier First Rails 2.0 screencast, you've have probably noticed that the Easy one is missing a feature (actually, it's missing a couple of features). Namely, it misses the comment form on post page.
So, how do you do that using the approach outlined in ERR screencast?
DISCLAIMER I'm not doing things quite as Akita did, because I'm simply describing what I did in my own project. I'll try to replicate this same approach when I have more time. Meanwhile, keep in mind that I'm also using the attribute_fu plugin, that may or may not be relevant to this method.
Now that we've gotten that out of the way, let's get down to coding.
First of all, make sure you've created Comment and Post models, and also installed resource_controller plugin. In your routes.rb file you have:
map.resources :posts, :has_many => :comments
You've also defined polymorphic relationship between Comment and other models (including Post). In Comment model you have this:
belongs_to :commentable, :polymorphic => true, :counter_cache => true
and in Post model:
has_many :comments, :as => :commentable, :dependent => :delete_all
Let's see what that means. :commentable is a set of intermediate references that point to different records from diffrent tables. If you said belongs_to :posts, you could only link comments and posts, and not other stuff you might comment on (like images, or articles, or whatever). Of course, you don't have to define a polymorphic relationship, but Akita did, so I'm just following that path. One other detail. :dependent => :delete_all makes the comments go away once the parent post is deleted. That's how comments generally work, so it's a good thing. ;-)
Next, we define the controller relations as well. In the comments controller, you have this:
belongs_to :post
This is important if you want a polymorphic controller. But don't get cofused here. A polymorphic controller doesn't mean that models are also polymorphic. This should work regardless of the actual model relations.
Now, in the show.html.erb file for the PostsController, I have inserted the form for comments:
<% form_for([@post, Comment.new]) do |f| %>
<%= render :partial => 'comments/form', :locals => { :f => f } %>
<p>
<%= submit_tag "post" %>
</p>
<% end %>
What this does has nothing to do with resource_controller plugin, actually. This is standard code for a nested resource code. Instead of passing a single object, we pass an array ([@post, Comment.new]) where the second member of the array is a new instance of Comment model. I render a form partial from comments directory, but it's contents are fairly standard, so I won't go into that.
This will call the CommentsController (not PostsController) and its create method. So we want the create method to redirect to the parent post's show method. But the default is to redirect to the show method of the controller whose create action was called. Usually, we'd simply edit the create method to give it new redirection target, but since we are using resource_controller, we can't do that. Instead we do something that I found on resource_controller Google group.
In the CommentsController, add the following:
create.wants.html { redirect_to smart_url(parent_url_options) }
As far as I can tell, no modification to the above line is ncessary at all. So it really is a smart_url method. This should work whenever you have to redirect to parent instead of child's show action.
Post new comment