Ruby on Rails 8.1 リリースノート

Rails 8.1 の注目ポイント:

  • Active Jobの継続機能
  • 構造化イベントレポート
  • ローカルCI
  • Markdownレンダリング
  • コマンドラインでのcredentials取得
  • 関連付けの非推奨化機能
  • Kamalをリモートレジストリ不要で利用可能

このリリースノートでは、主な変更点のみを取り上げています。バグ修正や変更点については、Changelogを参照するか、GitHubのRailsリポジトリにあるコミット一覧を確認してください。

1 Rails 8.1にアップグレードする

既存のアプリケーションをアップグレードするのであれば、その前に質のよいテストカバレッジを用意するのはよい考えです。アプリケーションがRails 8.0までアップグレードされていない場合は先にそれを完了し、アプリケーションが正常に動作することを十分確認してからRails 8.1にアップデートしてください。アップグレードの注意点などについてはRailsアップグレードガイドを参照してください。

2 主要な機能

2.1 Active Jobの継続機能

実行に時間のかかるジョブを、離散的なステップに分割可能になりました。これにより、再起動後に最初からやり直すのではなく、最後に完了したステップの続きから実行を再開できます。これは特にKamalでのデプロイ時に有用です(Kamalはジョブ実行中のコンテナにシャットダウンの猶予をデフォルトで30秒しか与えないためです)。

コード例:

class ProcessImportJob < ApplicationJob
  include ActiveJob::Continuable

  def perform(import_id)
    @import = Import.find(import_id)

    # ブロック形式の場合
    step :initialize do
      @import.initialize
    end

    # ステップにカーソルを設定することで、ジョブの中断時にカーソルが保存される
    step :process do |step|
      @import.records.find_each(start: step.cursor) do |record|
        record.process
        step.advance! from: record.id
      end
    end

    # メソッド形式の場合
    step :finalize
    end

  private
    def finalize
      @import.finalize
    end
end

3 構造化イベントレポート

Railsに組み込まれているデフォルトのロガーは、人間が読むのには適していますが、機械的な後処理にはあまり向いていませんでした。Railsに新しく追加されたイベントレポーターは、構造化されたイベントを生成するための統一されたインターフェイスをRailsアプリケーションに提供します。

Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")

以下のようにイベントにタグを追加できます。

Rails.event.tagged("graphql") do
  # イベントに`{ graphql: true }`タグを追加
  Rails.event.notify("user.signup", user_id: 123, email: "user@example.com")
end

コンテキストを追加することも可能です。

# すべてのイベントに`{request_id: "abc123", shop_id: 456}`コンテキストを追加
Rails.event.set_context(request_id: "abc123", shop_id: 456)

イベントはサブスクライバに送信されます。アプリケーションはサブスクライバを登録して、イベントのシリアライズと送信方法を制御します。サブスクライバは以下のように、イベントハッシュを受け取る#emitメソッドを実装しなければなりません。

class LogSubscriber
  def emit(event)
    payload = event[:payload].map { |key, value| "#{key}=#{value}" }.join(" ")
    source_location = event[:source_location]
    log = "[#{event[:name]}] #{payload} at #{source_location[:filepath]}:#{source_location[:lineno]}"
    Rails.logger.info(log)
  end
end

4 ローカルCI

近年の開発用コンピュータは驚くほど高速になり、多くのコアを搭載しているため、比較的大きなテストスイートでもローカルで十分実行可能です。

このため、小・中規模のアプリケーションでは、クラウドベースのCIセットアップを廃止してローカルでのCI実行に切り替えることが現実的かつ望ましい状況になっています。そこでRailsでは、config/ci.rbに定義することで、bin/ciコマンドで実行できるデフォルトのCI宣言DSLが追加されました。config/ci.rbの内容は以下のような感じになります。

CI.run do
  step "Setup", "bin/setup --skip-server"
  step "Style: Ruby", "bin/rubocop"

  step "Security: Gem audit", "bin/bundler-audit"
  step "Security: Importmap vulnerability audit", "bin/importmap audit"
  step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error"
  step "Tests: Rails", "bin/rails test"
  step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant"

  # `gh` CLIと`gh extension install basecamp/gh-signoff`が必要
  if success?
    step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff"
  else
    failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again."
  end
