search
LoginSignup
235
Help us understand the problem. What are the problem?

Ruby on Rails Advent Calendar 2021 Day 21

posted at

updated at

Rails 7.0 + Ruby 3.1でゼロからアプリを作ってみたときにハマったところあれこれ

:christmas_tree: Ruby on Rails Advent Calendar 2021の枠が空いていたので、あとから登録しました :christmas_tree:

はじめに

個人的なプロジェクトになりますが、僕が翻訳している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を使用します。

Gemfile
gem "rails", github: "rails/rails", branch: "7-0-stable"

thorも"DidYouMean::SPELL_CHECKERS.merge!"のような警告を出すため、以下のコードを使いました。

Gemfile
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の中身は以下のようになってます。

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の中身は以下のようになっています。

Procfile.dev
web: bin/rails server -p 3000
js: yarn build --watch
css: yarn build:css --watch

さらに、buildbuild:csspackage.jsonの中で定義されています。

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 

なお、JSとCSSをまとめてビルドしたいときはassets:precompileコマンドが使えます。

# JSとCSSをまとめてビルド
rails assets:precompile

(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リクエストを送信)

Screen Shot 2021-12-31 at 16.27.00.png

なぜか404エラーが発生します。

Screen Shot 2021-12-31 at 16.27.17.png

Chromeのネットワークタブをよく見ると・・・削除に成功した後、リダイレクト先の /projects/3 にDELETEリクエストで遷移しています。これにより、Taskの親レコードであるid=3のProjectが削除されます(おいおいおい!!)

Screen Shot 2021-12-31 at 16.27.39.png

Projectを削除した後は、/projectsページにリダイレクトします。ここでもDELETEリクエストを送信します。しかし、そんなルーティングはないので404エラーになります。

Screen Shot 2021-12-31 at 16.27.48.png

そのあとはなぜか/projects/3にGETでアクセスしようとしています。しかし、id=3のProjectは削除された後なので、やはり404エラーが発生します。そしてブラウザにはこのエラーが表示されています。

Screen Shot 2021-12-31 at 16.28.01.png

というわけで、 status: :see_other を付けなかったがために、404エラーが起きるだけでなく、消すつもりのなかったProjectまで削除されてしまうという、怖い例を紹介しました。Turboを使う場合は十分に気を付けてください。

ボタンやリンクのクリック時に何か予期せぬ動きに気づいたら、Chromeのネットワークタブを開いておかしなリクエストやレスポンスが発生していないかチェックすると、解決の糸口が見つかるかもしれません。

Turboが動作しているときは"fetch"や"turbo"の文字が見えるはずです。
また、通常のリダイレクトはStatusが302ですが、 status: :see_otherが付いているときはStatusが303になります。

Screen Shot 2022-01-02 at 9.00.36.png

上の問題は 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で自動生成されたコードを載せておきます。

app/views/tasks/show.html.erb
<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>
app/controllers/tasks_controller.rb
  # 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_tolink_toを変えると、前述の問題が起きるので注意してください。ちなみに button_tostatus: :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, form: { data: { turbo_confirm: "Are you sure?" } } %>

なお、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; }

上のコードを実際に動かすとこうなります。

bkOudzu260.gif

Turboがイヤでもrails-ujsは非推奨になったので戻りづらい

ここまでTurboの落とし穴をいろいろ紹介してきたので、読者のみなさんの中には「Oh、しばらくrails-ujsのままで行こうかな・・・」と思っている人も多いんじゃないかと思います。しかし、rails-ujsは非推奨になったため、しばらくすると使えなくなるかもしれません。

APIドキュメント上でもconfirm:オプションやdisable_with:オプションは非推奨になったことが記載されています。

Screen Shot 2021-12-31 at 17.16.36.png

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に対応していない

上で説明してきたように、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.

https://github.com/heartcombo/devise/blob/main/CHANGELOG.md

具体的には次のような問題が起きます。

  • バリデーション失敗時のレスポンスに status: :unprocessable_entity が付いていないので、ログインに失敗してもエラーメッセージが何も表示されない
  • DELETEリクエストのレスポンスに status: :see_other が付かないため、ログアウトやアカウント削除のリンクが正常に機能しない(ルーティングエラーが起きたりする)
  • アカウント削除のボタンをクリックしても確認ダイアログが表示されない

