Add Comment to User and Post Models (Ruby on Rails)

Add Comment to User and Post models (Ruby on Rails)

In your way you should put this:

def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(comment_params)
@comment.user_id = current_user.id #or whatever is you session name
if @comment.save
redirect_to @post
else
flash.now[:danger] = "error"
end
end

And also you should remove user_id from comment_params as strong parameters .
Hope this will help you .

Adding a comment model to associate with a post/user model

Your associations seem fine. The error

NoMethodError in Posts#show undefined method `comments_path'

means that you don't have the route comments_path or Comments#Create. Basically, when you have a form_for with a Comment as the parameter, it assumes you are wanting to go to the create or update route, depending if it's a new record. The easiest thing to do would be to add

resources :comments

to your routes file. However, since you want a comment associated with a post, you want to modify your routes file to have:

resources :posts do
resources :comments
end

Then, change your form to look like this:

<%= form_for [@post, @comment] do |f| %>

So when you submit a form, you will have a params[:post_id] and a params[:id] to play with. Find the Post with the params[:post_id]. Ignore the params[:id] when you're creating a comment, but use it when you're updating a comment.

Edit: Here is a link to some help regarding Nested Resourcing.

Ruby on Rails blog and adding comments to posts and editing and deleting comments

The First argument in form cannot contain nil or be empty is telling you that @comment in <%= form_for @comment do |f| %> is nil. This is because in the edit action of your CommentsController you are setting @post instead of @comment.

Change this to be:

def edit
@comment = Comment.find(params[:id])
end

For deleting a comment, the Couldn't find Comment without an ID is telling you that the value you're passing to find is nil. This is because you're trying to use params[:comment_id] instead of params[:id]. Change the destroy action to:

def destroy
@comment = Comment.find(params[:id])
@comment.destroy
redirect_to '/posts'
end

Update:

Also as per your code, you should change edit and delete links to below

<%= link_to("Edit Comment", edit_comment_path(c)) %>
<%= link_to("Delete Comment", comment_path(c), method: :delete)

You are passing @post.id which is an id of post. Instead you should pass id of the comment using the block variable from your comments.each, noticing that the .id isn't needed here because it can be inferred by Rails.

How can I comments to my posts?

In your post controller show action, make the new comment belong to the post

def show
@post = Post.where(:id => params[:id]).first
if @post.nil?
flash[:error] = "Post does not exist"
redirect_to(root_path)
end
@comment = @post.comments.new # <--- here's the change
end

Then add the post_id field to the form as a hidden field

<%= form_for @comment do |f| %>
<%= f.hidden_field :post_id %>
<%= f.text_area(:content, :size => '20x10', :class => 'textarea') %>
<%= f.submit('Create Post', class: 'button button-primary') %>
<% end %>

And you should be good to go without changing the comment controller create action

Add Comment to User and Post models Rails 4

Short names are easier to read and understand so I will rename your models in my example to Artist, Micropost and Comment

class Artist < ActiveRecord::Base
has_many :microposts, dependent: :destroy
has_many :comments, through: :microposts, dependent: :destroy
end

class Micropost < ActiveRecord::Base
belongs_to :artist
has_many :comments, dependent: :destroy
end

class Comment < ActiveRecord::Base
# I renamed artist to commenter to make it clear that is not the same artist as the one that created the micropost,
# this implies that instead of author_id you will have commented_id in comments table

belongs_to :commenter, :class_name => Artist
belongs_to :micropost
end

### views/artists/show.html.erb ###

<% @artist.microposts.each do |micropost| %>
...
<%= micropost.content %>
...

<% micropost.comments.each do |comment| %>
# here you display comments for each micropost
<%= comment.content %>

# pay attention at the way I builded the comment
<%= form_for(micropost.comments.build) do |f| %>
<%= f.hidden_field :micropost_id %> # this will make the link to your micropost
<%= f.text_area :content %>
<%= f.submit "post comment" %>
<% end %>
<% end %>
<% end %>

In your comments_controller you must assign current logged in artist (the commenter) to your comment.

class CommentsController < ApplicationController
def create
@comment = Comment.new(comment_params)
@comment.commenter = current_artist

if @comment.save
...
end
end

private

def comment_params
params.require(:comment).permit(:micropost_id, :content)
end
end

To avoid N+1 when you load artists, microposts and commenters do something like this:

class ArtistsController < ApplicationController
def show
@artist = Artist.includes(:microposts, :comments => :commenter).find(params[:id])
end
end

In 3-tiered relationship (User-Post-Comment), should user model include has_many :comments?

Edit:

Regarding these queries:

(1) query all other users' comments on this particular post for this particular user's comments.

And (2) query all the original user's comments on this particular post.

For (1), you will need to change the comments table to have a comment_id, which is the comment its responding to.

Then you can have in comment.rb: belongs_to :comment.

To get all the comments on a given post for a given comment, you'll query like this:

Comment.where(comment: parent_comment, post: some_post) # parent_comment & post must be set somewhere

This should return all comments that are responding to parent_comment for some_post.

For (2), you will need to add a user_id column to comments table, and add the following associations:

# comment.rb
belongs_to :user

# user.rb
has_many :comments

Then query the user's comments like this:

some_user.comments.where(post: some_post) # some_user & some_post must be set beforehand

This will return all comments made by some_user on some_post.

Original answer:

If the comments table does not have a user_id column; then you cannot have it associated with a user with belongs_to :user.

If you want a way to get all comments made by a user on any post, you can use has_many :comment, through: :posts in the User model. For example:

# user.rb

has_many :posts
has_many :comments, through: :posts

#post.rb
belongs_to :user
has_many :comments

#comment.rb
belongs_to :post

Now you can do something like User.find(1).comments and you'll get all comments made by said user.

Whether you should have this or not depends on your use-case; do you need to get all comments made by a user? if yes, then you should do that way. Otherwise your original models were fine.

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.



Related Topics



Leave a reply



Submit