Permalink
Browse files

[engines guide] change comments resource generation

Totally didn't like where this section was going, so scrapped it.

Scaffold is great for some things (lol) but nested resources is definitely not one of them.

Best to walk people through how to do it right, as they would in the real world
  • Loading branch information...
1 parent e6b2e7f commit e537a3fcb1fd16d169889dfbca13eece9cc3bdf1 @radar radar committed Oct 13, 2011
Showing with 33 additions and 54 deletions.
  1. +33 −54 railties/guides/source/engines.textile
View
87 railties/guides/source/engines.textile
@@ -201,83 +201,62 @@ If you'd rather play around in the console, +rails console+ will also work just
h4. Generating a comments resource
-Now that the engine has the ability to create new blog posts, it only makes sense to add commenting functionality as well.
+Now that the engine has the ability to create new blog posts, it only makes sense to add commenting functionality as well. To do get this, you'll need to generate a comment model, a comment controller and then modify the posts scaffold to display comments and allow people to create new ones.
-To do this, you can run the scaffold generator this time and tell it to generate a +Comment+ resource instead, with the table having two columns: a +post_id+ integer and +text+ text column.
+Run the model generator and tell it to generate a +Comment+ model, with the related table having two columns: a +post_id+ integer and +text+ text column.
<shell>
-$ rails generate scaffold Comment post_id:integer text:text
+$ rails generate model Comment post_id:integer text:text
+invoke active_record
+create db/migrate/[timestamp]_create_blorgh_comments.rb
+create app/models/blorgh/comment.rb
+invoke test_unit
+create test/unit/blorgh/comment_test.rb
+create test/fixtures/blorgh/comments.yml
</shell>
-This generator call will generate almost the same files as it did the first time we called it for generating the +Post+ resource, but this time the files will be called things such as +app/controllers/blorgh/comments_controller.rb+ and +app/models/blorgh/comment.rb+.
-
-There's a few things wrong with how this generator has worked. It would be better if the comments resource was nested inside the posts resource in the routes, and if the controller created new comment entries inside a post. These are two very easy things to fix up.
-
-The +resources+ line from this generator is placed into the +config/routes.rb+ by the generator, but you're going to want to have comments nested underneath a post, and so it's a good idea to change these lines in the +config/routes.rb+ file:
-
-<ruby>
-Blorgh::Engine.routes.draw do
- resources :comments
-
- resources :posts
-
-end
-</ruby>
-
-Into these:
-
-<ruby>
- Blorgh::Engine.routes.draw do
- resources :posts do
- resources :comments
- end
- end
-</ruby>
+This generator call will generate just the necessary model files it needs, namespacing the files under a +blorgh+ directory and creating a model class called +Blorgh::Comment+.
-That fixes the routes. For the controller, it's just as easy. When a request is made to this controller, it will be in the form of +post/:post_id/comments+. In order to find the comments that are being requested, the post is going to need to be fetched using something such as:
+To show the comments on a post, edit +app/views/posts/show.html.erb+ and add this line before the "Edit" link:
-<ruby>
-post = Post.find(params[:id])
-</ruby>
+<erb>
+<%= render @post.comments %>
+</erb>
-Then to get the comments for this post it would be as simple as:
+This line will require there to be a +has_many+ association for comments defined on the +Blorgh::Post+ model, which there isn't right now. To define one, open +app/models/blorgh/post.rb+ and add this line into the model:
<ruby>
-post.comments
+has_many :comments
</ruby>
-Alternatively, the query to fetch the comments in actions such as the +index+ action would need to be changed from +Comment.all+ into +Comment.find_all_by_post_id(params[:post_id])+. However, the first way is cleaner and so it should be done that way.
-
-To fetch the post in the controller, add a +before_filter+ into the controller's class definition like this:
+Turning the model into this:
<ruby>
module Blorgh
- class CommentsController < ApplicationController
- before_filter :load_post
- ...
+ class Post < ActiveRecord::Base
+ has_many :comments
end
end
</ruby>
-This +before_filter+ will call the +load_post+ method before every request that comes into this controller. This method should be defined as a +private+ method after all the actions in the controller:
-
-<ruby>
-module Blorgh
- class CommentsController < ApplicationController
- before_filter :load_post
+Because the +has_many+ is defined inside a class that is inside the +Blorgh+ module, Rails will know that you want to use the +Blorgh::Comment+ model for these objects.
- # actions go here
+Next, there needs to be a form so that comments can be created on a post. To add this, put this line underneath the call to +render @post.comments+ in +app/views/blorgh/posts/show.html.erb+:
- private
+<erb>
+<%= render "comments/form" %>
+</erb>
- def load_post
- @post = Post.find(params[:post_id])
- end
- end
-end
-</ruby>
+Next, the partial that this line will render needs to exist. Create a new directory at +app/views/blorgh/comments+ and in it a new file called +_form.html.erb+ with this content to create the required partial:
-With the post being loaded, the queries in the controller need to be altered in order to query within the scope of the relative post. All occurrences of +Comment+ in this controller should now be replaced with +@post.comments+ so that the queries are correctly scoped.
+<erb>
+<%= form_for [@post, @post.comments.build] do |f| %>
+ <p>
+ <%= f.label :text %><br />
+ <%= f.text_area :text %>
+ </p>
+<% end %>
+</erb>
h3. Hooking into application

0 comments on commit e537a3f

Please sign in to comment.