おつかれさまです!のぶじゃす です。
最近Rails7でWebアプリケーションを開発しているのですが、削除の処理などの後戻りができないときや、事前に確認が必要な処理を書く際にブラウザのconfirm機能を使って確認ダイアログを出す処理を出したい場面がありました。
Rails7でこの機能の処理が変わってしまっていてハマりました。今回はある程度詳細な理由も調べてみました。
想定以上にアタフタ困ってしまった動画はこちら
実は動画撮影中にこの変更にハマってしまいました。まんまとハマって困りまくり焦りまくりの動画はこちらです。面白かったら高評価おねがいしますw
VIDEO
www.youtube.com
Railsでは button_to
などで簡単にconfirmを出す機能がありました。
<% button_to "削除" , any_path(any), { method : :delete, data : { confirm: "本当に削除してもいいですか?" } } %>
のように書くことで確認ダイアログが表示されていました。
Rails7 ではこれだと出ない
Rails7ではこの方法では確認ダイアログが表示されず、そのまま処理されてしまいます。これでは簡単に削除できすぎてしまいます。
そこでいくつか調べた所、 解決策を見つけました。
<%= button_to "削除" , rabbit_weight_path(@rabbit, weight), { method : :delete, form : { data : { turbo_confirm: "本当に削除しますか?" } } } %>
data: { confirm: "確認" }
を form: { data: { 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を出したい場合などにも使いやすそうです。
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
処理を動かしています
この辺りの処理です
github.com
正しい対応っぽいので大丈夫そう
コードをざっと読んでみた所、特におかしな所はなく想定されている挙動のようだったのでこれで安心して開発が進められます。
アクセスありがとうございます🙇♂️
ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブ や、Twitterのフォロー していただけると大変喜びます😊
それではよいRails7ライフを!