end

オプションでghと連携することにより、CIが成功しない限りプルリクがマージ可能にならないようにできます。

5 Markdownレンダリング

markdown形式は今やAIのリンガフランカ(共通語)となりつつあります。Railsは、Markdown形式のリクエストに応答して直接レンダリング可能にすることで、markdownの採用を受け入れています。

class Page
  def to_markdown
    body
  end
end

class PagesController < ActionController::Base
  def show
    @page = Page.find(params[:id])

    respond_to do |format|
      format.html
      format.md { render markdown: @page }
    end
  end
end

6 credentialsをコマンドラインで取得

Kamalは、デプロイ時にRailsの暗号化credentialsストアからsecrets(秘密情報)を手軽に取得できるようになりました。これにより、マスターキーさえあれば動作する外部のsecretsストアの安価な代替手段となります。

# .kamal/secrets
KAMAL_REGISTRY_PASSWORD=$(rails credentials:fetch kamal.registry_password)

7 関連付けの非推奨化

Active Recordの関連付けに、deprecated: trueで非推奨化を指定できるようになりました。

class Author < ApplicationRecord
  has_many :posts, deprecated: true
end

これにより、posts関連付けにアクセスすると、非推奨化の警告がレポートされます。以下のような明示的なAPI呼び出しも非推奨化レポートの対象となります。

author.posts
author.posts = ...

以下のように関連付けを間接的に利用する場合やネステッド属性で利用する場合も、非推奨化レポートの対象となります。

author.preload(:posts)

非推奨化レポートでは、3つのモードがサポートされています(:warn:raise:notify)。バックトレースは有効化または無効化できますが、報告された利用箇所の位置は常に取得されます。デフォルトは:warnモードで、バックトレースは無効化されています。

8 Kamalをリモートレジストリ不要でデプロイ

Kamalで基本的なデプロイを行うときに、Docker HubやGitHub Container Registry(GHCR)などのリモートレジストリが不要になりました。Kamal 2.8では、シンプルなデプロイにはデフォルトでローカルレジストリを使うようになりました。大規模なデプロイでは引き続きリモートレジストリが必要ですが、これによりプロジェクトの立ち上げが容易になり、Hello Worldデプロイを実際の環境で確認しやすくなります。

9 Railties

変更点について詳しくはChangelogを参照してください。

9.1 削除されたもの

  • 非推奨化されていたrails/console/methods.rbファイルを削除。

  • 非推奨化されていたbin/rake statsコマンドを削除。

  • 非推奨化されていたSTATS_DIRECTORIESグローバル定数を削除。

9.2 非推奨化

9.3 主な変更

10 Action Cable

変更点について詳しくはChangelogを参照してください。

10.1 削除されたもの

10.2 非推奨化

10.3 主な変更

11 Action Pack

変更点について詳しくはChangelogを参照してください。

11.1 削除されたもの

  • パラメータパーサー内で、パラメータ名の冒頭に含まれるブラケット[]をスキップするサポート(非推奨化)を削除。

    削除前:

    ActionDispatch::ParamBuilder.from_query_string("[foo]=bar") # => { "foo" => "bar" }
    ActionDispatch::ParamBuilder.from_query_string("[foo][bar]=baz") # => { "foo" => { "bar" => "baz" } }
    

    削除後:

    ActionDispatch::ParamBuilder.from_query_string("[foo]=bar") # => { "[foo]" => "bar" }
    ActionDispatch::ParamBuilder.from_query_string("[foo][bar]=baz") # => { "[foo]" => { "bar" => "baz" } }
    
  • セミコロンをクエリ文字列パラメータとして利用するサポート(非推奨化)を削除。

    削除前:

    ActionDispatch::QueryParser.each_pair("foo=bar;baz=quux").to_a
    # => [["foo", "bar"], ["baz", "quux"]]
    

    削除後:

    ActionDispatch::QueryParser.each_pair("foo=bar;baz=quux").to_a
    # => [["foo", "bar;baz=quux"]]
    
  • 複数パスへのルーティング(非推奨化)を削除。

