はじめに
Rubyを使用したOSSのWebアプリケーションフレームワーク、Ruby on Rails(以下Rails)の最新バージョンである7.2(以下Rails 7.2)が2024年8月10日にリリースされました。
Rails 7.2は、開発用のDockerコンテナの設定の生成、YJITのデフォルト化、RuboCop / Brackeman / GitHub CIの設定の生成など、主に、プロジェクトを開発、運用するに当たって必要な設定をあらかじめフレームワーク側で用意したリリースとなっています。
本記事では、Railsの公式ブログやRailsガイド、GitHubのRailsプロジェクトのIssuesやPull Requestsの内容をもとに、Rails 7.2の主要な機能追加・変更点の紹介を行います。
※ 以前のバージョンのRailsの主要な新機能・機能追加・変更点については以下を参照してください。
注意点
Rubyのバージョン
Rails 7.2を動かすには、Ruby 3.1.0以上が必要になります。
Railsのサポート対象のバージョン
Rails 7.2のリリース後は、バグ修正の対象がバージョン7.2、セキュリティ修正の対象が7.2、7.1、深刻なセキュリティ修正の対象が7.2、7.1、7.0、6.1系列となります。それより前のバージョンに関してはサポートは行われません。
参考
新機能
開発用のDockerコンテナ(devコンテナ)
Dockerコンテナをフル機能の開発環境として使用できるdevコンテナと呼ばれる新機能が追加されました。
デフォルトでは、以下のようなコンテナが含まれています。
- データベース(SQLite、PostgreSQL、MySQL、MariaDBなど)
- Active Storage
- Redis
- システムテスト(Headless Chrome)
新規のアプリケーションでdevコンテナを使用するには、rails new
でアプリケーションを生成する際に--devcontainer
オプションを追加します。
$ rails new myapp --devcontainer
既存のアプリケーションは、Railsのdevcontainer
コマンドを使用することで、devコンテナの設定を生成することができます。
$ rails devcontainer
Generating Dev Container with the following options:
app_name: blog
database: sqlite3
active_storage: true
redis: true
system_test: true
node: false
create .devcontainer
create .devcontainer/devcontainer.json
create .devcontainer/Dockerfile
create .devcontainer/compose.yaml
gsub test/application_system_test_case.rb
.devcontainer
ディレクトリ以下に生成された、これらの設定ファイルはDevelopment Container Specificationに基づいており、VSCodeなどの対応したエディタで開くことによって、Dockerイメージを取得し、コンテナを生成、起動することが可能です。
参考
YJITのデフォルト化
YJITはRubyのJITコンパイラで、有効にすることでRailsアプリケーションのパフォーマンスを大幅に向上させ、レイテンシを15〜25%改善することができます。
Rails 7.2でRuby 3.3以上を使用している場合は、YJITがデフォルトで有効になっています。
無効にする場合は、以下のように設定を行う必要があります。
Rails.application.config.yjit = false
ブラウザのバージョンのGuardのデフォルト化
アプリケーション生成時に以下の設定がApplication Controllerに追加されるようになりました。
allow_browser versions: :modern
これは、リクエストのヘッダのUser-Agentに基づいて、モダンブラウザ(WebP画像、Import maps、CSS入れ子などの機能をサポート)のアクセスを許可するというもので、古いバージョンのブラウザに対しては許可せず、HTTP status 406を返すようになっています。
User-Agentがリクエストのヘッダに含まれない場合もアクセスを許可する点には注意してください。
この設定は各コントローラでカスタマイズ可能で、以下のように特定のブラウザの特定のバージョン以上を許可することもできます。
# Safari 16.4+、Firefox 121+をサポートし、IEをサポートしない
allow_browser versions: { safari: 16.4, firefox: 121, ie: false }
また、以下のようにonly
オプションをつけることによって、コントローラの特定のアクションのみ、ブラウザのバージョンの制限をかけることができるようになっています。
# showアクションで、Opera 104+、Chrome 119+をサポートする
allow_browser versions: { opera: 104, chrome: 119 }, only: :show
参考
PWA (Progressive Web Application)ファイルのデフォルト化
RailsでPWAアプリケーションを作成可能なように、デフォルトでmanifest.json
ファイルとservice-worker.js
ファイルをapp/view/pwa
以下に生成し、以下のルーティングを追加するようになりました。
get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
参考
RuboCopのデフォルト化
デフォルトでRuby静的構文アナライザとフォーマッタであるRuboCopが含まれるようになり、RuboCopのルール集としてrubocop-rails-omakaseを使用するようになりました。
rails new
でRailsアプリケーションを作成後にすぐにrubocop
コマンドでフォーマットを行うことができます。
このルール集は、Rails作者のDHHが作成したもので、チーム内で特定のコーディングスタイルを適用していない場合の出発点として便利に使うことができそうです。
参考
Brakemanのデフォルト化
デフォルトでRubyのセキュリティ脆弱性ツールのBrakemanが含まれるようになりました。
brakeman
コマンドでセキュリティチェックを行うことが可能になり、また、後述するGitHub CIワークフローでも、GitHubにコミットがpushされる毎に、Brakemanを走らせることができます。
参考
GitHub CIワークフローのデフォルト化
デフォルトでGitHub CIワークフローが作成されるようになり、.github/workflows/ci.yml
、.github/dependabot.yml
ファイルが生成されるようになりました。
(rails new
を実行する際に、--skip-ci
オプションをつけることで、ファイルの生成をスキップすることができます。)
初期状態ではGitHub CIでテストと、前述したRuboCopとBrakemanを実行することができます。テストでRSpecを実行したり、カスタマイズを行う場合は.github/workflows/ci.yml
ファイルを修正する必要があります。
参考
機能追加
DBのトランザクションへのコールバックの追加
DBのトランザクションのコミットやロールバックの前後にコールバックを指定して、実行できるようになりました。
具体的には、ActiveRecord::Base.transaction
メソッドが、ActiveRecord::Transaction
オブジェクトをブロックに渡すようになり、例えば以下のようにtransaction.after_commit
でトランザクション内でコールバックを指定できるようになっています。
Article.transaction do |transaction|
article.update(published: true)
transaction.after_commit do
PublishNotificationMailer.with(article: article).deliver_later
end
end
上記の例ではトランザクション内でメール送信のジョブをエンキューするのではなく、トランザクションのコミットを行ってから、エンキューを行うことができます。
参考
DBのトランザクション内でジョブをエンキューした場合はトランザクション外で実行するように
トランザクション内にジョブをエンキューするコードを含む場合に、自動で上記のafter_commit
コールバックを使用して、コミット後に処理を行うようになりました。コミットに失敗した場合は、エンキューされたジョブは破棄されます。
以下のようなコードで、
Topic.transaction do
topic = Topic.create
NewTopicNotificationJob.perform_later(topic)
end
以前はtopic
の保存がコミットされる前にNewTopicNotificationJob
が実行され、別プロセスのジョブが永続化されたtopic
を取得できず、エラーを発生することがありました。Rails 7.2以降では、同じコードでもtopic
の保存のコミット後にジョブが実行されるようになります。
ジョブ内で以下のように設定することで、元の挙動(トランザクション内でコミット前にエンキュー)にすることも可能です。
self.enqueue_after_transaction_commit = :never
参考
変更点
Pumaのスレッド数のデフォルトの変更
Pumaのデフォルトのスレッド数が5から3へと変更になりました。
これは、本番環境で運用されているアプリケーションを分析した結果、スレッド数が多すぎるとレイテンシに影響を及ぼすことが判明したためだそうです。
具体的には、元の5スレッドは低速のSQLクエリやインラインの処理を想定してましたが、複数の高速なSQLクエリや、ジョブ経由の処理には向いておらず、新しい3スレッドはこれらに向けて最適化した形だそうです。
このスレッド数は37signalsのアプリケーションに合わせて設定された値なので、それぞれのアプリケーションの処理やインフラ構成に応じてスレッド数を調整するのが良さそうです。
参考