このため、僕は一時的な回避策として以下のような対応を取りました。

formはいったんTurboを無効化する

status: :unprocessable_entity を付けるためにはDeviseのコントローラを修正しなければなりません。ですが、Deviseのコントローラの実装はscaffoldのような単純なものではないので、 status: :unprocessable_entity を付けようにもどこに付ければ良いかぱっとわかりません。

そのため、コントローラをいじるのは諦めて rails generate devise:views で生成されたviewのformにdata: { turbo: false }オプションを付けて回りました。

app/views/devise/sessions/new.html.erb
<!-- Turboを無効化したformの例 -->
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: { turbo: false }) do |f| %>

DELETEリクエストのみ status: :see_other を付ける

今回、DELETEリクエストはログアウトとアカウント削除の2つだけだったので、これは自前のコントローラを用意してレスポンスを返す部分をオーバーライドしました。

【注意!!】
以下は応急処置目的で雑に追加したコードです。ユースケースによっては不具合を引き起こす可能性もあるので、実務で導入する場合はDeviseの実装コードを十分確認した上で対処することを推奨します。(というか、DeviseがTurboに正式対応するまでTurboの導入は見送った方がいいかも)

config/routes.rb
# registrationsとsessionsのコントローラは自前で用意
devise_for :users, controllers: { registrations: 'registrations', sessions: 'sessions' }
app/controllers/registrations_controller.rb
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
app/controllers/sessions_controller.rb
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に対応させる

ログアウトのリンクは以下のように turbo_method: :delete を使うように変更します。

<%= link_to "Sign Out", destroy_user_session_path, data: { turbo_method: :delete } %>

アカウント削除ボタンをTurboに対応させる

確認ダイアログが表示されるよう、アカウント削除ボタンを以下のように修正します。

<%= button_to "Cancel my account", registration_path(resource_name), method: :delete, form: { data: { turbo_confirm: "Are you sure?" } } %>

Turboを使ってAjax風の更新処理を実装する

ずっとTurboを悪者扱いにしてきましたが、Turboを使うとこんなことができますよ、というポジティブな例を紹介しておきます。

今回実装するのはこんなふうにチェックボックスをクリックすると画面のリロード無しにタスクの完了状態を切り替えることができる機能です。

rUUASb6ENv.gif

更新用のルーティングを定義する

まず、タスクの完了状態を切り替えるためのルーティング(tasks#toggle)を定義します。

config/routes.rb
  resources :projects do
    # 略
    resources :tasks do
      member do
        patch :toggle
      end
    end
  end

partialを作る

次に、Turboを利用するためのpartialを用意します。

app/views/tasks/_completed.html.erb
<%= 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がレンダリングされます。

app/views/tasks/_task.html.erb
  <!-- 略 -->
  <td>
    <%= render 'tasks/completed', task: task %>
  </td>
  <!-- 略 -->

ちなみに以下の青枠部分がpartialの表示部分で、Turboで差し替え可能な部分になります。

Screen Shot 2021-12-31 at 19.07.50.png

コントローラを実装する

コントローラのtasks#toggleアクションは次のように実装しました。

app/controllers/tasks_controller.rb
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;
}

完成!

これで完成です :tada:

rUUASb6ENv.gif

なお、この機能の作成にあたっては以下のサイトを参考にさせてもらいました。

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にして必要なとき以外は読み込まれないようにしました。

Gemfile
  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のコードを使います。

Gemfile
  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のコードを使います。

Gemfile
  gem 'vcr', github: 'vcr/vcr'

まとめ

というわけで、この記事ではRails 7.0でゼロから簡単なRailsアプリケーションを作ったときに気づいた点やハマった点をあれこれ書いてみました。

実際にアプリを作る前は「フロントエンド周り以外はそんなに変わってないのでは?」と考えていましたが、そのフロントエンド周りが思った以上に変わっていたので、従来のノウハウがそのままでは活かせない部分が多かったです。

特にコントローラに追加する status: :unprocessable_entitystatus: :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のサイトから最新版をダウンロードしてください。

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
What you can do with signing up
235
Help us understand the problem. What are the problem?