【Ruby on Rails】【Turbo Streams】idの指定有無で、挙動が変わることを確認した
はじめに
コメント編集機能をHotwireの機能の一つであるTurbo Streamsで実装しました。
当初非同期処理を実装したい箇所のidをしていなかったため、コメント編集の挙動が予期していない挙動となっておりました。
今後もTurbo Streamsで非同期処理を実装する予定があるため、記事にまとめております。
ご参考になりましたら幸いです。
環境
Rails 7.1.3.4
hotwired/stimulus: 3.2.2
hotwired/turbo-rails: 8.0.4
idの指定有無による挙動の違い
イメージしていたコメント編集の挙動は下記の通りでした。
しかし、当初実装していた内容では下記の挙動となっておりました。
- 一番上のコメントは、コメント投稿した箇所でコメント編集ができる
- しかし、2番目以降の箇所でコメント編集しようとすると、コメント編集欄が投稿した箇所と異なる場所へ移動してしまう
- また、編集ボタンを押しても編集画面が消えない
※両者ともに、app/views/comments/update.turbo_stream.erbでは、編集したコメントが一番上にくるようprependメソッドを使用しています。
修正前の実装
コメント本文を表示している_comment.html.erb内の<%= comment.body %>
を、<div id="post_comment">
で囲み、edit.turbo_stream.erbの内容とreplaceメソッドで入れ替えるよう実装しています。
これでコメント編集がうまくいくと思いましたが、先ほどのGIF画像のように編集の挙動が意図しないものとなっておりました。
- app/views/comments/_comment.html.erb
<tr id="comment-<%= comment.id %>">
<td>
<%= comment.user.name %>
<div id="post_comment">
<%= comment.body %>
</div>
</tr>
- app/views/comments/edit.turbo_stream.erb
<!-----コメント編集する文言を表示------>
<%= turbo_stream.replace "post_comment" do %>
<%= form_with model: @comment do |form| %>
<%= form.label :body, "コメント"%>
<%= form.text_area :body, placeholder: 'コメント', class: "textarea textarea-bordered w-full mb-4 h-full bg-white text-gray-600" %>
<%= form.submit "編集", class: "mt-10 flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"%>
<% end %>
<% end %>
どのように修正したか
実装がうまく行っていない可能性のある挙動を一つずつ確認し、_comment.html.erbを<div id="post_comment-<%= comment.id %>">
へ修正、併せてedit.turbo_stream.erbを<%= turbo_stream.replace "post_comment-#{@comment.id}" do %>
に修正しました。
すると、コメント投稿した箇所で編集もできるようになりました。
意図しない挙動になってしまった理由
コメントが複数存在しているにも関わらず、どのコメントをreplaceメソッドで入れ替えたいのか(=どのidのコメントを編集したいのか)を指定していなかったことが原因でした。
検証ツールでも、カーソルを当てている青い箇所でidの指定有無を確認できます。
最後に
スクールのカリキュラムでTurbo Streamsを学習している際は、idの指定有無によって挙動が異なるところまで確認できていませんでした。
自分で改めてTurbo Streamsを使ってみることで、理解がより深まりました。
ありがとうございました。
Discussion