Rails 7 のターボ ストリーム
概要
私はこのチュートリアル https://www.youtube.com/watch?v=TKIbtbYyRdE&list=PL6SEI86zExmvb4qjVHJWrKRQrKjWksQ81&index=34 とその 2 番目の部分を続けています。 https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://www.youtube.com/watch?v=akrXCho2m6Y&list=PL6SEI86zExmvb4qjVHJWrKRQrKjWksQ81&index=34
何が間違っているのかを探すのにうんざりしている、
<%= link_to "Connect", connections_path, class:"btn btn-primary", data: { controller:"connections", turbo_method: :post, requester_id: current_user.id, connected_id: user.id, connections_target:"connection" } %>
上記の link_to は、POST リクエストを実行する必要がある StimulusJS コントローラーの「接続」を使用します。
接続_コントローラー.js
import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="connections"
export default class extends Controller {
static targets = ["connection"];
connect() {}
initialize() {
this.element.setAttribute("data-action", "click->prepareConnectionParams");
}
prepareConnectionParams(event) {
event.preventDefault();
this.url = this.element.getAttribute("href");
const element = this.connectionTarget;
const requesterId = element.dataset.requesterId;
const connectedId = element.dataset.connectedId;
const connectionBody = new FormData();
connectionBody.append("connection[user_id]", requesterId);
connectionBody.append("connection[connected_user_id]", connectedId);
connectionBody.append("connection[status]", "pending");
console.log("Connection Body:", connectionBody);
fetch(this.url, {
method: "POST",
headers: {
Accept: "text/vnd.turbo-stream.html",
"X-CSRF-Token": document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content"),
},
body: connectionBody,
})
.then((response) => response.text())
.then((html) => Turbo.renderStreamMessage(html));
}
}
その後、ConnectionsController.rbがあります
class ConnectionsController < ApplicationController
before_action :authenicate_user!
def create
Rails.logger.debug "Params received: #{params.inspect}"
@connection = current_user.connections.new(connection_params)
@connector = User.find(connection_params[:connected_user_id])
respond_to do |format|
if @connection.save
format.turbo_stream {
render turbo_stream:
turbo_stream.replace(
"user-connection-status",
partial: "connection/create",
locals: { connector: @connector }
)
}
end
end
end
private
def connection_params
params.require(:connection).permit(:user_id, :connected_user_id, :status)
end
end
リンクをクリックすると、コンソールにエラー 400 Bad Request for POST が表示され、ページが更新されます。 機能しなかったので、Rails.logger.debug「受信したパラメータ: #{params.inspect}」を使用しました したがって、ターミナルログでは、パラメータが送信されていないことが示されています 受信したパラメータ: #<ActionController::Parameters {“controller”=>“connections”, “action”=>“create”} allowed: false>
解決策
アクションのコントローラーがありません:
this.element.setAttribute("data-action", "click->connections#prepareConnectionParams");
// ^^^^^^^^^^^
以下は、Stimulus アクションのパラメーターを使用した別の例です。 https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://stimulus.hotwired.dev/reference/actions#action-parameters
# there is no need for `turbo_method: :post` since we're doing our own posting
# `connections_target` is also a bit redundant on a controller element itself
<%= link_to "Connect", connections_path,
data: {
controller: "connections",
connections_requester_id_param: 1,
connections_connected_id_param: 2,
connections_status_param: "pending",
}
%>
// app/javascript/controllers/connections_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
connect() {
this.element.setAttribute("data-action", "connections#prepareConnectionParams");
}
prepareConnectionParams(event) {
event.preventDefault();
const { params } = event;
const body = new FormData();
body.append("connection[user_id]", params.requesterId);
body.append("connection[connected_user_id]", params.connectedId);
body.append("connection[status]", params.status);
fetch(this.element.getAttribute("href"), {
method: "POST",
headers: {
Accept: "text/vnd.turbo-stream.html",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
},
body,
})
.then((response) => response.text())
.then((html) => Turbo.renderStreamMessage(html));
}
}
私はチュートリアルを見ていませんが、^ が何か役に立つことを意味するものであることを確認してください。通常の形式で、はるかに少ないコードで同じことを達成できるからです。
<%= button_to "Connect", connections_path,
params: {
connection: {
user_id: 1,
connected_user_id: 2,
status: "pending",
}
}
%>
これにより、同じパラメータを持つ TURBO_STREAM POST リクエストが送信され、turbo_stream 応答が処理されます。