Reputation: 311
Please help me to display all the comments for certain thread.
I use the following gems: 'awesome_nested_set', 'acts_as_commentable_with_threading'
For example, I create scaffold 'message'. And I try for certain message unit make comments thread.
MessagesController:
def show
# to display all comments
@all_comments = @message.comment_threads
p '-----------------'
p @all_comments
p @all_comments.count
# for form new comment
@message = Message.find(params[:id])
@user_who_commented = current_user
@comment = Comment.build_from( @message, @user_who_commented.id, "Hey guys this is my comment!" )
end
views/messages/show.html.erb:
<p>
<strong>message Title:</strong>
<%= @message.title %>
</p>
<p>
<strong>message Body:</strong>
<%= @message.body %>
</p>
<%= render 'comments/form' %>
<% @all_comments.each do |comment| %>
<div>
<%= @comment.title %>
<%= @comment.body %>
</div>
<% end %>
schema:
create_table "comments", force: :cascade do |t|
t.integer "commentable_id"
t.string "commentable_type"
t.string "title"
t.text "body"
t.string "subject"
t.integer "user_id", null: false
t.integer "parent_id"
t.integer "lft"
t.integer "rgt"
t.datetime "created_at"
t.datetime "updated_at"
end
in this table after add new comment i(and gem) filled via create-action fields:
title,
body,
user_id,
lft,
rgt
CommentsController:
def create
comment = Comment.new(comment_params)
comment.user = current_user
comment.save
if comment.update_attributes(user: current_user)
redirect_to messages_path, notice: 'Comment was successfully created.'
else
render :new
end
end
def new
@comment = Comment.new
end
The form to add a new message worked ok, but all comments for certain messages are not displayed.
ps: log:
Started GET "/messages/1" for 127.0.0.1 at 2015-10-23 14:09:47 +0300
Processing by MessagesController#show as HTML
Parameters: {"id"=>"1"}
Message Load (0.1ms) SELECT "messages".* FROM "messages" WHERE "messages"."id" = ? LIMIT 1 [["id", 1]]
"-----------------"
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = ? AND "comments"."commentable_type" = ? [["commentable_id", 1], ["commentable_type", "Message"]]
#<ActiveRecord::Associations::CollectionProxy []>
(0.1ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."commentable_id" = ? AND "comments"."commentable_type" = ? [["commentable_id", 1], ["commentable_type", "Message"]]
0
CACHE (0.0ms) SELECT "messages".* FROM "messages" WHERE "messages"."id" = ? LIMIT 1 [["id", "1"]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 2]]
Rendered comments/_form.html.erb (1.0ms)
Rendered messages/show.html.erb within layouts/application (1.9ms)
Completed 200 OK in 40ms (Views: 34.5ms | ActiveRecord: 0.4ms)
Upvotes: 1
Views: 521
Reputation: 76774
Why are you outputting in the show action?
You should only be defining @instance_variables
and passing them to the view for rendering:
#config/routes.rb
resources :users do
resources :comments, only: [:show, :create]
end
#app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def show
@message = Message.find params[:id]
end
end
#app/views/messages/show.html.erb
<%= @message.title %>
<%= render @message.comments if @message.comments.any? %>
#app/views/messages/_comment.html.erb
<% comment.title %>
<% comment.body %>
This will output the top-level comments.
If you wanted nested comments, I'd highly recommend using acts_as_tree
. This gives you access to "child" objects (set with a parent
column in your table), which allows you to do the following:
<%= render @message.comments if @message.comments.any? %>
#app/views/messages/_comment.html.erb
<%= render comment.children if comment.children.any? %>
1. Vars
When you run a loop (<% @message.comments.each do |comment| %>
), you need to use the local variable within the block:
@message.comments.each do |comment|
comment.title
comment.body
end
You're currently using -- should be @comment.title
comment.title
-
2. Comment Creation
You can make comment creation through a form embedded in the messages#show
view:
#app/views/messages/show.html.erb
<%= render "comments/new" %>
You'd have to make sure you set your @comment
variable:
#app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def show
@message = Message.find params[:id]
@comment = Comment.new
end
end
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
@comment = Comment.new comment_params
end
private
def comment_params
params.require(:comment).permit(:title, :body)
end
end
You're doing this already, of course - I think it could be cleared up a lot.
-
3. Migration
Finally, you're using a polymorphic association in your table. This should not be used in this case; you should have a standard foreign_key
as follows:
create_table "comments", force: :cascade do |t|
t.integer "message_id"
t.string "title"
t.text "body"
t.string "subject"
t.integer "user_id", null: false
t.integer "parent_id"
t.datetime "created_at"
t.datetime "updated_at"
end
This would allow for the following:
#app/models/message.rb
class Message < ActiveRecord::Base
has_many :comments
end
#app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :message
belongs_to :user
acts_as_tree
end
Upvotes: 2