おつかれさまです!のぶじゃすです。
最近Rails7でWebアプリケーションを開発しているのですが、削除の処理などの後戻りができないときや、事前に確認が必要な処理を書く際にブラウザのconfirm機能を使って確認ダイアログを出す処理を出したい場面がありました。
Rails7でこの機能の処理が変わってしまっていてハマりました。今回はある程度詳細な理由も調べてみました。
想定以上にアタフタ困ってしまった動画はこちら
実は動画撮影中にこの変更にハマってしまいました。まんまとハマって困りまくり焦りまくりの動画はこちらです。面白かったら高評価おねがいしますw
Rails7より前の button_to
で confirm を出す方法
Railsでは button_to
などで簡単にconfirmを出す機能がありました。
<% button_to "削除", any_path(any), { method: :delete, data: { confirm: "本当に削除してもいいですか?" } } %>
のように書くことで確認ダイアログが表示されていました。
Rails7 ではこれだと出ない
Rails7ではこの方法では確認ダイアログが表示されず、そのまま処理されてしまいます。これでは簡単に削除できすぎてしまいます。
そこでいくつか調べた所、 解決策を見つけました。
Rails7 で button_to
で confirm を出す方法
<%= button_to "削除", rabbit_weight_path(@rabbit, weight), { method: :delete, form: { data: { turbo_confirm: "本当に削除しますか?" } } } %>
data: { confirm: "確認" }
を form: { data: { turbo_confirm: "確認" } }
に直す事で正しく表示されます。
挙動としてはこれで正しくなりましたがなぜなのかはよく分かりません。どういう処理でこれが動作しているのか少し調べてみました。
2023/02/15 追記: form
をつけなくても confirm
を turbo_confirm
にすると動く
id:JunichiIto さんにコメントを頂きました。ありがとうございます!
該当のPull Requestはこちらです Make data-turbo-confirm work with multiple submitters inside a form by feliperaul · Pull Request #564 · hotwired/turbo · GitHub
このPull Requestがmergeされた Turbo 7.2 (turbo-rails 1.3) 以降では <form data-turbo-confirm="xxx"
でも動きますが、 <button data-turbo-confirm="xxx"
のようにbuttonタグに設定する形でも反応してくれるようになりました。
具体的にはこんな感じです
<%= button_to "削除", rabbit_weight_path(@rabbit, weight), { method: :delete, data: { turbo_confirm: "本当に削除しますか?" } } %>
これはありがたいですね。出力されたHTMLを見た時に見つけやすくなりますし、1つのformの中で複数のボタンがある場合で別のconfirmを出したい場合などにも使いやすそうです。
form:
でくくると何が起こるのか
button_to
の第3引数で form: { data:
を設定するとそれ自体が form
タグで囲まれます。そして form
タグのアトリビュートに data-turbo-confirm
が設定されます。
具体的には
erbに下記のように書くと
<%= button_to "削除", rabbit_weight_path(@rabbit, weight), { method: :delete, form: { data: { turbo_confirm: "本当に削除しますか?" } } } %>
HTMLとしてはこのようにレンダリングされます。
<form data-turbo-confirm="本当に削除しますか?" class="button_to" method="post" action="/rabbits/1/weights/2"> <input type="hidden" name="_method" value="delete" autocomplete="off"> <button type="submit">削除</button> <input type="hidden" name="authenticity_token" value="..........................." autocomplete="off"> </form>
そしてどうやってconfirm処理が動いているのか
Rails7ではturboが動いているため、以前のバージョンと変わったようです。
ということで turbo のコードを読んでみましょう。
- confirm 処理を探して読んでみた
form_submission.ts
にそれっぽいコードを見つけましたFormSubmission
というクラスでは formElement を constructor で受け取りますconfirmationMessage
でdata-turbo-confirm
を探しますneedsConfirmation
ではconfirmationMessage
が存在した場合にtrue
を返しますneedsConfirmation
がtrue
の場合にはconfirmMethod
が発火しますconfirmMethod
ではJavaScript標準(ブラウザ標準?)のcofirm
処理を動かしています
この辺りの処理です
正しい対応っぽいので大丈夫そう
コードをざっと読んでみた所、特におかしな所はなく想定されている挙動のようだったのでこれで安心して開発が進められます。
アクセスありがとうございます🙇♂️
ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊
それではよいRails7ライフを!