partialに対して変数を渡せていないのが、原因だと思います。
format.turbo_stream do
render turbo_stream: turbo_stream.append(
:modal,
partial: 'shared/update_modal',
)
end
↑ ここの部分で変数を渡すと良さそうです!
更新したスキル名を取得し、モーダル内で表示させたい。
アプリの仕様
ruby on rails でポートフォリオサイトのようなものを作っています。
解決したいページの内容は、スキルを表示する表があり、スキルのレベルだけ編集可能にしており、セレクターで数値を選択し、保存ボタンを押す。保存ボタンが押されると、モーダルがオープンし、{スキル名}のレベルを保存しました!と表示される。
{}内に更新したスキル名が入るというような感じです。
<%= @skill.name %>
を取得できず、else処理になってしまう。
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" data-backdrop="static">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body text-center mt-5">
<% if @skill.present? %>
<p><%= @skill.name %></p>
<% else %>
<p>スキルが更新されていません</p>
<% end %>
<button type="button" class="btn btn-primary us-btn" data-dismiss="modal">スキル編集ページに戻る</button>
</div>
</div>
</div>
</div>
def update
@skill = Skill.find(params[:id])
respond_to do |format|
if @skill.update(skill_params)
@updated_skill = true
format.turbo_stream do
render turbo_stream: turbo_stream.append(
:modal,
partial: 'shared/update_modal',
)
end
format.json { render json: { success: true } }
else
format.html { render 'edit', status: :unprocessable_entity }
format.json { render json: { success: false, errors: @skill.errors.full_messages } }
end
end
end
元々は、turboのことなどよくわからず、javascriptやindexページのcontroller経由して変数渡したりなど色々やっていましたが、turboを使用すれば、modalをパーシャルで準備して表示できる感じだったので、上記のようにしました。デバッグし、updateメソッドのどこかで止まっているのかと思いましたが、正常に動いており、レベルの更新も問題なくできています。
@skillにデータが格納されていることも確認できたので、何が問題なのかわからなくなりました。
index.html.erbはviews/positions/
配下にあります。
positions_controllerに変数受け取りのアクションが必要なのでしょうか?
51: def update
52: @skill = Skill.find(params[:id])
53: respond_to do |format|
54: if @skill.update(skill_params)
55: @updated_skill = true
56: format.turbo_stream do
57: render turbo_stream: turbo_stream.append(
58: :modal,
59: partial: 'shared/update_modal',
60: )
61: end
62:
=> 63: binding.pry
64:
65: format.json { render json: { success: true } }
66: else
67: format.html { render 'edit', status: :unprocessable_entity }
68: format.json { render json: { success: false, errors: @skill.errors.full_messages } }
69: end
70: end
71: end
[1] pry(#<SkillsController>)> @skill
=> #<Skill:0x0000ffff8d7928a8
id: 35,
position_id: 1,
name: "Go",
level: 70,
created_at: Mon, 15 May 2023 03:49:21.807342000 UTC +00:00,
updated_at: Thu, 18 May 2023 03:06:30.811758000 UTC +00:00>
[2] pry(#<SkillsController>)> @skill.name
=> "Go"
ご教授いただけますと幸いです🙇
partialに対して変数を渡せていないのが、原因だと思います。
format.turbo_stream do
render turbo_stream: turbo_stream.append(
:modal,
partial: 'shared/update_modal',
)
end
↑ ここの部分で変数を渡すと良さそうです!
@maasiii
Questioner@apierce さん
今回も、アドバイスありがとうございます!
公式を見るところ、turbo updateなどを使用する際は、
HTMLを<turbo streame>
でラップしなければ使用できないということでしょうか?
自分の読解力が足りないため、質問させていただきました。
<div class="container mt-5">
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between mt-3">
<div>
<h3>バックエンド</h3>
<div class="border-underbar-1"></div>
</div>
<%= link_to "スキルを追加する", new_skill_path(position: "backend"), class: "btn btn-primary us-btn" %>
</div>
<div class="table-container">
<table class="p-table mt-4">
<thead class="p-thead">
<tr class="p-tr">
<th class="skill-header" style="padding-left: 3%">習得スキル</th>
<th>習得レベル</th>
</tr>
</thead>
<tbody>
<% @backend_skills.each do |skill| %>
<tr class="p-tr">
<td class="p-td">
<span class="skill-name"><%= skill.name %></span>
</td>
<%= form_with(model: skill, url: skill_path(skill), method: :patch, local: true, id: "edit-skill-form-#{skill.id}") do |f| %>
<td class="p-td">
<%= f.select :level, options_for_select((0..100).step(10), skill.level), include_blank: true %>
</td>
<td class="p-td">
<%= f.submit "習得レベルを保存する", class: "btn skill-edit-btn" %>
</td>
<% end %>
<td class="p-td">
<%= link_to "スキルを削除する", skill_path(skill), data: { "turbo-method": :delete, toggle: "modal", target: "#deleteModal" }, remote: true, class: "btn skill-delete-btn" %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
上記のf.select :level
のスキルレベルを非同期で更新できるようにしたいと思っています。
お時間ある際に助言いただけますと幸いです🙇
すみません、多分僕が添付したリンクが良くなかったです。
部分テンプレート側で変数を参照するには、その変数を渡してあげる必要があります。
format.turbo_stream do
render turbo_stream: turbo_stream.append(
:modal,
partial: 'shared/update_modal',
locals: { skill: @skill } # ここを追加
)
end
↑のようにすることで、views/shared/_update_modal.html.erb
でskill
を参照できるようになります。
@maasiii
Questioner@apierce
ありがとうございます!!
ちなみになのですが、rails7の非同期処理はturboで実装するのが普通なのでしょうか?
以前読んだ記事で、7からはjqueryが非推奨というのをみたのでajaxは使用あまりしないのか、、?
しかし、今回自分が実装したかったのがindexページで非同期で値の更新をし、更新できた時にmodalが発火し、モーダルで更新したスキル名を取得する。など、少し複雑なように感じ、turboだけでできるのか?(turboは簡単だが柔軟性はあまりないなどを記事で見かけた。。)などと困惑していました。
お忙しいかと思いますので、お時間ある際に助言いただけますと幸いです。🙇♂️💦