11.2 非推奨化

  • Rails.application.config.action_dispatch.ignore_leading_bracketsを非推奨化。

11.3 主な変更

  • 新規Railsアプリでは、development環境でリダイレクトのログ出力が詳細になった。既存のアプリで有効にするには、config/development.rbファイルにconfig.action_dispatch.verbose_redirect_logs = trueを追加すること。

12 Action View

変更点について詳しくはChangelogを参照してください。

12.1 削除されたもの

12.2 非推奨化

12.3 主な変更

13 Action Mailer

変更点について詳しくはChangelogを参照してください。

13.1 削除されたもの

13.2 非推奨化

13.3 主な変更

14 Active Record

変更点について詳しくはChangelogを参照してください。

14.1 削除されたもの

  • SQLite3アダプタで非推奨化されていた:retriesオプションを削除。

  • MySQL用の非推奨化された:unsigned_floatおよび:unsigned_decimalカラムメソッドを削除。

14.2 非推奨化

  • orderを指定せずに順序依存のfinderメソッド(例: #first)を使うことを非推奨化(#54608)。

  • ActiveRecord::Base.signed_id_verifier_secretを非推奨化(#54422)。今後は、Rails.application.message_verifiersを使うこと(または特定モデルに固有のsecretの場合はModel.signed_id_verifierを使うこと)。

  • 永続化されていないレコードを含む関連付けでinsert_all/upsert_allを使うことを非推奨化(#53920)。

  • update_allWITHWITH RECURSIVEDISTINCTを併用することを非推奨化(#54231)。

14.3 主な変更

  • schema.rb内のテーブルカラムのソート順がアルファベット順に変更された(#53281)。

15 Active Storage

変更点について詳しくはChangelogを参照してください。

15.1 削除されたもの

  • 非推奨化されていた:azureストレージサービスを削除。

15.2 非推奨化

15.3 主な変更

16 Active Model

変更点について詳しくはChangelogを参照してください。

16.1 削除されたもの

16.2 非推奨化

16.3 主な変更

17 Active Support

変更点について詳しくはChangelogを参照してください。

17.1 削除されたもの

  • Time#sinceにTimeオブジェクトを渡せるサポート(非推奨化)を削除。

  • 非推奨化されていたBenchmark.msメソッドを削除。現在はbenchmark gem内で定義されている。

  • TimeインスタンスとActiveSupport::TimeWithZoneを加算できる機能(非推奨化)を削除。

  • to_timeメソッドがシステムのローカル時間を保持するサポート(非推奨化)を削除。今後は常にレシーバーのタイムゾーンを保持する。

17.2 非推奨化

  • config.active_support.to_time_preserves_timezoneを非推奨化。

  • ActiveSupport::Configurableを非推奨化。

17.3 主な変更

18 Active Job

変更点について詳しくはChangelogを参照してください。

18.1 削除されたもの

  • ActiveJob::Base.enqueue_after_transaction_commit:never:always:defaultを設定するサポートを削除。

  • 非推奨化されていたRails.application.config.active_job.enqueue_after_transaction_commitを削除。

  • 非推奨化されていた組み込みSuckerPunchアダプタを削除。今後はsucker_punch gemに含まれるアダプタを使うこと。

18.2 非推奨化

  • Active Jobのカスタムシリアライザには#klass publicメソッドを含めなければならない。

18.3 主な変更

19 Action Text

変更点について詳しくはChangelogを参照してください。

19.1 削除されたもの

19.2 非推奨化

19.3 主な変更

20 Action Mailbox

変更点について詳しくはChangelogを参照してください。

20.1 削除されたもの

20.2 非推奨化

20.3 主な変更

21 Ruby on Rails Guides

+変更点について詳しくはChangelogを参照してください。

21.1 主な変更

22 クレジット

Railsを頑丈かつ安定したフレームワークにするために多大な時間を費やしてくださった多くの開発者については、Railsコントリビューターの完全なリストを参照してください。これらの方々全員に深く敬意を表明いたします。

フィードバックについて

Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。

原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨

本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。

Railsガイド運営チーム (@RailsGuidesJP)

支援・協賛

Railsガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。

  1. Star
  2. このエントリーをはてなブックマークに追加