-
Notifications
You must be signed in to change notification settings - Fork 0
26 Creating Comments
We must have comments! We'll use a gem to do the heavy lifting, rather than building a commenting system from scratch. The gem in question: acts_as_commentable_with_threading
.
Let's add it to our Gemfile, install the bundle, and restart the server.
Gemfile
gem 'acts_as_commentable_with_threading'
$ bundle
AACWT (as we'll abbreviate it) can generate a migration and a Comment
model for you.
$ bin/rails generate acts_as_commentable_with_threading_migration
create db/migrate/20141106191339_acts_as_commentable_with_threading_migration
create app/models/comment.rb
$ bin/rake db:migrate
== 20141106191339 ActsAsCommentableWithThreadingMigration: migrating ==========
-- create_table(:comments, {:force=>true})
-> 0.0082s
-- add_index(:comments, :user_id)
-> 0.0018s
-- add_index(:comments, [:commentable_id, :commentable_type])
-> 0.0021s
== 20141106191339 ActsAsCommentableWithThreadingMigration: migrated (0.0124s) =
To allow comments on posts, we add one line of code to the model.
app/models/post.rb
acts_as_commentable
Restart your Rails console, and let's try adding a comment.
Pick a post, and pick a user. (I've truncated the console output in the following examples.)
[1] pry(main)> post = Post.first
[2] pry(main)> user = User.last
Then build a comment.
[3] pry(main)> comment = Comment.build_from(post, user.id, "First! LOLOLOL")
Now save the comment.
[4] pry(main)> comment.save
Try loading the comment from the post.
[5] pry(main)> post.comment_threads
Does it work? That's worth an incremental commit.
$ git add .
$ git commit -m "Configure acts_as_commentable_with_threading."
In order to create comments in the app, we'll need a route for comments#create
. We can nest that route under the existing routes for posts
.
config/routes.rb
resources :comments, only: :create
Let's add a comment form to our view, below our post partials.
app/views/posts/show.html.erb
<% if user_signed_in? %>
<%= form_for @comment, html: { class: 'comment' } do |f| %>
<fieldset>
<%= f.label :body, 'Add a comment' %><br />
<%= f.text_area :body %>
</fieldset>
<%= f.hidden_field :commentable_type %>
<%= f.hidden_field :commentable_id %>
<%= f.submit class: 'btn btn-default' %>
<% end %>
<% end %>
Notice that I added a CSS class to the form itself, and I specified the text for the label. I also included hidden fields for commentable_type
and commentable_id
. AACWT implements Comment
with polymorphic relationships to other objects. You're encouraged to learn more about polymorphic relationships.
Now let's add a wee bit of CSS.
app/assets/stylesheets.scss
form.comment {
fieldset {
background-color: transparent;
label {
font-size: small;
}
}
}
We need to build @comment
in the controller before the form is rendered.
app/controller/posts_controller.rb
def show
@post = Post.find params[:id]
@comment = Comment.build_from(@post, current_user.id, '') if user_signed_in?
end
We'll need a CommentsController
to actually create comments.
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
post = Post.find params[:comment][:commentable_id]
comment = Comment.build_from post, current_user.id, comment_params[:body]
if comment.save
flash[:notice] = 'Your comment has been added.'
else
flash[:error] = 'There was a problem adding your comment.'
end
redirect_to post
end
private
def comment_params
params.require(:comment).permit(:body, :commentable_name, :commentable_id, :commentable_type)
end
end
Try adding a comment to a text post. Use the console to check that the comment saved. If all is well, let's commit our work.
$ git add .
$ git commit -m "Create comments on posts."