диспетчер комментариев
class CommentsController < ApplicationController
before_action :load_commentable
before_action :checked_logged_in, only: [ :create]
def new
@comment = @commentabl.comments.new
end
def create
@comment = @commentable.comments.new(comment_params)
@comment.user_id = current_user.id
@comment.commenter = current_user.username
if @comment.blank? || @comment.save
flash[:success] = "Commented was created"
ActionCable.server.broadcast 'comment_channel',
commenter: current_user.username,
comment: @comment.content
redirect_to @commentable
else
flash[:danger] = render_to_string(:partial => 'shared/error_form_messaging',
:locals => {obj: @comment},
format: :html)
redirect_to @commentable
end
end
private
def comment_params
params.require(:comment).permit(:content, :commenter, :user_id)
end
def load_commentable
resource, id = request.path.split('/')[1,2]
@commentable = resource.singularize.classify.constantize.find(id)
end
def checked_logged_in
unless logged_in?
flash[:danger] = 'please log in to be able to comment'
redirect_to login_path
end
end
end
моя форма для создания комментария:
<%= form_with model:[commentable, commentable.comments.new], :html => {class: "form-horizontal", role:"form"} , local: true do |form| %>
<div class = "form-group">
<div class = "control-label col-sm-2">
<%= form.label :content, 'Comment' %>
</div>
<div class = "col-sm-8">
<%= form.text_field :content , class: 'form-control', placeholder: "enter your comment here", autofocus: true %>
</div>
</div>
<div class = "form-group">
<div class = "col-sm-offset-2 col-sm-10">
<%= form.submit 'Comment' , class: ' btn btn-primary' %>
</div>
</div>
<% end %>
форма называется в show.html.erb
<h2 class = "text-center">
Title: <%= @article.title %>
</h2>
<div class = "well col-xs-8 col-xs-offset-2">
<div id = "user-info-showpage" align = "center">
Created by: <%= render 'shared/user-info', obj: @article.user %>
</div>
<h4 class = "text-center">
<strong>Description:</strong>
</h4>
<hr />
<%= simple_format(@article.description) %>
<% if @article.categories.any? %>
<p>Categories: <%= render @article.categories %></p>
<% end %>
<div class = "article-actions">
<% if logged_in? && (current_user == @article.user || current_user.admin?) %>
<%= link_to "Delete", article_path(@article), method: :delete,
data: {confirm: "Are you sure you want to delete the article?"},
class: 'btn btn-xs btn-danger' %>
<%= link_to "Edit", edit_article_path(@article), class: 'btn btn-xs btn-success'%>
<%end%>
<%= link_to "View All Articles", articles_path , class: 'btn btn-xs btn-primary'%>
</div>
</div>
<% if logged_in? %>
<div class = "col-xs-8 col-xs-offset-2">
<%#= render partial: 'comments/form', :locals => {commentable: @article} %>
</div>
<%end%>
<div class = "col-xs-8 col-xs-offset-2">
<div id = "comments"></div>
<%= @article.comments.inspect %>
<% @article.comments.each do |c| %>
<div class = "well">
<%= c.content %> by
<%= c.commenter %>
</div>
<%end%>
<div id = "comments"></div>
</div>
Пожалуйста, если нужна дополнительная информация, спросите меня, чтобы я мог предоставить
Примечание: Я не уверен, что эта пустая запись из-за того, что комментарии к комментариям равны нулю, или я что-то пропустил
Я прокомментировал форму рендеринга на странице шоу, и теперь пустая запись исчезла, поэтому моя проблема должна быть связана с form_with
Спасибо за ответ. Я тестировал сборку и получил тот же результат. и я разместил весь код для страницы шоу. Псевдоним сборки новый?, значит, они должны быть одинаковыми, не так ли?
зачем вам <%= @article.comments.inspect %> ставить в вашу форму? Вы можете удалить его, если не хотите видеть #<ActiveRecord...
Это для целей отладки. когда решу вопрос, удалю.
@KickButtowski не могли бы вы поделиться кодом контроллера
так что я до сих пор не понимаю, в чем твоя проблема? Я думаю, что #<ActiveRecord... от commentable.comments.build, потому что это новый комментарий к текущей статье с идентификатором 1.
#<Comment id: nil ... очевидно, что это просто новый объект комментария, который еще не хранится в базе данных.
почему это отображается в представлении?
Наверное, потому что у вас есть <%= @article.comments.inspect %>. Будет ли он отображаться в представлении, если вы удалите этот код?
это будет то же самое. это разные сущности. нам лучше где-нибудь поболтать
@NirajKaushal, извините, я пропустил ваш комментарий. Выполнено
Позвольте нам продолжить обсуждение в чате.





Насколько я понимаю, ты
articles#show, чтобы не отображать пустой HTML-код by _________<div>, потому что comment все еще построен (все еще в памяти) и еще не сохранен (еще не в БД).приложение / просмотры / статьи / show.html.erb
...
<div class = "col-xs-8 col-xs-offset-2">
<div id = "comments"></div>
<% @article.comments.each do |c| %>
<!-- ADD THIS LINE -->
<% if c.persisted? %>
<div class = "well">
<%= c.content %> by
<%= c.commenter %>
</div>
<% end %>
<%end%>
<div id = "comments"></div>
</div>
...
приложение / просмотров / комментарии / _form.html.erb
<%= form_with model:[commentable, Comment.new(commentable: commentable)], :html => {class: "form-horizontal", role:"form"} , local: true do |form| %>
Причина, по которой на странице отображается пустой by _________<div>, заключается в том, что вы «построили» новый comment до того, как вызывается .each. Поскольку они используют одно и то же пространство памяти, build, по сути, также добавляет его в массив в памяти. См. Следующее:
# rails console
article = Article.create!
comment1 = Comment.create!(commentable: article)
# from here, comment1 is then saved already in the DB
# now let's see what happens when you use "build" or "new"
# They have differences, it seem: for details: https://stackoverflow.com/questions/1253426/what-is-the-difference-between-build-and-new-on-rails/1253462
# redefine (to simulate your @article = Article.find(params[:id])
article = Article.find(article.id)
comment2 = article.comments.build
puts article.comments.count
# SQL: Select count(*) FROM ...
# => 1
puts article.comments.size
# => 2
# notice how `count` and `size` are different. `count` value is "DB-based" while `size` is "memory-based". This is because `count` is an `ActiveRecord` method while `size` is a delegated `Array` method.
# now let's simulate your actual problem in the view, where you were looping...
article.comments.each do |comment|
puts comment
end
# => <Comment id: 1>
# => <Comment id: nil>
# notice that you got 2 comments:
# one is that which is already persisted in DB
# and the other is the "built" one
# the behaviour above is to be expected because `.each` is a delegated `Array` method
# which is agnostic to where its items come from (DB or not)
Это причина, по которой на вашей странице "встроенный" комментарий отображается на странице, потому что вы звоните
<%= render partial: 'comments/form', :locals => {commentable: @article} %>
... который вызывает commentable.comments.build
ДО<% "article.comments.each do |c| %>
Если это еще недостаточно ясно, попробуйте поставить
<%= render partial: 'comments/form', :locals => {commentable: @article} %>
... который вызывает commentable.comments.build
ПОСЛЕ<% "article.comments.each do |c| %> ... <% end %>
... и by _________<div> уже не должен появиться.
если комментарий не сохраняется в базе данных, почему он вообще отображается?
@KickButtowski, если вы заметили мой код объяснения выше, он отображается, потому что вы «построили» комментарий, который отображается в представлении в вашем цикле .each. Использование comments.build создаст экземпляр Comment в массиве (в памяти). Это сделано намеренно. Вы можете думать о сборке как о чем-то вроде следующего: article.comments << Comment.new (за исключением того, что он все еще находится в памяти)
Можете показать свой код
show.html.erb? Кстатиcommentable.comments.newдолжен бытьcommentable.comments.build