Ruby on Rails Advent Calendar 2021の枠が空いていたので、あとから登録しました
はじめに
個人的なプロジェクトになりますが、僕が翻訳しているRSpecの入門書「Everyday Rails - RSpecによるRailsテスト入門」を2022年前半にRails 7.0バージョンにアップデートしようと考えています。
そこでこの本の中で使っているサンプルアプリケーションをRails 7.0でゼロから作り直してみました。フロントエンド周りを中心に結構考え方が変わっている部分があったので、「ここでハマった!」とか「こういうポイントを押さえておくといいかも」という点をあれこれ書いてみます。
なお、Rails 7.0版のサンプルアプリケーションはまだ公開できる状態ではないので、公開はもうしばらくお待ちください🙏
今回作成したサンプルアプリケーションはこちらで公開しています。
実行環境
この記事は以下の実行環境で動作確認しました。
- Rails 7.0.0 (revision: 6a0f6c4d70b198ef36c2d512314248dabec6fbbc)
- Ruby 3.1.0
注意事項等
- この情報はRails 7.0がリリースされて間もない、2021年12月31日時点の情報です。日が経てば状況が変わりそうな内容もあるので、適宜最新の情報を確認するようにしてください。
- 僕自身も試行錯誤しながらやっている部分があるので「そのやり方は違うよ」とか「もっといい方法があるよ」という場合はコメント欄等で教えてください。
既存のRailsアプリをRails 7にアップグレードしようとしている方へ
- 本記事はTurboが話題の中心になっていますが、Rails 7.0で"rails new"するのではなく、既存のRailsアプリをRails 7にアップグレードしたときは明示的にturbo-railsのgemやnpmを組み込まない限り、勝手にTurboが有効になることはありません(引き続きrails-ujsが使われます)。
- Turboを導入せずに既存のRailsアプリをRails 7にアップグレードする場合はそれほどハマるところは多くないと思います。ただ、rails-ujsは非推奨になっているのでどこかのタイミングでTurboに移行する必要が出てくるかもしれません。
それでは以下が本文です!
rails newするときのオプションが増えた
今回はCSSフレームワークとしてBootstrapを使いたかったので、以下のコマンドでrails newしました。
rails new everydayrails-rspec-jp-2022 --css bootstrap
cssは以下のオプションが選べるようです。
rails new myapp --css [tailwind|bootstrap|bulma|postcss|sass]
同じくJS用のオプションもあります。
通常のデフォルトはimportmap
ですが、CSSオプションでtailwind
以外を有効にした場合のデフォルトはesbuild
っぽいです。
rails new myapp --javascript [importmap|esbuild|rollup|webpack]
Rails本体やthorがRuby 3.1.0にまだ対応していない
Rails 7.0.1やThor 1.2.0がリリースされたので、以下の問題は解消しました。
Rails 7.0をRuby 3.1.0で動かそうとするとエラーが起きるため、GitHub上のrailsを使用します。
gem "rails", github: "rails/rails", branch: "7-0-stable"
thorも"DidYouMean::SPELL_CHECKERS.merge!"のような警告を出すため、以下のコードを使いました。
gem 'thor', github: 'deivid-rodriguez/thor', branch: 'support_latest_did_you_mean'
ただし、こういった対応はRailsやthorの次バージョンがリリースされれば不要になるはずです。
bin/dev コマンドでサーバを起動する
Rails 7ではお馴染みのrails s
コマンドでサーバを起動してもJSやCSSがビルド(コンパイル)されません。代わりにbin/dev
コマンドで起動するとJSやCSSがビルドされ、なおかつJSやCSSを変更したときに自動的に再ビルドされます。
このとき、foremanが必要になるのでbin/dev
の実行時に"foreman: command not found"のようなエラーが出た場合は gem install foreman
でforemanをインストールしてください。
MinitestやRSpecのような自動テストを実行するときも、JSやCSSを最新に保つ必要があるので、開発時は常時 bin/dev
で開発サーバを動かしたままにしておく方が良いです。
bin/devのからくり
bin/dev
の中身は以下のようになってます。
#!/usr/bin/env bash
if ! command -v foreman &> /dev/null
then
echo "Installing foreman..."
gem install foreman
fi
foreman start -f Procfile.dev
最後のforeman start -f Procfile.dev
がポイントです。そしてProcfile.dev
の中身は以下のようになっています。
web: bin/rails server -p 3000
js: yarn build --watch
css: yarn build:css --watch
さらに、build
やbuild:css
はpackage.json
の中で定義されています。
{
"name": "app",
"private": "true",
"dependencies": {
"@hotwired/stimulus": "^3.0.1",
"@hotwired/turbo-rails": "^7.1.0",
"@popperjs/core": "^2.11.0",
"bootstrap": "^5.1.3",
"esbuild": "^0.14.9",
"sass": "^1.45.1"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds",
"build:css": "sass ./app/assets/stylesheets/application.bootstrap.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules"
}
}
ここまでの知識を応用すると、bin/dev
を使わずにJSやCSSをビルドしたい場合に以下のコマンドを使うことができます。
# JSのビルド
yarn build
# CSSのビルド
yarn build:css
(2022.4.20追記)「Everyday Rails - RSpecによるRailsテスト入門」の読者のみなさんへ
Everyday Railsのサンプルアプリケーションではjsbundling-rails/cssbundling-railsからimportmap-railsに移行しました。そのため、bin/dev
ではなくbin/rails s
でサーバが起動するようになっています。
Turboがいろいろと厄介
Rails 7.0でデフォルトで導入されるTurboがなかなかのクセモノです。
特別難しい処理を実装したわけでもないのに、以下のような症状が出たときはこのあとに説明するポイントをチェックしてみてください。
- 保存ボタンをクリックしても画面遷移せず、同じ画面が再描画される
- 保存ボタンをクリックすると画面遷移はしたが、処理の完了を知らせるフラッシュメッセージが出ない
- 削除ボタンをクリックしたら「本当に削除しますか?」の確認ダイアログが出ず、いきなり処理が実行される
- ボタンやリンクをクリックするとなぜか404エラーが発生した
バリデーション失敗時に status: :unprocessable_entity
を付ける必要がある
Turboを使っている場合、バリデーション失敗時のレスポンスに必ず status: :unprocessable_entity
を付ける必要があります。これがないとバリデーション失敗時のエラーメッセージが表示されません。
def create
@project = current_user.projects.new(project_params)
respond_to do |format|
if @project.save
format.html { redirect_to project_url(@project), notice: "Project was successfully created." }
format.json { render :show, status: :created, location: @project }
else
# status: :unprocessable_entity が必須!!
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end
link_toのmethod:
オプションの書き方が変わった
Turboを使っている場合、link_to
メソッドのmethod:
オプションの書き方が変わりました。
<!-- 従来の書き方(rails-ujsを使っている場合) -->
<%= link_to 'Delete', [task.project, task], method: :delete %>
<!-- Turboを使っている場合 -->
<%= link_to 'Delete', [task.project, task], data: { turbo_method: :delete } %>
ただし、link_to
でDELETEリクエストを送信する場合は、次のセクションで述べる注意点に気を付ける必要があります。
destroyのレスポンスに status: :see_other
を付ける必要がある
Turboを使っている場合、destroyアクションのレスポンスには必ず status: :see_other
を付ける必要があります。
def destroy
@task.destroy
respond_to do |format|
# status: :see_other が必須!!
format.html { redirect_to @project, notice: "Task was successfully destroyed.", status: :see_other }
format.json { head :no_content }
end
end
status: :see_other
がないと非常に危険!!
これがないとリダイレクト先のURLにDELETEリクエストで遷移してしまい、404エラーが発生したり、最悪、予期せぬリソースを削除してしまうことがあります😱
たとえばこんなことが起きます。
Taskを削除するためにDeleteボタンをクリックします。(/projects/3/tasks/10
へDELETEリクエストを送信)
なぜか404エラーが発生します。
Chromeのネットワークタブをよく見ると・・・削除に成功した後、リダイレクト先の /projects/3
にDELETEリクエストで遷移しています。これにより、Taskの親レコードであるid=3のProjectが削除されます(おいおいおい!!)
Projectを削除した後は、/projects
ページにリダイレクトします。ここでもDELETEリクエストを送信します。しかし、そんなルーティングはないので404エラーになります。
そのあとはなぜか/projects/3
にGETでアクセスしようとしています。しかし、id=3のProjectは削除された後なので、やはり404エラーが発生します。そしてブラウザにはこのエラーが表示されています。
というわけで、 status: :see_other
を付けなかったがために、404エラーが起きるだけでなく、消すつもりのなかったProjectまで削除されてしまうという、怖い例を紹介しました。Turboを使う場合は十分に気を付けてください。
ボタンやリンクのクリック時に何か予期せぬ動きに気づいたら、Chromeのネットワークタブを開いておかしなリクエストやレスポンスが発生していないかチェックすると、解決の糸口が見つかるかもしれません。
Turboが動作しているときは"fetch"や"turbo"の文字が見えるはずです。
また、通常のリダイレクトはStatusが302ですが、 status: :see_other
が付いているときはStatusが303になります。
上の問題は link_to
で削除を実行するときに起きる
なお、上の問題は link_to
で削除ボタン(削除リンク)を作った場合に発生します。button_to
の場合は status: :see_other
を付けなくても正常に動作します。
<!-- status: :see_other が必須 -->
<%= link_to 'Delete', [task.project, task], data: { turbo_method: :delete } %>
<!-- status: :see_other がなくても大丈夫 -->
<%= button_to 'Delete', [task.project, task], method: :delete %>
Rails 7.0でscaffoldを作ると削除ボタンが button_to
で作成されます。そのため、destroyアクションにはstatus: :see_other
が付いていません。参考までにscaffoldで自動生成されたコードを載せておきます。
<p style="color: green"><%= notice %></p>
<%= render @task %>
<div>
<%= link_to "Edit this task", edit_task_path(@task) %> |
<%= link_to "Back to tasks", tasks_path %>
<%= button_to "Destroy this task", @task, method: :delete %>
</div>
# DELETE /tasks/1 or /tasks/1.json
def destroy
@task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: "Task was successfully destroyed." }
format.json { head :no_content }
end
end
しかし、デザイン上の都合等でbutton_to
をlink_to
を変えると、前述の問題が起きるので注意してください。ちなみに button_to
は status: :see_other
が付いていても正常に動いてそうなので、scaffoldの時点で status: :see_other
が付いている方が嬉しいですね。。
確認ダイアログ(confirm:
オプション)の出し方が変わった
Turboを使っている場合、リンクやボタンをクリックした際の確認ダイアログを出すためには次のように書く必要があります。
<!-- link_toの場合 -->
<%= link_to 'Delete', [task.project, task], data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' } %>
<!-- button_toの場合 -->
<%= button_to "Delete", [task.project, task], method: :delete, data: { turbo_confirm: "Are you sure?" } %>
(2023-02-15追記)
上記の記述はTurbo 7.2 (turbo-rails 1.3)以降の場合です。それ以前は form: { data: { turbo_confirm: "Are you sure?" } }
のように form:
で囲む必要がありました(修正PR)。
なお、GETリクエストでlink_to
を作るときもturbo_method:
オプションは必要です。
<%= link_to 'Cancel', task.project, data: { turbo_method: :get, turbo_confirm: 'Are you sure?' } %>
(2022.1.28追記)
submitボタンの場合はformタグにdata-turbo-confirm
を書く必要があるようです。
詳しくは以下の記事をご覧ください。
disable_withの指定方法が変わった
これまではボタンの二重サブミットを防ぐためにdata: { disable_with: '送信中...' }
のような書き方が用意されていましたが、Turboを使う場合はボタンタグの中に2つのテキストを用意し、それをCSSで制御するような形になります。
<button class="btn btn-primary">
<span class="show-when-enabled">Submit</span>
<span class="show-when-disabled">Submitting...</span>
</button>
button .show-when-disabled { display: none; }
button[disabled] .show-when-disabled { display: initial; }
button .show-when-enabled { display: initial; }
button[disabled] .show-when-enabled { display: none; }
上のコードを実際に動かすとこうなります。
Turboがイヤでもrails-ujsは非推奨になったので戻りづらい
ここまでTurboの落とし穴をいろいろ紹介してきたので、読者のみなさんの中には「Oh、しばらくrails-ujsのままで行こうかな・・・」と思っている人も多いんじゃないかと思います。しかし、rails-ujsは非推奨になったため、しばらくすると使えなくなるかもしれません。
APIドキュメント上でもconfirm:
オプションやdisable_with:
オプションは非推奨になったことが記載されています。
confirmやdisable_with(みたいな機能)とTurboは不可分
Turboはdata: { turbo: false }
オプションを付けることで個別にTurboの使用を無効化することができます。
Turboを極力使いたくない人は「なるほど!」と思って次のようなコードを書きたくなるかもしれません。
<!-- Turboはイヤだ!昔のやり方がいい!! -->
<%= link_to 'Delete', [task.project, task], method: :delete, data: { turbo: false } %>
しかし、上のコードは意図した通りに動きません。なぜならmethod: :delete
を実現しているのはrails-ujsであり、rails-ujsはRails 7.0ではデフォルトでインストールされないからです。
また、GETリクエストを送るリンクであっても、Turboを無効化した上で確認ダイアログを出す、といったことはできません。なぜなら、Turboを無効化することで、turbo_confirm:
オプションも無効化されるからです。そのため、以下のようなコードでは確認ダイアログは出せません。
<!-- Turboを無効化したいが、確認ダイアログだけは出したい、みたいなことはできない -->
<%= link_to 'Cancel', task.project, data: { turbo: false, turbo_confirm: 'Are you sure?' } %>
これは上で紹介した二重サブミットを防止するボタンの表示制御(disable_withみたいな機能)についても同様です。
そのためRails 7.0時代では以下のどちらかを選択することになりそうです。
- Turboを有効化して、Turboが提供するconfirmやdisable_with(みたいな機能)を利用する(が、既存のRailsアプリをアップグレードする場合はかなりのコード変更が発生しそう)
- 非推奨であることを理解しつつ、rails-ujsを使ってレガシーな書き方を使い続ける(が、数年後には使えなくなる可能性もある)
他にもいろいろハマりどころがありそうな予感……
今回僕が作ったのはごく簡単なRailsアプリなのでこれぐらいで済みましたが、Turboを導入すると他にもいろいろハマりどころがありそうな予感がしています(特にjQueryやVue.js、Reactを多用している場合など)。
TurbolinksがRails 4.0で導入されたときに「メリットよりもハマるデメリットの方が大きいからオフにする」という話をよく見かけましたが、それと同じ状況が起きそうです(そもそもTurbolinksの進化版がTurboですし)。
ただ、Turbolinksとは異なり、前述の通りTurboをオフにするとconfirmやdisable_withが使えなくなりますし、rails-ujsは非推奨になったので、Turboとはうまく付き合っていかなければいけないかもしれません。
DeviseがTurboに対応していない
DeviseがTurboに正式対応しました
Turboに正式対応したDevise 4.9.0が2023年2月17日にリリースされました。
以下の記事で導入方法を説明しているので、Deviseを使う場合はこちらの記事を読んでください。
Devise 4.9をインストールしてRails 7.0 (Hotwire/Turbo)に対応する - Qiita
上で説明してきたように、Turboを導入するとviewやコントローラの書き方がいろいろと変わってきます。自分でviewやコントローラを書いている場合はコツコツとコードを書き換えればいいのですが、場合によってはgemが提供しているviewやコントローラを使う場合があります。その代表例がDeviseです。
この記事の執筆時点ではDeviseのバージョンはDevise 4.8.1ですが、DeviseはまだTurboに対応できていないことが正式に述べられています。
4.8.1 - 2021-12-16
enhancements
Add support for Rails 7.0. Please note that Turbo integration is not fully supported by Devise yet.
具体的には次のような問題が起きます。
- バリデーション失敗時のレスポンスに
status: :unprocessable_entity
が付いていないので、ログインに失敗してもエラーメッセージが何も表示されない - DELETEリクエストのレスポンスに
status: :see_other
が付かないため、ログアウトやアカウント削除のリンクが正常に機能しない(ルーティングエラーが起きたりする) - アカウント削除のボタンをクリックしても確認ダイアログが表示されない
このため、僕は一時的な回避策として以下のような対応を取りました。
formはいったんTurboを無効化する
2023.1.4追記:このセクションの記述は無視してください
status: :unprocessable_entity
を付けるためにはDeviseのコントローラを修正しなければなりません。ですが、Deviseのコントローラの実装はscaffoldのような単純なものではないので、 status: :unprocessable_entity
を付けようにもどこに付ければ良いかぱっとわかりません。
そのため、コントローラをいじるのは諦めて rails generate devise:views
で生成されたviewのformにdata: { turbo: false }
オプションを付けて回りました。
<!-- Turboを無効化したformの例 -->
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: { turbo: false }) do |f| %>
DELETEリクエストのみ status: :see_other
を付ける
status: :see_other
を付ける2023.1.4追記:このセクションの記述は無視してください
今回、DELETEリクエストはログアウトとアカウント削除の2つだけだったので、これは自前のコントローラを用意してレスポンスを返す部分をオーバーライドしました。
【注意!!】
以下は応急処置目的で雑に追加したコードです。ユースケースによっては不具合を引き起こす可能性もあるので、実務で導入する場合はDeviseの実装コードを十分確認した上で対処することを推奨します。(というか、DeviseがTurboに正式対応するまでTurboの導入は見送った方がいいかも)
# registrationsとsessionsのコントローラは自前で用意
devise_for :users, controllers: { registrations: 'registrations', sessions: 'sessions' }
class RegistrationsController < Devise::RegistrationsController
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message! :notice, :destroyed
yield resource if block_given?
# status:とnotice:を追加
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name), status: :see_other, notice: find_message(:destroyed) }
end
end
class SessionsController < Devise::SessionsController
def respond_to_on_destroy
respond_to do |format|
format.all { head :no_content }
# status:とnotice:を追加
format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name), status: :see_other, notice: find_message(:signed_out) }
end
end
end
ログアウトリンクをTurboに対応させる
2023.1.4追記:このセクションの記述は無視してください
ログアウトのリンクは以下のように turbo_method: :delete
を使うように変更します。
<%= link_to "Sign Out", destroy_user_session_path, data: { turbo_method: :delete } %>
アカウント削除ボタンをTurboに対応させる
2023.1.4追記:このセクションの記述は無視してください
確認ダイアログが表示されるよう、アカウント削除ボタンを以下のように修正します。
<%= button_to "Cancel my account", registration_path(resource_name), method: :delete, form: { data: { turbo_confirm: "Are you sure?" } } %>
Turboを使ってAjax風の更新処理を実装する
ずっとTurboを悪者扱いにしてきましたが、Turboを使うとこんなことができますよ、というポジティブな例を紹介しておきます。
今回実装するのはこんなふうにチェックボックスをクリックすると画面のリロード無しにタスクの完了状態を切り替えることができる機能です。
更新用のルーティングを定義する
まず、タスクの完了状態を切り替えるためのルーティング(tasks#toggle
)を定義します。
resources :projects do
# 略
resources :tasks do
member do
patch :toggle
end
end
end
partialを作る
次に、Turboを利用するためのpartialを用意します。
<%= turbo_frame_tag task do %>
<%= form_with model: task, url: [:toggle, task.project, task] do |f| %>
<label class="<%= task.completed? ? 'completed' : '' %>">
<%= f.check_box :completed, onchange: "this.form.requestSubmit()" %>
<%= task.name %>
</label>
<% end %>
<% end %>
ポイントは以下のとおりです。
-
turbo_frame_tag task do
で囲んだ部分がTurboで差し替え可能なDOMになる。 -
onchange: "this.form.requestSubmit()"
でチェックボックスがON/OFFされたときにsubmitされるようにする。-
submit()
ではTurboが動作しないので、requestSubmit()
にしないといけない点に注意。
-
なお、上のpartialは以下のようなHTMLを出力します。
<turbo-frame id="task_17">
<form action="/projects/3/tasks/17/toggle" accept-charset="UTF-8" method="post">
<input type="hidden" name="_method" value="patch" autocomplete="off">
<input type="hidden" name="authenticity_token" value="m-L35ID..." autocomplete="off">
<label class>
<input name="task[completed]" type="hidden" value="0" autocomplete="off">
<input onchange="this.form.requestSubmit()" type="checkbox" value="1" name="task[completed]" id="task_completed">
原稿を書く
</label>
</form>
</turbo-frame>
メインのviewに組み込む
上で作ったpartialをviewに組み込みます。partialの中ではturbo_frame_tag task do
を使っていますが、ここでは通常のpartialのようにHTMLがレンダリングされます。
<!-- 略 -->
<td>
<%= render 'tasks/completed', task: task %>
</td>
<!-- 略 -->
ちなみに以下の青枠部分がpartialの表示部分で、Turboで差し替え可能な部分になります。
コントローラを実装する
コントローラのtasks#toggle
アクションは次のように実装しました。
def toggle
@task.update(completed: !@task.completed)
render turbo_stream: turbo_stream.replace(
@task,
partial: 'completed',
locals: { task: @task }
)
end
ポイントは以下のとおりです。
-
turbo_stream: turbo_stream.replace
で「Turboを利用したDOMに置き換え」を指定する。 -
replace
メソッドの各引数の意味は以下のとおり。-
@task
= Taskオブジェクトが生成するdom_id
("task_17"など)に合致するidのturbo-frameを置き換える -
partial: 'completed'
= 置き換えに使用するpartial -
locals: { task: @task }
= partialに渡すパラメータ
-
CSSで表示を整える
Taskが完了するとlabelタグに"completed"のclassが付くので、その場合は取り消し線が入るようにします。
.completed {
text-decoration: line-through;
}
完成!
これで完成です
なお、この機能の作成にあたっては以下のサイトを参考にさせてもらいました。
RSpec実行時の警告に対応する
RSpecを実行すると警告がいくつか出たので以下のように対応しました。
debug.gemをrequire: false
する
js: true
が付いているシステムスペックを実行すると以下のような警告が出ます。
$ bundle exec rspec -f progress
...................................................................DEBUGGER: Attaching after process 69034 fork to child process 69055
...
Finished in 3.26 seconds (files took 1.79 seconds to load)
70 examples, 0 failures
一瞬「テストに問題があるのかな?」と勘違いしてしまうので、debug.gemをrequire: false
にして必要なとき以外は読み込まれないようにしました。
gem "debug", platforms: %i[ mri mingw x64_mingw ], require: false
Capybaraの警告に対処する
js: true
が付いているシステムスペックを実行すると以下のような警告が出ます。
WARN Selenium [DEPRECATION] [:browser_options] :options as a parameter for driver initialization is deprecated. Use :capabilities with an Array of value capabilities/options if necessary instead.
この警告はCapybaraの問題なのですが、masterではすでに対応済みなので、次バージョン(3.36.0の次)がリリースされるまでGitHubのコードを使います。
gem "capybara", github: 'teamcapybara/capybara'
ちなみにこの警告を修正するプルリクエストは僕が出しました(自慢)。
VCRの警告に対処する
VCR 6.1.0がリリースされたので、以下の問題は解消しました。
Ruby 3.1.0でVCRを使うと以下のような警告(例外情報)が表示されます。
/Users/jnito/.rbenv/versions/3.1.0-preview1/bin/bundle: warning: Exception in finalizer #<Proc:0x000000010a01e6f8 /Users/jnito/.rbenv/versions/3.1.0-preview1/lib/ruby/gems/3.1.0/gems/vcr-6.0.0/lib/vcr/library_hooks/webmock.rb:36 (lambda)>
/Users/jnito/.rbenv/versions/3.1.0-preview1/lib/ruby/gems/3.1.0/gems/vcr-6.0.0/lib/vcr/library_hooks/webmock.rb:36:in `block in global_hook_disabled_requests': wrong number of arguments (given 1, expected 0) (ArgumentError)
こちらもmasterではすでに対応済みなので、次バージョン(6.0.0の次)がリリースされるまでGitHubのコードを使います。
gem 'vcr', github: 'vcr/vcr'
まとめ
というわけで、この記事ではRails 7.0でゼロから簡単なRailsアプリケーションを作ったときに気づいた点やハマった点をあれこれ書いてみました。
実際にアプリを作る前は「フロントエンド周り以外はそんなに変わってないのでは?」と考えていましたが、そのフロントエンド周りが思った以上に変わっていたので、従来のノウハウがそのままでは活かせない部分が多かったです。
特にコントローラに追加する status: :unprocessable_entity
や status: :see_other
オプションなどは、予備知識がまったくなかったのでなぜエラーが出るのかわからず、かなりハマりました。
みなさんもRails 7.0でRailsアプリを作るときはこの記事に挙げたポイントに注意しながら開発していってください。
謝辞
「Rails 7、ここがようわからん」と思った点はruby-jpで質問していろいろ情報を教えてもらいました。回答してくれたみなさん、どうもありがとうございました!
PR:「Everyday Rails - RSpecによるRailsテスト入門」をアップデートしました!
冒頭にもちらっと書いたとおり、僕が翻訳している電子書籍「Everyday Rails - RSpecによるRailsテスト入門」を2022年前半にアップデートする予定です アップデートしました!
アップデート版ではRuby 7.0 + Ruby 3.1環境でテストを書く方法を説明しています。
今回のアップデートの詳細は以下のブログで紹介しています。
すでに持っている方は無料でアップデートできますので、Leanpubのサイトから最新版をダウンロードしてください。