Hotwire Turbo 流返回 head :no_content

3

我有一个带有帖子和评论的系统,每个 Post 都有多个 Comment。我试图设置 turbostream,以便在您发表评论时立即显示。

一切都正常,因为数据已持久化到数据库中,但似乎 turbo stream 没有正确返回。当我点击“评论”按钮时,什么也不会改变,并且对于 CommentsController#create,我会收到一个 :no_content 的消息。

  ↳ app/controllers/comments_controller.rb:11:in `create'
[ActiveJob] Enqueued Turbo::Streams::ActionBroadcastJob (Job ID: b0be3a08-d7bb-4216-aac5-2f274a22dcbf) to Async(default) with arguments: "Z2lkOi8vY2lhby9Qb3N0LzM", {:action=>:append, :target=>"comments", :locals=>{:comment=>#<GlobalID:0x00007fa94123baf8 @uri=#<URI::GID gid://ciao/Comment/16>>}, :partial=>"comments/comment"}
[ActiveJob] Enqueued Turbo::Streams::ActionBroadcastJob (Job ID: 382e45b4-7a8f-4c8c-9e48-819fab0c19c4) to Async(default) with arguments: "Z2lkOi8vY2lhby9Qb3N0LzM", {:action=>:replace, :target=>#<GlobalID:0x00007fa9401ea938 @uri=#<URI::GID gid://ciao/Comment/16>>, :locals=>{:comment=>#<GlobalID:0x00007fa9401ea0f0 @uri=#<URI::GID gid://ciao/Comment/16>>}, :partial=>"comments/comment"}
No template found for CommentsController#create, rendering head :no_content
Completed 204 No Content in 37ms (ActiveRecord: 8.5ms | Allocations: 8931)

Turbo 看起来已经能创建评论并将其发送回浏览器网络标签中的评论 POST 请求,但我想知道为什么会有 :no_content,以及为什么评论在页面刷新之前不会显示。

Place.rb

class Post < ApplicationRecord
  belongs_to :place
  has_many :comments
  broadcasts
end

Comment.rb

class Comment < ApplicationRecord
  belongs_to :post
  broadcasts_to :post
end

comment_controller.rb

def new
    @comment = @post.comments.new
  end

  def create
    @comment = current_user.comments.create!(comment_params)
    respond_to do |format|
      if @comment.save
         format.turbo_stream do
             render turbo_stream: turbo_stream.append(@comment, partial: 'comments/comment', locals: { comment: @comment })
        end
        format.html { redirect_to @comment.post.place }
      end
    end
  end


在该帖子中,我将评论呈现为一个局部视图:
 <div class="post__comments--inner">
   <%= render '/comments/show', post: post %>
 </div>

接下来是comments/_show.html.erb文件

  <%= turbo_stream_from post %>
  <%= render post.comments %>
  <% puts post.comments %>
  <div class="comments__post">
    <%= turbo_frame_tag "new_comment", src:  new_post_comment_path(post), target: "_top" %>
  </div>

_comment.html.erb

<div class="comment" id="<%= dom_id comment %>">
  <%= comment.content %>
</div>

new.html.erb

<%= turbo_frame_tag "new_comment", target: "_top" do %>
  <%= form_with model: [@comment.post, @comment], class: "comment-row__form",
     data: { controller: "reset_form", action: "turbo:submit-end->reset_form#reset" }  do |form| %>
      <%= form.text_area :content, class: "comment-form--input form-control", data: {target: "comments.body"} %>
      <%= form.hidden_field :post_id, value: @comment.post.id %>
      <%= form.submit "comment", class: "btn btn-primary mt-2 mt-sm-0 ml-sm-3" %>
 
  <% end %>
<% end %>

我认为我可能找到了问题所在,但是不确定为什么会发生。日志中的最后一条信息是:

Turbo::StreamsChannel transmitting "<turbo-stream action=\"replace\" target=\"comment_36\"><template>  <div class=\"comment\" id=\"comment_36\">\n    <div class=\"comment__user\">\n

我认为应该使用 action=\"append\" 而不是替换,特别是因为页面上当前不存在comment_36


你在该块中没有渲染任何内容,例如 format.turbo_stream { render turbo_stream: turbo_stream.append(@comment) }。 - Joel Blum
我只是从Hotwire演示中复制了以下代码:respond_to do |format| format.turbo_stream format.html { redirect_to @room } end我添加了一个渲染块,它成功返回,但没有任何内容被附加。我已经更新了我的问题以反映这些更改。 - tfantina
由于这是一条新评论,确实需要追加。 - Joel Blum
这就是为什么我感到困惑,为什么 Turbo Streams 频道说该操作是替换。 - tfantina
我可能提供了一个不好的代码片段,请尝试我的答案。 - Joel Blum
1个回答

5

请尝试按照文档中的示例进行操作:

 respond_to do |format|
  format.turbo_stream do
    render turbo_stream: turbo_stream.append(:comments, partial: "comments/comment",
      locals: { comment: @comment })
  end
 end

这会将其附加到您的HTML中具有ID“comments”的div上。

谢谢你的原始评论,这是朝着正确方向迈出的重要一步。我认为仍然没有渲染任何内容的原因与target="comments"的指定有关,因为页面上每篇文章都有一个评论字段,我不认为Turbo知道在哪里添加。 - tfantina
确实,它正在寻找一个具有DOM ID“comments”的元素进行附加。 - Joel Blum
如果有帮助到其他人,请不要忘记包括 render turbo_stream: - James Klein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接