Sachin
Sachin

Reputation: 277

Stuck trying to build nested commenting system Rails 5

Unsure what to do at this point, I've followed a tutorial but can't get even the comments to post currently. They work just fine if I take all relations/mentions of commentable out of the models. But I would like to build a functionality for a nested commenting system where it's possible to comment on a comment. Here are all the pertinent files + errors.

New comment form located inside comments new.html.erb page

 <div class='form-signin col-md-6 offset-md-3'>
        <%= form_with url: post_comments_path, scope: "comment", local:true do |form| %>

           <div class="form-group"> 
            <%= form.label :body %>
            <%= form.text_area :body, :class => "form-control-lg" %>
            </div>
            <div class="form-group">
            <%= form.hidden_field :user_id, :value =>current_user.id %>
            <%= form.hidden_field :post_id, :value => @post.id %>
            <%= form.hidden_field :commentable_id, :value => @comment.id %>
            <%= form.hidden_field :commentable, :value => @comment.body %>
            </div>

            <%= form.submit %>
        <% end %>
</div>

Comments model

class Comment < ApplicationRecord
  belongs_to :post
  belongs_to :user
  belongs_to :commentable, polymorphic: true
  has_many :comments, as: :commentable
  paginates_per 5

end

Comments controller:

def create
    @post = Post.find(params["post_id"])

    user_id = comment_params["comment"]["user_id"]
    body = comment_params["comment"]["body"]

    @comment = Comment.new(post_id: @post.id, user_id: user_id, body: body )

    if @comment.save
      redirect_to post_path(@post), method: :patch, notice: 'Reply successfully created.'
    else
      redirect_to post_path(@post), notice: @comment.errors.messages

    end
  end

 def comment_params
    params.permit(:post_id, comment: [:user_id, :body] )
  end

The error I get when I try to post a comment currently:

Server Logs:

Started GET "/posts/1" for 127.0.0.1 at 2018-09-27 16:33:56 -0400
Processing by PostsController#show as HTML
  Parameters: {"id"=>"1"}
  Post Load (0.2ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/posts_controller.rb:40
  Rendering posts/show.html.erb within layouts/application
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 143], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:21
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 19], ["LIMIT", 1]]
  ↳ app/views/posts/show.html.erb:45
   (0.4ms)  SELECT COUNT(*) FROM "comments" WHERE "comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2  [["commentable_id", 1], ["commentable_type", "Post"]]
  ↳ app/views/posts/show.html.erb:49
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 19], ["LIMIT", 1]]
  ↳ app/views/posts/show.html.erb:49
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 19], ["LIMIT", 1]]
  ↳ app/views/posts/show.html.erb:54
  Comment Load (0.4ms)  SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2  [["commentable_id", 1], ["commentable_type", "Post"]]
  ↳ app/views/posts/show.html.erb:71
  Rendered posts/show.html.erb within layouts/application (11.8ms)
Completed 200 OK in 49ms (Views: 42.8ms | ActiveRecord: 1.7ms)

Like I said earlier, the comments work just fine without the commentable system, but would like to add this functionality if possible with my current structure. Do not have any gems installed for this function.

Upvotes: 0

Views: 47

Answers (2)

Laertis Pappas
Laertis Pappas

Reputation: 82

First of all you have a security flaw in the above code: <%= form.hidden_field :user_id, :value =>current_user.id %> this is not needed. Please take the current user from the session instead in the controller. With the above code one can change the user id in the view and submit it so the comment will be attached to another user.

The next thing I see is the following:

<%= form.hidden_field :commentable, :value => @comment.body %>

the commentable is your relation why you assign the comment's body there? that should be commentable_type and the value should be the class name of the comment thus: <%= form.hidden_field :commentable_type, :value => @comment.class.name %>

In your controller you do not assign a commentable so the validation fails since a commentable is required.

Moreover since you decided to make the comment polymorphic you don't need a reference to the post anymore. You only need to keep a reference to the commentable.

GoRails should have a great example I really like the instructor (Chris Oliver). You can check it here: https://gorails.com/episodes/comments-with-polymorphic-associations

Please follow the tutorial and make sure you adapt your code accordingly. Hope that helps.

Upvotes: 0

wehdi
wehdi

Reputation: 96

Try to add optional: true

class Comment < ApplicationRecord
 belongs_to :commentable, polymorphic: true, optional: true

In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.

Read this

Upvotes: 1

Related Questions