Open kurashiki777 opened 7 months ago
使用しているPC mac
やりたいこと actiion cableで編集のリアルタイム更新
現状発生している問題・エラーメッセージ コメントの編集ボタンを押すとhttp://localhost:3000/~~/edit.turbo_streamのURLに遷移して、コードがそのまま表示されます
どの処理までうまく動いているのか 該当のソースコード
app/channels/comment_channel.rb
class CommentChannel < ApplicationCable::Channel
def subscribed
stream_for card
end
def unsubscribed
stop_all_streams
end
private
def card
Card.find(params[:card_id])
end
end
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
before_action :require_login, only: [:create, :edit, :update, :destroy]
before_action :set_comment, only: [:edit, :update, :destroy]
def create
@comment = current_user.comments.build(comment_params)
@comment.card_id = params[:card_id]
if @comment.save
CommentChannel.broadcast_to(@comment.card, render_to_string(partial: 'comments/comment', locals: { comment: @comment }))
else
redirect_to card_path(@comment.card), danger: t('defaults.message.not_created', item: Comment.model_name.human)
end
end
def edit
respond_to do |format|
format.turbo_stream { render 'edit' }
format.html { render partial: 'comments/edit_form', locals: { comment: @comment } }
end
end
def update
if @comment.update(comment_params)
CommentChannel.broadcast_to(
@comment.card,
{ html: render_to_string(partial: 'comments/comment', locals: { comment: @comment }), action: 'update', comment_id: @comment.id }
)
head :ok
else
render json: { status: 'error', message: @comment.errors.full_messages.join(", ") }, status: :unprocessable_entity
end
end
def destroy
card = @comment.card
comment_id = @comment.id
@comment.destroy
CommentChannel.broadcast_to(card, { action: 'destroy', comment_id: comment_id })
head :ok
end
private
def comment_params
params.require(:comment).permit(:body).merge(card_id: params[:card_id])
end
def set_comment
@comment = Comment.find(params[:id])
end
end
3.コメント編集フォームとTurbo Streamの設定をしました
app/views/comments/edit.turbo_stream.erb
<turbo-stream target="edit-comment-form-<%= @comment.id %>" action="replace">
<template>
<%= render partial: 'comments/edit_form', locals: { comment: @comment } %>
</template>
</turbo-stream>
app/views/comments/_edit_form.html.erb
<%= form_with model: [comment.card, comment], remote: true, html: { id: "edit-comment-form-#{comment.id}" } do |form| %>
<div class="field">
<%= form.text_area :body, rows: 3 %>
</div>
<div class="actions">
<%= form.submit "更新", class: "btn btn-primary" %>
</div>
<% end %>
app/views/comments/_comment.html.erb
<tr id="comment-<%= comment.id %>" class="bg-white">
<td class="p-3">
<%= image_tag comment.user.avatar_url, width: '50', height: '50' %>
</td>
<td class="p-3" style="vertical-align: top;">
<h3 class="text-sm font-semibold"><%= comment.user.decorate.full_name %></h3>
<div class="text-gray-700">
<%= simple_format(comment.body) %>
</div>
<% if current_user&.own?(comment) %>
<div class="comment-buttons">
<table>
<tr>
<td>
<%= link_to "編集", edit_card_comment_path(comment.card, comment, format: :turbo_stream), remote: true, class: "block p-2.5 bg-green-500 text-white text-center rounded hover:bg-green-700", data: { turbo_frame: "edit-comment-form-#{comment.id}" } %>
</td>
<td>
<%= button_to '削除', card_comment_path(comment.card, comment), method: :delete, data: { confirm: '本当に削除しますか?' }, class: "block p-2.5 bg-red-500 text-white text-center rounded hover:bg-red-700" %>
</td>
</tr>
</table>
</div>
<%= turbo_frame_tag "edit-comment-form-#{comment.id}" %>
<% end %>
</td>
</tr>
app/javascript/packs/application.js
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
// Tailwind CSS
import "stylesheets/application"
import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = true
Rails.start()
Turbolinks.start()
ActiveStorage.start()
document.addEventListener("turbo:frame-load", () => {
console.log("Turbo Frame Loaded");
});
app/javascript/channels/comment_channel.js
import { createConsumer } from "@rails/actioncable"
const consumer = createConsumer()
document.addEventListener('turbo:load', () => {
const commentsElement = document.getElementById('comments')
if (commentsElement) {
const cardId = commentsElement.dataset.cardId
consumer.subscriptions.create({ channel: "CommentChannel", card_id: cardId }, {
received(data) {
if (data.action === 'update') {
const commentElement = document.getElementById(`comment-${data.comment_id}`)
commentElement.outerHTML = data.html
} else if (data.action === 'destroy') {
const commentElement = document.getElementById(`comment-${data.comment_id}`)
commentElement.remove()
} else {
commentsElement.insertAdjacentHTML('beforeend', data.html)
}
}
})
}
})
エラーから考えられる 原因Turboの設定が不十分、またはJavaScriptエラーが発生している可能性がある。
試したこと Turboが正しくインストールされていることを確認するために yarn add @hotwired/turbo-rails を打ちました インストールされてました
コンソールログを見るために app/javascript/packs/application.js document.addEventListener("turbo:frame-load", () => { console.log("Turbo Frame Loaded");
これ追加したのですがコンソールログが見れなかった
参考にしたURL・使用したプロンプト https://qiita.com/mitaninjin/items/5a58533a183e62307a6c 全部chatGPTに聞きました
カードの譲渡などの話しをする際に毎回リロードするのはユーザー体験としては良くないかと思うので非同期化