Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Hotwire を使って管理画面を簡単にプチSPA化する - Kaigi on Rails 2023
Search
Takaharu Yamamoto
October 29, 2023
Programming
2
1.4k
Hotwire を使って管理画面を簡単にプチSPA化する - Kaigi on Rails 2023
https://kaigionrails.org/2023/talks/yamataka/
Takaharu Yamamoto
October 29, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
AI時代の『改訂新版 良いコード/悪いコードで学ぶ設計入門』 / ai-good-code-bad-code
minodriven
23
9k
『自分のデータだけ見せたい!』を叶える──Laravel × Casbin で複雑権限をスッキリ解きほぐす 25 分
akitotsukahara
2
650
状態遷移図を書こう / Sequence Chart vs State Diagram
orgachem
PRO
2
180
型で語るカタ
irof
0
550
Goで作る、開発・CI環境
sin392
0
260
技術同人誌をMCP Serverにしてみた
74th
1
680
Hack Claude Code with Claude Code
choplin
6
2.4k
AIエージェントはこう育てる - GitHub Copilot Agentとチームの共進化サイクル
koboriakira
0
630
Startups on Rails in Past, Present and Future–Irina Nazarova, RailsConf 2025
irinanazarova
0
200
Claude Code + Container Use と Cursor で作る ローカル並列開発環境のススメ / ccc local dev
kaelaela
12
6.8k
脱Riverpod?fqueryで考える、TanStack Queryライクなアーキテクチャの可能性
ostk0069
0
340
AI コーディングエージェントの時代へ:JetBrains が描く開発の未来
masaruhr
1
200
Featured
See All Featured
The Invisible Side of Design
smashingmag
301
51k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
Documentation Writing (for coders)
carmenintech
72
4.9k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Why Our Code Smells
bkeepers
PRO
336
57k
KATA
mclloyd
30
14k
The Pragmatic Product Professional
lauravandoore
35
6.7k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
108
19k
Typedesign – Prime Four
hannesfritz
42
2.7k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
Become a Pro
speakerdeck
PRO
29
5.4k
Transcript
Hotwire を使って 管理画⾯を簡単にプチSPA化する Takaharu Yamamoto Kaigi on Rails 2023
⾃⼰紹介 • ⼭本孝春 • GitHub: yamataka22 • 個⼈事業主 • 中⼩規模システムの受託開発をしてます
• Railsで⼀気通貫した開発が好き
Hotwire 使ってますか?
Hotwire 使ってますか? 情報が少ない 実績が少ない とりあえず無効化
Hotwire 使ってますか? 情報が少ない 実績が少ない とりあえず無効化 Turbolinksの⼆の舞に...?!
本⽇のテーマ Hotwireを使って管理画⾯をモーダル化する →この説明を通じて、Hotwireの敷居を下げたい
• 話すこと ◦ HotwireでModalを扱う⽅法を、コードを例⽰しながら実践 レベルで説明します • 話さないこと ◦ 時間の都合上、Hotwireの⼊⾨的な内容(TurboFrameとは 何か?など)は割愛します
今⽇の内容
管理画⾯にモーダルを 使うメリットは? そもそも
よくある画⾯遷移 ⼀覧で検索をして、⾏を選択
よくある画⾯遷移 詳細画⾯に遷移する
よくある画⾯遷移 そこから⼀覧に戻ると indexのPath
よくある画⾯遷移 検索状態がリセットされてしまう
よくある対策 • ブラウザの別タブで表⽰ ◦ assetsを含めた画⾯全体をリロードするので重い ◦ 気づいたらブラウザがタブだらけ • 戻るボタンに検索条件のパラメータを保持 ◦
戻るだけなのに再度検索が⾛る ◦ スクロール位置などは保持されない
⼀覧からの遷移をモーダルで開けば
⼀覧の状態を維持できる
モーダル表⽰のメリット • 画⾯の状態を維持しながら操作を進められる • モーダル内だけ描画するので、挙動が軽い • ユーザーはその画⾯に留まれる安⼼感がある
ただし管理画⾯なので • 開発にそこまでコストをかけたくない • サーバーサイド側のエンジニアだけで UIも含めて実装することが多い
ただし管理画⾯なので • 開発にそこまでコストをかけたくない • サーバーサイド側のエンジニアだけで UIも含めて実装することが多い モーダルのために作り込むことは避けたい
そこで Hotwire
Hotwireなら • ほとんどJavaScriptを書くことなく • ⼀般的な画⾯遷移版に少し⼿を⼊れるだけで • 簡単にモーダル化できる
コードの説明の前に • モーダルの描画にはBootstrapを利⽤します ◦ Bootstrap以外でも、JavaScriptを使ってモーダル表⽰の制御ができれ ば、他のツールでも代替可能です • 時間の都合上、細かな部分は説明を省略します ◦ 本⽇説明するコードはGitHubで公開してます
github.com/yamataka22/kaigionrails2023-admin-modal
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
モーダル表⽰のポイント • TurboFrameを使って、モーダル部分のHTMLの破⽚を⽣ 成する • その破⽚がブラウザに読み込まれたタイミングで、 Stimulusのインスタンスを⽣成し、connect()を経由して モーダルを開く
app/views/application/_remote_modal.html.erb Modal表⽰のerb (TurboFrame)
app/views/application/_remote_modal.html.erb 中⾝はBootstrapの⼀般的な Modal Component turbo_frame_tag で囲む Modal表⽰のerb (TurboFrame)
app/views/application/_remote_modal.html.erb ポイントはここ! 破⽚の中から、Stimulusの controllerを指定する この破⽚がブラウザに組み込まれたタイミングで 該当Stimulusのインスタンスが⽣成される →TurboFrameとStimulusを連携して、動きをつけられる Modal表⽰のerb (TurboFrame)
app/javascript/controllers/remote_modal_controller.js Modal表⽰のStimulus • `connect()`は、Stimulusのインス タンスが⽣成されたときに⾃動的に 起動するメソッド • TurboFrameで読み込んだHTMLに対 して、Stimulusで動きをつけられる •
`disconnect()`もある
これだけでモーダル表⽰できる 🎉
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
⼀般的な画⾯遷移による更新処理 編集フォームから更新すると
⼀般的な画⾯遷移による更新処理 エラーがあれば編集画⾯にとどまり
⼀般的な画⾯遷移による更新処理 更新に成功したら詳細画⾯にリダイレクトする
⼀般的な画⾯遷移による更新処理 更新に成功したら詳細画⾯にリダイレクトする モーダルでも同等な動きを実現したい
モーダルでの更新処理 編集フォームから更新すると
モーダルでの更新処理 エラーがあればモーダル上で表示され
モーダルでの更新処理 更新後に詳細画⾯が表⽰される
Controller#update app/controllers/products_controller.rb
Controller#update • 更新に成功しても、redirectしない • update.turbo_stream.erbがレンダリ ング対象 • 本来redirectするパス (product_path) を@turbo_pathにセット
→これは後述にて説明 app/controllers/products_controller.rb
Controller#update invalidの場合は :edit を再度レンダリン グする →これは通常の画⾯遷移時と同様 app/controllers/products_controller.rb
Turbo Stream app/views/products/update.turbo_stream.erb
Turbo Stream remote_modal の部分を @product で `replace` する (モーダルの内容が詳細画⾯に変わる) app/views/products/update.turbo_stream.erb
Turbo Stream app/views/products/update.turbo_stream.erb ⼀覧(index) に表⽰されているレコードの内容も 最新化する
以上で登録後の遷移ができる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
やること 1. TurboFrame + Stimulus でモーダルを開く 2. TurboStream で登録後の描画を切り替える 3.
ブラウザのURLを追随させる
管理画⾯の運⽤でよくあるシーン URLを使ってやり取りすることが多々ある 例えばSlackで...
管理画⾯の運⽤でよくあるシーン URLを使ってやり取りすることが多々ある 例えばSlackで... こんな感じで該当ページのURLを使って コミュニケーションしたい
単にModal化しただけでは ブラウザのURLが追随しない →URLを使った運⽤ができない 管理画⾯の実運⽤も考慮して 対処したい
2つの対策を提案 a) モーダル起動の link_to に `turbo_action: :advance` を指定 b) JavaScriptの
History API を使って制御する
2つの対策を提案 a) モーダル起動の link_to に `turbo_action: :advance` を指定 ∙ Railsの仕組みでできるのでシンプル
∙ Modalを閉じたときや、更新後の表⽰切り替え時に追随しない b) JavaScriptの History API を使って制御する ∙ URLのために仕組みを実装する必要 ∙ Modalを閉じたとき、更新後の表⽰切り替えも追随できる
2つの対策を提案 a) モーダル起動の link_to に `turbo_action: :advance` を指定 ∙ Railsの仕組みでできるのでシンプル
∙ Modalを閉じたときや、更新後の表⽰切り替え時に追随しない b) JavaScriptの History API を使って制御する ∙ URLのために仕組みを実装する必要 ∙ Modalを閉じたとき、更新後の表⽰切り替えも追随できる 今回はこちらの内容を説明
以下2つのURLを使う • Modalを表⽰したときのURL ◦ TurboFrameによるGETリクエスト or リダイレクトのURL ◦ Modalを開く際に、HistoryAPIにセットする •
Modalを閉じたときのURL ◦ Modalを開く直前のURLを location.href から取得しておく ◦ Modalのhideイベントをフックして、このURLに戻す
app/controllers/application_controller.rb ApplicationControllerの before_action で、turboでリクエスト されたURLを @turbo_path へセットし ておく Modal起動時のURL GETリクエストでModalを起動する
app/controllers/products_controller.rb 例えば #update に成功すると、通常の画⾯遷移版 では show_path へリダイレクトする。 そのpathを @turbo_path としてセットしておく。
Modal起動時のURL Modalにリダイレクトの動きをさせたい場合
app/views/application/_remote_modal.html.erb @turbo_path をModalに付与しておき、Stimulusを介 してHistoyAPIにセットする 前項で説明した turbo_frame でModal表示をするerb
app/javascript/controllers/remote_modal_controller.js 前述で説明した、Stimulusのconnect()を使って Modalを開くロジック部分 Modalを起動するStimulus
Modalを開く前に、URLの仕組みを ⼊れる app/javascript/controllers/remote_modal_controller.js Modalを起動するStimulus
app/javascript/controllers/remote_modal_controller.js Modalを起動するStimulus 前述の `turboPath` を HistoryAPIにセットするこ とで、Modal起動時にURLを追随させる
現在のパス=Modalを開く直前のパ ス (`location.href`) を、Modal#hide イベントをフックしてセットする app/javascript/controllers/remote_modal_controller.js Modalを起動するStimulus
以上でブラウザ上のURLが追随します
ちなみに、この状態で URLを直接指定したリクエストをすると...
特に何も仕組みを設けなくても表⽰できる
コード補足 a) 登録フォームのModalは、背景クリックでも閉じないように • ⼊⼒途中にうっかりModalが閉じることを防ぐ • 詳細ページなら背景クリックで閉じたほうが便利 b) Flashによるメッセージ表⽰ •
Turboだと少し仕組みを設ける必要 サンプルのGitHubリポジトリで実装しています github.com/yamataka22/kaigionrails2023-admin-modal
まとめ • Hotwireを使って、管理画⾯をModalでプチSPA化するポイントを説明 しました ◦ TurboFrameとStimulus (connect()) を連携させて、HTMLの破⽚に動き をつける ◦
TurboStreamで、Modal上の描画を切り替える(リダイレクトのイメー ジ) • 今回説明した内容は、管理画⾯はもちろん、⼀般的なフロント向け ページでも応⽤可能です
ご清聴ありがとうございました ※ご不明な点などあれば、お気軽にご連絡ください github.com/yamataka22