SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Railsによるクライアントサイド開発入門

Rails 7×Hotwireで簡単にSPA開発! Turboの基本をチュートリアルとともに理解しよう

Railsによるクライアントサイド開発入門 第5回

  • X ポスト
  • このエントリーをはてなブックマークに追加

ページの一部を指定して変更できるTurbo Frames

 ここまで、Driveの基本的な動作を見てきました。このように、Scaffoldingによって生成されたページやフォームに特に手を入れなくても、ページ遷移のない高速なアプリケーションを開発できます。また、上記の通りTurboを設定で無効にすれば、従来どおりのページ遷移を伴うアプリケーションに簡単に切り替えられます。

 しかしながら、やはりページのほとんどの部分を書き換えるのは無駄だとか、SPAらしくページの一部だけを書き換えたいということはあります。このような場合には、次のステップとしてTurbo Frames(以降、Frames)の機能を使ってページに「フレーム」という領域を設けて、それを必要に応じて更新していきます。

 ここ以降は再びTurboの機能を使っていきますので、app/javascript/application.jsのTurboを無効にする設定は、削除するかコメントアウトしておいてください。

[NOTE]Turbolinks

 Turboは、Rails 4から導入されたTurbolinksというライブラリの後継版です。Turbolinksではfetchの対象がリンク(link_toメソッド)のみでしたが、Turboではフォーム(form_withメソッド)まで拡張されました。これにより、アプリケーションの多くの局面でTurboの恩恵を受けられるようになっています。

置き換え対象のフレームを作成する

 Framesの機能を使って、一覧ページ(/words)の[New word]リンクを、新規作成フォームで置き換えてみます。リンクをクリックすると、その部分がそのままフォームになるので、引き続き作業できるようになるというわけです。フレームの作成は、app/views/words/index.html.erbをリストのように変更します。

リスト app/views/words/index.html.erb
…略…
<%# [New word]リンクをフレームで囲む %>
<%= turbo_frame_tag 'new_word' do %>
    <%= link_to "New word", new_word_path %>
<% end %>

 リンクであるlink_toメソッドを、turbo_frame_tagメソッドのブロックで囲んでいます。turbo_frame_tagメソッドは、turbo-railsライブラリによるTurboのためのヘルパーメソッドで、Framesのためのタグ(turbo-frameタグ)を生成してくれます。引数はturbo-frameタグのid属性の値になります。これで、link_toメソッド(リンク)はフレームで囲まれますので、この部分だけの更新が可能になります。

[NOTE]turbo_frame_tagメソッドのレンダリング

 turbo_frame_tagメソッドはturbo-frameタグを生成しますが、具体的なレンダリングのイメージは以下の通りです。turbo_frame_tagメソッドの替わりに直接タグを記述してもよいですが、モデルオブジェクトによるid属性の自動的な生成などのメリットがなくなるので、できるだけヘルパーメソッドを使うようにしましょう。

<turbo-frame id="new_word">
    <a href="/words/new">New word</a>
</turbo-frame>

置き換わるフレームを作成する

 リンクのクリックで、リンクを新規作成フォームで置き換えるので、新規作成フォームであるapp/views/words/new.html.erbをリストのように書き換えます。

リスト app/views/words/new.html.erb
<%# フォームとリンクをフレームで囲む %>
<%= turbo_frame_tag @word do %>
  <%= render "form", word: @word %>
  <br>
  <div>
    <%= link_to "Back to words", words_path %>
  </div>
<% end %>

 ここでも、フォームと[Back to words]リンクをturbo_frame_tagメソッドで囲っています。こちらも、これでフレームとなります。turbo_frame_tagメソッドの引数はモデルオブジェクトを指定していますので、これによりid属性は一意的に生成されます。

Framesの動作

 この時点でアプリケーションを実行して、/wordsから[New word]リンクをクリックすると、[New word]リンクが新規作成フォームに置き換わることが確認できます(図7)。確かめる必要はないですが、もちろんページ遷移は発生していません。

図7 リンクがフォームに置き換わった
図7 リンクがフォームに置き換わった

 内部で何が行われているかを以下にまとめてみました(図8)。

  • 一覧ページの[New word]リンクのクリックにより、/words/newへのfetchリクエストが発生する
  • 新規作成ページであるnew.html.erbのレンダリング結果がレスポンスとして返る
  • レスポンスにはturbo_frame_tagメソッドによりturbo-frameタグが含まれるので、この中身で呼び出し側のturbo-frameタグの中身を書き換える
図8 フレームの置き換え
図8 フレームの置き換え

 このように、フレーム内部からのリクエストでは、フレームの内部をレスポンスのフレームの内容でそっくり置き換えます。このように、Framesではページの一部を極めて単純な指定だけで書き換えることができます。

[NOTE]FramesではURLは変更されない

 Framesでは、あくまでもページの部分的な更新であるため、基本的にはURLは変更されません。Driveと同様にURLを変更したい場合には、data-turbo-action属性をフレームかリンクのどちらかに指定します。以下は、フレームに対してURLの変更を指定した例です。

…略…
<%# フレームの更新でURLを変更する %>
<%= turbo_frame_tag 'new_word', data: { turbo_action: :advance } do %>
    <%= link_to "New word", new_word_path %>
<% end %>

 なお、:advanceは新しいURLとしますが:replaceでは最新のURLを置き換えます。通常は:advanceで問題ないでしょう。

[NOTE]遅延ローディング(Lazy loading)

 Driveでは、時間のかかる処理のためにプログレスバーやキャッシュの仕組みがありました。Framesでは、遅延ローディングの仕組みを使うことができます。遅延ローディングでは、読み込み中に表示する内容をturbo-frames要素のコンテンツとして配置し、src属性(turbo_frame_tagメソッドのsrcオプション)に読み込み先のURLを指定します。以下は、フォームの読み込み中にスピナーを表示しておく例です。

…略…
<%# フレームの更新でURLを変更する %>
<%= turbo_frame_tag 'new_word', src: new_word_path do %>
    <%= image_tag 'spinner.png' %>
<% end %>

まとめ

 今回は、アプリケーションにSPAライクな振る舞いを導入できるHotwrireについて、主にTurbo DriveとTurbo Framesの機能を紹介しました。次回は後半として、Turbo StreamsとStimulusの機能を紹介します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Railsによるクライアントサイド開発入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook <個人紹介> WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16790 2022/11/17 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング