10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Hotwire(Turbo)を試す その1: 導入、作成・更新フォーム

Last updated at Posted at 2021-04-25

環境: Rails 6.1、Turbo 7.0.0-beta.5

Hotwire(Turbo)とは

Hotwireは、Railsの作者であるBasecampのDHHが昨年発表したものです。「モダンなウェブアプリケーションを、たくさんのJavaScriptなしで、JSONの代わりにHTMLを送って作るもの」だそうです。

Hotwireは次の3つからなります。

  • Turbo
  • Stimulus
  • Strada

といっても、Stimulusは前からありますし、Stradaはまだできていないので、実際に試してみるのはもっぱらTurboということになります。Turboは、簡単に言えば今までのTurbolinksを発展させたものです。「Turbolinksがなんかすごくなったもの」です。

参考にしたサイト

Hotwireのサイトの他に:

Hotwire (Turbo)の導入

では試してみましょう。Rails 6.1でアプリケーションを作ります。

% rails new hotwire-sample
% cd hotwire-sample

Gemfileにhotwire-railsを加えます。

Gemfile
gem 'hotwire-rails'

Gemをインストールします。

% bundle install

次のコマンドを実行すると、RailsアプリケーションにTurboとStimulusが入ります。

% bin/rails hotwire:install

Gemfileが自動的に修正され、Turbolinksが外されてRedisが必須になります。もう一度 bundle install を実行します。

Gemfile
- gem 'turbolinks', '~> 5'
+
- # gem 'redis', '~> 4.0'
+ gem 'redis', '~> 4.0'

package.jsonでは、Turbolinksの代わりにTurboが入ります。

package.json
  "dependencies": {
+   "@hotwired/turbo-rails": "^7.0.0-beta.5",
    "@rails/actioncable": "^6.0.0",
    "@rails/activestorage": "^6.0.0",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "5.2.1",
-   "turbolinks": "^5.2.0"
+   "stimulus": "^2.0.0"
  },

cable.ymlが修正されています。ActionCableを使うときは開発環境でRedisが必要なようです。なお、Turboを使うにはActionCableが必須というわけではありません。この「その1」と「その2」のサンプルではActionCableもRedisも要りません。

config/cable.yml
development:
-  adapter: async
+  adapter: redis
+  url: redis://localhost:6379/1

application.jsでも、Turbolinksの代わりにTurboが入り、Stimulusの初期化(import "controllers")が加わります。

app/javascript/packs/application.js
import Rails from "@rails/ujs"
- import Turbolinks from "turbolinks"
+ import "@hotwired/turbo-rails"
import * as ActiveStorage from "@rails/activestorage"
import "channels"

Rails.start()
- Turbolinks.start()
ActiveStorage.start() 
+ import "controllers"

レイアウトテンプレートでdata-turbolinks-trackdata-turbo-trackに変える必要がありますが、ここは自動的に修正されないので手動で直します。

app/views/layouts/applicaton.html.erb
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbo-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbo-track': 'reload' %>

なお、hotwire-railsはturbo-railsstimulus-railsをまとめたものです。Gemfileにhotwire-railsの代わりにgem 'turbo-rails' を加えて、次のコマンドを実行しても同じです。webpacker:install:stimulus を実行しなければ、StimulusなしでTurboだけ使えます。

% bundle install
% bin/rails turbo:install
% bin/rails webpacker:install:stimulus

作成・更新フォーム

Turboの機能を調べるために、作成・更新フォームを作ってみます。scaffoldで手抜きします。

% bin/rails g scaffold entry title:string body:text
% bin/rails db:migrate

エラー表示を試すために、バリデーションを加えます。

app/models/entry.rb
class Entry < ApplicationRecord
  validates :title, :body, presence: true
end

http://localhost:3000/entries から新規作成と編集画面を試すと、Turboのために何も手を加えなくても、そのまま動作します。

バリデーションエラーのときの挙動は、これまでのRailsとは変わります。POSTでブラウザーが画面遷移せずに、TurboのJavaScriptが画面を差し替えます。URLは /entries/new や /entries/:id/edit のままです。

turbo1.png

注意しなければならないのは、Turboを使っているときにPOST(PATCH、DELETE)メソッドでリクエストを送ったら、リダイレクトするかHTTPステータスをエラーにする(300番台か400番台のステータスを返す)必要があることです。200を返すと画面が変わりません。

app/controllers/entries_controller.rb
  def create
    @entry = Entry.new(entry_params)
    if @entry.save
      redirect_to @entry, notice: "Entry was successfully created."
    else
      render :new, status: :unprocessable_entity # statusが必須
    end
  end

POSTのときにバグによる500エラーが出たときは、TurboはRailsのいつものエラー画面を出してくれません。これはそういうものなのか、これから変わるのか分かりません。

IE対応

TurboはIE 11で動きません。Polyfillをあれこれ入れて試してみましたが、無理そうです。

ここまでの感想

  • Turboは、Turbolinksよりもめっちゃ速い。
  • バリデーションエラーでPOSTによる画面遷移をしないのは、たいへんありがたい。このためだけでもTurboを使いたい。
  • 今年はいよいよIEを完全に切る年になるか。

続き:

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?