Form_with производит первую запись как nil

диспетчер комментариев

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 производит первую запись как nil

Пожалуйста, если нужна дополнительная информация, спросите меня, чтобы я мог предоставить

Примечание: Я не уверен, что эта пустая запись из-за того, что комментарии к комментариям равны нулю, или я что-то пропустил

Я прокомментировал форму рендеринга на странице шоу, и теперь пустая запись исчезла, поэтому моя проблема должна быть связана с form_with

Form_with производит первую запись как nil

Можете показать свой код show.html.erb? Кстати commentable.comments.new должен быть commentable.comments.build

Thanh 24.12.2018 05:48

Спасибо за ответ. Я тестировал сборку и получил тот же результат. и я разместил весь код для страницы шоу. Псевдоним сборки новый?, значит, они должны быть одинаковыми, не так ли?

Kick Buttowski 24.12.2018 05:51

зачем вам <%= @article.comments.inspect %> ставить в вашу форму? Вы можете удалить его, если не хотите видеть #<ActiveRecord...

Thanh 24.12.2018 05:56

Это для целей отладки. когда решу вопрос, удалю.

Kick Buttowski 24.12.2018 05:56

@KickButtowski не могли бы вы поделиться кодом контроллера

Niraj Kaushal 24.12.2018 06:00

так что я до сих пор не понимаю, в чем твоя проблема? Я думаю, что #<ActiveRecord... от commentable.comments.build, потому что это новый комментарий к текущей статье с идентификатором 1.

Thanh 24.12.2018 06:00
#<Comment id: nil ... очевидно, что это просто новый объект комментария, который еще не хранится в базе данных.
Thanh 24.12.2018 06:03

почему это отображается в представлении?

Kick Buttowski 24.12.2018 06:05

Наверное, потому что у вас есть <%= @article.comments.inspect %>. Будет ли он отображаться в представлении, если вы удалите этот код?

Thanh 24.12.2018 06:06

это будет то же самое. это разные сущности. нам лучше где-нибудь поболтать

Kick Buttowski 24.12.2018 06:07

@NirajKaushal, извините, я пропустил ваш комментарий. Выполнено

Kick Buttowski 24.12.2018 06:25

Позвольте нам продолжить обсуждение в чате.

Thanh 24.12.2018 06:57
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
12
100
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Насколько я понимаю, ты

Ожидать:

  • на странице articles#show, чтобы не отображать пустой HTML-код by _________<div>, потому что comment все еще построен (все еще в памяти) и еще не сохранен (еще не в БД).

Решение 1:

приложение / просмотры / статьи / 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>
...

Решение 2 (лучше, но все же это временное решение):

приложение / просмотров / комментарии / _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> уже не должен появиться.

если комментарий не сохраняется в базе данных, почему он вообще отображается?

Kick Buttowski 24.12.2018 19:45

@KickButtowski, если вы заметили мой код объяснения выше, он отображается, потому что вы «построили» комментарий, который отображается в представлении в вашем цикле .each. Использование comments.build создаст экземпляр Comment в массиве (в памяти). Это сделано намеренно. Вы можете думать о сборке как о чем-то вроде следующего: article.comments << Comment.new (за исключением того, что он все еще находится в памяти)

Jay-Ar Polidario 24.12.2018 19:55

Другие вопросы по теме