Question | Click to View Answer |
In this quiz, we will make comments as a nested resource of posts. We will use scaffolding to build posts, but will build comments from scratch. Start by generating a new rails project. |
$ rails new nested_resources
|
Generate the Post model with scaffolding and include title and body attributes. |
$ rails generate scaffold Post title:string body:text
|
Create the posts table in the database. |
$ rake db:migrate
|
Generate an empty migration to create the comments table. |
$ rails generate migration CreateComments
|
Update the comment migration file, so the comments table will have body and post_id attributes. |
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :body
t.integer :post_id
t.timestamps
end
end
end
|
Create the comments table in the database. |
$ rake db:migrate
|
Create the comment model. |
Make the comment.rb file in the models directory (the rest of this quiz specifies the file path and it is implied the file should be created if it does not already exist) and add the following code: class Comment < ActiveRecord::Base
attr_accessible :body
end
|
Update the routes file to make comments a nested resource of posts. |
# config/routes.rb:
resources :posts do
resources :comments
end
|
View the routes that are created by nesting resources. |
$ rake routes
Notice that the path for comments will have the post_id in the URL. This will come in handy later. |
Associate the posts and comments models. |
# models/post.rb:
has_many :comments
# models/comment.rb:
belongs_to :post
|
Create an empty comments controller. |
# controllers/comments_controller.rb:
class CommentsController < ApplicationController
end
|
Create a form on the posts#show page to make comments on that particular post. Update the controller code so comments can be saved to the database. |
# controllers/comments_controller.rb:
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.build(params[:comment])
@comment.save
redirect_to @post
end
# controllers/posts_controller.rb
def show
@post = Post.find(params[:id])
@comment = Comment.new
end
# views/posts/show.html.erb:
<%= render 'comments/form' %>
# views/comments/_form.html.erb:
<%= form_for [@post, @comment] do |f| %>
<%= f.label :body %><br>
<%= f.text_area :body %><br>
<%= f.submit %>
<% end %>
|
Make a comment on a post. Open the database in terminal and write an SQL query to list all the comments. |
$ rails db
select * from comments;
|
Notice that the post_id is populated in the database even though we did not have a post_id field in the comments form. How did the comment know what post it is associated with? |
The post_id is added with this line in the comments controller: @comment = @post.comments.build(params[:comment])
|
Create a list of all the comments on the posts/show.html.erb page. |
<ul>
<% @post.comments.each do |comment| %>
<li><%= comment.body %></li>
<% end %>
</ul>
|
Add links to edit a comment on the posts#show page and include the code required to perform this action. |
# controller/comments_controller.rb:
def edit
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
end
def update
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
if @comment.update_attributes(params[:comment])
redirect_to post_path(@post)
else
render :action => :edit
end
end
# views/comments/edit.html.erb:
<%= render "form" %>
# posts/show.html.erb:
<ul>
<% @post.comments.each do |comment| %>
<li><%= comment.body %></li>
<%= link_to "Edit", edit_post_comment_path(:post_id => @post.id, :id => comment.id) %>
<% end %>
</ul>
|
Add links to delete a comment on the posts#show page and include the code required to perform this action. |
# controller/comments_controller.rb:
def destroy
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
@comment.destroy
redirect_to post_path(:id => @post.id)
end
# views/posts/show.html.erb:
<ul>
<% @post.comments.each do |comment| %>
<li><%= comment.body %></li>
<%= link_to "Edit", edit_post_comment_path(:post_id => @post.id, :id => comment.id) %>
<%= link_to "Delete", post_comment_path(:post_id => @post.id, :id => comment.id), :method => :delete %>
<% end %>
</ul>
|