Steven
Steven

Reputation: 502

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

I finally was able to associate a user model with a post model with:

def create
 @post = Post.new(post_params)
 @post.user = current_user

Right now I'm trying to create a comment in the Post#Show page but continue to receive an error regarding my form. The two errors I'm running into are:

NoMethodError in Posts#show undefined method `comments_path' 

when I have @comment = Comment.new in Post#show. When it's removed I get:

ArgumentError in Posts#show First argument in form cannot contain nil or be empty

What could possibly be wrong with my form? Also if someone can recommend a better way to associate my 3 models (basically have a user_id and a post_id when comment is created I'm open for suggestions). My comment form is going to appear within the Post#Show page. My current code is:

Comment Model

belongs_to :user
belongs_to :post

User Model

has_many :posts
has_many :comments

Post Model

has_many :comments
belongs_to :user

Comment Controller

class CommentsController < ApplicationController
 before_action :find_comment, only: [:show, :edit, :update, :destroy]

 def index
  @comments = Comment.all
 end

 def new
  @comment = Comment.new
 end

 def create
  @post = Post.find(params[:id])
  @comment = @post.comments.build(comment_params)
  @comment.user = current_user

  if @comment.save
   flash[:notice] = "Successfully created..."
   redirect_to comments_path
  else
   flash[:alert] = "failed"
   redirect_to root_path
  end
 end

 def show
 end

 def edit
 end

 def update
  if @comment.update
   flash[:notice] = "You updated your comment"
  else
   flash[:alert] = "Failed to update"
 end

 def destroy
  @comment.destroy
  redirect_to '/'
 end

 private

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

  def comment_params
   params.require(:comment).permit(:comment)
  end
end

Post Controller

class PostsController < ApplicationController
  before_action :find_post, only: [:show, :edit, :update, :destroy]

  def index
    @posts = Post.all
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)
    @post.user = current_user
    if @post.save!
      flash[:notice] = "Successfully created..."
      redirect_to posts_path
    else
      flash[:danger] = "failed to add a post"
      render 'new'
    end
  end

  def show
  end

  def edit
  end

  def update
    if @post.update
      flash[:notice] = "Successfully updated"
      redirect_to post_path
    else
      flash[:alert] = "Failed to update Post"
      redirect_to :back
    end
  end

  def destroy
    if @post.destroy
      flash[:notice] = "Successfully delete"
      redirect_to posts_path
    else
      flash[:danger] = "Wasn't able to delete Blog post."
      redirect_to :back
    end
  end

  private
    def find_post
      @post = Post.find(params[:id])
    end

    def post_params
      params.require(:post).permit(:title, :body, :description)
    end
end

Post#Show View

<%= render '/comments/form' %>

Comment#form

<%= form_for @comment do |f| %>
  <%= f.label :comment, "Title" %>
  <%= f.text_field :comment, placeholder: "Write a comment" %>
  <%= f.submit "Submit" %>
<% end %>

If there is something missing please ask me to update my post. Thank you all who help me better understand my problem.

Upvotes: 0

Views: 705

Answers (1)

Ryan K
Ryan K

Reputation: 4053

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.

Upvotes: 1

Related Questions