João Mateus
João Mateus

Reputation: 115

RoR - Form only works once

I'm building a forum app where users can create posts and comment them, at this point the post functionally works fine but the comment form only works once and from then on the post page crashes showing the following error:

NoMethodError in Post#show

undefined method `to_key' for # Did you mean? to_set to_ary

through rails console i can see that the comment was saved.

here is the terminal error:

ActionView::Template::Error (undefined method `to_key' for #<Comment::ActiveRecord_Relation:0x007fb845e9cca8>
Did you mean?  to_set
               to_ary):
     7: <h3>Reply to thread</h3>
     8: 
     9:  <div class="comments_form">
    10:     <%= form_for @comment, url: new_comments_path(@post), method: :post, remote: true do |f| %>
    11:       <%= f.label :title %><br>
    12:     <%= f.text_field :title, placeholder: "Type the comment title here" %><br>
    13:     <%= f.label :content %><br>

app/views/post/show.html.erb:10:in `_app_views_post_show_html_erb__4054771198415677123_70214711817160'

here is the form:

<%= form_for @comment, url: new_comments_path(@post), method: :post, remote: true do |f| %>
    <%= f.label :title %><br>
    <%= f.text_field :title, placeholder: "Type the comment title here" %><br>
    <%= f.label :content %><br>
    <%= f.text_area :content, placeholder: "Type the comment content here" %><br>
    <%= f.submit %>
<% end %>

rails mention that error is in this line of the form:

<%= form_for @comment, url: new_comments_path(@post), method: :post, remote: true do |f| %>

the comment_controller.rb:

class CommentController < ApplicationController
  before_action :set_comment, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user! 

  def index
    @comments = Comment.all
  end

  def new
    @comment = Comment.new
  end    

  def create 
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(params[:comment].permit(:comment))
    @comment.user = current_user
    @comment.assign_attributes(comment_params)

    if @comment.save
      format.html { redirect_to @link, notice: 'Comment was successfully created.' }
      format.json { render json: @comment, status: :created, location: @comment }
    else
      format.html { render action: "new" }
      format.json { render json: @comment.errors, status: :unprocessable_entity }
    end 
  end

  def destroy
    @comment.destroy
    respond_to do |format|
      format.html { redirect_to :back, notice: 'Comment was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

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

    def comment_params
      params.require(:comment).permit(:post_id, :content, :title, :user_id)
    end
end

the routes.rb:

devise_for :users
  root                              to: 'post#index'

  #Posts
  get    '/posts/new',             to: 'post#new' 
  get    '/post/:id',              to: 'post#show',      as: 'show'
  get    '/post/:id/edit',         to: 'post#edit',      as: 'edit'
  post   '/post',                  to: 'post#create'
  put    '/post/:id',              to: 'post#update',    as: 'update'
  delete '/post/:id',              to: 'post#destroy',   as: 'delete' 

  #Comments
  post  '/post/:post_id',  to: 'comment#create', as: 'new_comments'

and the post_controller:

class PostController < ApplicationController
  def index
    if params[:user].blank?
      @posts = Post.all.order("created_at DESC")
    else
      posts = Post.where(user_id: @user_id).order("created_at DESC")
    end
  end


  before_action :authenticate_user!
  before_action :find_post, only: [:show, :edit, :update, :destroy]

  def show
    if Comment.where(post_id: @post.id).present?
      @comment = Comment.where(post_id: @post.id)
    else
      @comment = Comment.new
    end
  end

  def new
    @post = Post.new  
  end

  def create
    @post = Post.new
    @post.user_id = current_user.id.to_i
    #Post.create(title: title.string, content: content.string, user_id: current_user.id)

    @post.assign_attributes(post_params)

    if @post.save
      flash[:notice] = "Successfully created post!"
      #Post.create(title: title.string, content: content.string, user_id: current_user.id)
      redirect_to show_path(@post)
    else
      flash[:alert] = "Error creating new post!"
      render :new
    end
  end

  def edit
  end

  def update
    @post.assign_attributes(post_params)
    if @post.changed?
      @post.save
      redirect_to show_path(@post)
    else
      render edit_path(@post)
    end
  end

  def destroy
    @post.destroy
    redirect_to root_path#, notice: “Post destroyed”
  end

  private
  def post_params
     params.require(:post).permit(:title, :content, :user_id)
  end

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

Thanks in advance for your help.

Upvotes: 0

Views: 57

Answers (1)

Tarek N. Elsamni
Tarek N. Elsamni

Reputation: 1837

I think replacing this line:

<%= form_for @comment, url: new_comments_path(@post), method: :post, remote: true do |f| %>

with this:

<%= form_for @post.comments.new, url: new_comments_path(@post), method: :post, remote: true do |f| %>

Should fix the issue!

Upvotes: 1

Related Questions