Ruby on Rails - Adding comments to post
As a comment can belong to a single post only, you do not need an association table (post_comments). You just need a simple one-to-many relationship.
Your post comment would be:
class Post < ActiveRecord::Base
has_many :comments
...
end
And comment would be like this:
class Comment < ActiveRecord::Base
belongs_to :post
...
end
Just make sure that you have the necessary post_id
column in the comments
table (you can check the db/schema.rb
file). If that is missing, you can use the following migration to add it:
class AddPostIdToComments < ActiveRecord::Migration
def change
add_column :comments, :post_id, :integer
add_index :comments, :post_id
end
end
You also need to make sure you keep somewhere the reference to the post, whenever a user tries to create a comment to a post. You can add this in a hidden field to your comments/new.html.erb
template. You could set the hidden field in the new
action, in PostsController, after passing it through the URL.
So, in your posts/show.html.erb
template you would have:
<%= link_to "Add Comment", new_comment_path(post_id: @post.id) %>
In your new
action, in PostsController
:
def new
@comment = Comment.new(post_id: params[:post_id])
end
And finally the hidden field in your form would be:
<%= f.hidden_field :post_id %>
Finally, add the post_id parameter to the list of permitted parameters in CommentsController
.
Adam 'Sacki' Sackfield
Currently studying programming. Starting with CS50, currently on C. Also have a grasp on HTML, CSS and a little JS
Updated on June 04, 2022Comments
-
Adam 'Sacki' Sackfield almost 2 years
Trying to learn RoR. Currently adding comments to posts by user. So far I have a posts model, comments model and post_comments model (to associate the two). So for in 'rails console' I can run: (say I set p = Post.first and c = Comment.first)
p.comments << c
This forms an association so it works in the console. I just can't seem to get the comments to form this association from the UI. So far I am creating the comments at "comments/new" (not sure if this is the issue. Do they need to be created on the "show view" for "post").
Here are some code snippets
Controllers comments_controller.rb
class CommentsController < ApplicationController def index @comment = Comment.all end def new @comment = Comment.new end def create @comment = Comment.new(commentParams) if @comment.save flash[:success] = "Comment successfully added" redirect_to comments_path(@comment) else render 'new' end end def show @comment = Comment.find(params[:id]) end private def commentParams params.require(:comment).permit(:comment) end end
posts_controller
class PostsController < ApplicationController before_action :setPost, only: [:edit, :update, :show, :destroy, :sold] before_action :requireUser, except: [:index, :show] before_action :requireSameUser, only: [:edit, :update, :destroy, :sold] def index @posts = Post.paginate(page: params[:page], per_page: 20) end def new @post = Post.new end def create @post = Post.new(postParams) @post.user = currentUser if @post.save flash[:success] = "Post successfully added." redirect_to post_path(@post) else render 'new' end end def update if @post.update(postParams) flash[:success] = "Post successfully updated." redirect_to post_path(@post) else render 'edit' end end def show end def edit end def sold @post.toggle(:sold) @post.save redirect_to post_path(@post) end def destroy @post.destroy flash[:danger] = "Item successfully deleted." redirect_to posts_path end private def postParams params.require(:post).permit(:title, :price, :description, category_ids:[]) end def setPost @post = Post.find(params[:id]) end def requireSameUser if currentUser != @post.user and !currentUser.admin flash[:danger] = "You can only edit or delete your own items" redirect_to root_path end end end
Models comment.rb
class Comment < ActiveRecord::Base belongs_to :post_comments belongs_to :user belongs_to :post end
post_comment.rb
class PostComment < ActiveRecord::Base belongs_to :post belongs_to :comment end
post.rb
class Post < ActiveRecord::Base belongs_to :user has_many :post_categories has_many :categories, through: :post_categories has_many :post_comments has_many :comments, through: :post_comments validates :title, presence: true, length: { minimum: 4, maximum: 20 } validates :description, presence: true, length: { maximum: 1000 } validates :user_id, presence: true
end
Views posts/show.html.erb
<p>Comments: <%= render @post.comments %></p>
This renders the partial below
comments/_comment.html.erb <%= link_to comment.name, comment_path(comment) %>
Finally is the new comment page as it is.
comments/new.html.erb
<h1>New Comment</h1> <%= render 'shared/errors', obj: @comment %> <div class="row"> <div class="col-xs-12"> <%= form_for(@comment, :html => {class: "form-horizontal", role: "form"}) do |f| %> <div class="form-group"> <div class="control-label col-sm-2"> <%= f.label :comment %> </div> <div class="col-sm-8"> <%= f.text_area :comment, rows: 3, class: "form-control", placeholder: "Please enter a comment", autofocus: true %> </div> </div> <div class="form-group"> <div class="center col-sm-offset-1 col-sm-10"> <%= f.submit class: "btn btn-primary btn-lg" %> </div> </div> <% end %>
Any help would be greatly received.
Update
Log
Started GET "/posts/2" for ::1 at 2016-01-15 12:39:55 +0000 Processing by PostsController#show as HTML Parameters: {"id"=>"2"} [1m[36mPost Load (0.1ms)[0m [1mSELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1[0m [["id", 2]] [1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]] [1m[36m (0.1ms)[0m [1mSELECT COUNT(*) FROM "posts" WHERE "posts"."user_id" = ?[0m [["user_id", 1]] [1m[35mCategory Exists (0.1ms)[0m SELECT 1 AS one FROM "categories" INNER JOIN "post_categories" ON "categories"."id" = "post_categories"."category_id" WHERE "post_categories"."post_id" = ? LIMIT 1 [["post_id", 2]] [1m[36mCategory Load (0.0ms)[0m [1mSELECT "categories".* FROM "categories" INNER JOIN "post_categories" ON "categories"."id" = "post_categories"."category_id" WHERE "post_categories"."post_id" = ?[0m [["post_id", 2]] Rendered categories/_category.html.erb (0.2ms) [1m[35mComment Load (0.1ms)[0m SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 2]] Rendered comments/_comment.html.erb (0.1ms) Rendered posts/show.html.erb within layouts/application (6.5ms) [1m[36mCategory Load (0.1ms)[0m [1mSELECT "categories".* FROM "categories"[0m Rendered layouts/_navigation.html.erb (0.9ms) Rendered layouts/_messages.html.erb (0.1ms) Rendered layouts/_footer.html.erb (0.1ms) Completed 200 OK in 52ms (Views: 50.3ms | ActiveRecord: 0.5ms)