Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 8.1.0.beta1のChangelog: Active Record(全項目リンク付き)

🔗 Active Record CHANGELOG

参考: Release 8.1.0.beta1 · rails/rails
参考: コミットリスト: Comparing v8.0.2.1...v8.1.0.beta1 · rails/rails

🔗 Remove deprecated :unsigned_float and :unsigned_decimal column me… · rails/rails@6edb687

MySQL向けの:unsigned_floatおよび:unsigned_decimalカラムメソッドを削除。

Rafael Mendonça França

参考: #52828

🔗 Remove deprecated :retries option for the SQLite3 adapter · rails/rails@54a1dc7

SQLite3アダプタで非推奨になっていた:retriesオプションを削除。

Rafael Mendonça França
同Changelogより

SQLite on Railsシリーズ(02)SQLiteをチューニングで強化する(翻訳)

🔗 Maintain AR connection pools in the background by matthewd · Pull Request #54175 · rails/rails

データベースの設定オプションに新しく keepalivemax_agemin_connectionsを導入し、整合性のためpoolmax_connectionsに変更。

デフォルトの振る舞いは変更されていないが、これによってコネクションプールの振る舞いをより細かく制御できるようになった、

Matthew DraperChris AtLeeRachael Wright-Munn
同Changelogより

🔗 Simplify limit validation, move to call time by skipkayhil · Pull Request #55585 · rails/rails

LIMITバリデーションの配置を、クエリ生成時からlimit!()が呼び出された時点に変更した。

Hartley McGuireShuyang
同Changelogより

🔗 Add ActiveRecord::CheckViolation error class for check constraint violations by kamipo · Pull Request #55551 · rails/rails

CHECK制約バリデーション用のActiveRecord::CheckViolationエラークラスを追加。

Ryuta Kamizono
同Changelogより

🔗 Add ActiveRecord::ExclusionViolation error class for exclusion constraint violations by kamipo · Pull Request #55545 · rails/rails

EXCLUDE制約違反をチェックするためのActiveRecord::ExclusionViolationエラークラスを追加。

PostgreSQLでEXCLUDE制約に違反した場合、汎用のActiveRecord::StatementInvalidエラーではなくActiveRecord::ExclusionViolationエラーが発生するようになった。これにより、アプリケーションコードでこれらの特定の制約違反を処理しやすくなる。

これはUNIQUE制約違反のRecordNotUniqueやFOREIGN KEY制約違反のInvalidForeignKeyなど、他の制約違反エラークラスと同じパターンに沿っている。

Ryuta Kamizono
同Changelogより

🔗 filter sensitive attributes in logs by that-jill · Pull Request #55251 · rails/rails

機密情報漏えい防止のため、filter_attributesによって除外された属性をfilter_parametersでも除外するようになった。

Jill Klang
同Changelogより

🔗 Provide a method to check current transaction's isolation level by kirs · Pull Request #55407 · rails/rails

現在のトランザクション分離レベルをチェックできるconnection.current_transaction.isolation APIを追加。

トランザクション分離レベルがisolation:パラメータやActiveRecord.with_transaction_isolation_levelで明示的に設定済みの場合はその値を返し、それ以外の場合はnilを返す。
ネストしたトランザクションは、親トランザクションの分離レベルを返す。

# トランザクションが存在しない場合はnilを返す
User.connection.current_transaction.isolation # => nil

# 明示的に設定されたトランザクション分離レベルを返す
User.transaction(isolation: :serializable) do
  User.connection.current_transaction.isolation # => :serializable
end

# トランザクション分離レベルが明示的に設定されていない場合はnilを返す
User.transaction do
  User.connection.current_transaction.isolation # => nil
end

# ネストしたトランザクションは親トランザクションの分離レベルを継承する
User.transaction(isolation: :read_committed) do
  User.transaction do
    User.connection.current_transaction.isolation # => :read_committed
  end
end

Kir Shatrov
同Changelogより

🔗 Emit a warning when pg gem < 1.6.0 is used with PostgreSQL 18+ by yahonda · Pull Request #55368 · rails/rails

PostgreSQL 18以上を使っているときにpg gemのバージョンが1.6.0未満の場合は警告を表示するようにした。

Yasuo Honda
同Changelogより

ged/ruby-pg - GitHub

🔗 [Fix #52530] Ensure all Nary children are evaluated when extracting attributes for WhereClause#merge by joshuay03 · Pull Request #54167 · rails/rails

#mergeクエリメソッドに#or#andや属性を組み合わせたときのSQLクエリ文字列が正しくならないバグを修正。

base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql

修正前:

SELECT "comments".* FROM "comments"
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
WHERE (recent = 1)
AND (
  "comments"."user_id" = 1
  AND (recent = 1)
  AND "comments"."draft" = 1
  OR "posts"."archived" = 1
)

修正後:

SELECT "comments".* FROM "comments"
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
WHERE "comments"."user_id" = 1
AND (recent = 1)
AND (
  "comments"."user_id" = 1
  AND (recent = 1)
  AND "comments"."draft" = 1
  OR "posts"."archived" = 1
)

Joshua Young
同Changelogより

🔗 Make schema dumper to account for ActiveRecord.dump_schemas when dumping in :ruby format by fatkodima · Pull Request #50020 · rails/rails

スキーマを:rubyフォーマットでダンプするときにもActiveRecord.dump_schemasを考慮するようスキーマダンパーを修正(従来は:sqlでのみ考慮されていた)。

fatkodima
同Changelogより

🔗 Add touch option to #update_columns and #update_column methods by moofkit · Pull Request #51455 · rails/rails

update_columnメソッドとupdate_columnsメソッドに:touchオプションを追加。

# :niceカラムに合わせて:updated_at/:updated_onを更新する
Will update :updated_at/:updated_on alongside :nice column.
user.update_column(:nice, true, touch: true)

# Will update :updated_at/:updated_on alongside :last_ip column
user.update_columns(last_ip: request.remote_ip, touch: true)

Dmitrii Ivliev
同Changelogより

🔗 Optimize Active Record batching further when using ranges by maximerety · Pull Request #51243 · rails/rails

use_range: trueを指定したときのActive Recordバッチ処理(in_batches)を最適化。

改修の結果、1,000万件のレコードと1万件のレコードのバッチを含むPostgreSQLテーブルでテストしたところ、1,000個のバッチのリレーション生成は4.8倍高速化し(6.8秒 vs. 1.4秒)、帯域幅の使用量は 900倍削減され(180MB vs. 0.2MB)、メモリ使用量は45倍削減された(490MB vs. 11MB)。

Maxime Rétyfatkodima
同Changelogより

参考: Rails API in_batches -- ActiveRecord::Batches

🔗 Include current character length in index and table name length error messages by joshuay03 · Pull Request #55313 · rails/rails

インデックスやテーブル名の長さバリデーションのエラーメッセージに、現在の文字数も出力するようになった。

Joshua Young
同Changelogより

🔗 Add rename_schema method for PostgreSQL by tsvallender · Pull Request #55293 · rails/rails

PostgreSQL向けのrename_schemaメソッドを追加。

T S Vallender
同Changelogより

🔗 Deprecated associations by fxn · Pull Request #55285 · rails/rails

関連付けに非推奨メッセージを表示するdeprecated: trueを実装

has_many :posts, deprecated: true

これによって、Active Recordでposts関連付けを使うと利用状況がレポートが出力されるようになる。

レポートのモードは3種類(:warn:raise:notify)あり、バックトレースもオンオフできる。デフォルトは:warnモードでバックトレースはオフになる。

詳しくはRailsガイドをチェックして欲しい。

Xavier Noria
同Changelogより

🔗 Add locale options to PostgreSQL adapter DB create by Be-ngt-oH · Pull Request #55030 · rails/rails

PostgreSQLアダプタのデータベース作成時にlocale_providerオプションと localeオプションが追加されるようになった。

Bengt-Ove Hollaender
同Changelogより

🔗 Use ntuples to populate row_count instead of count for Postgres by jcalvert · Pull Request #55200 · rails/rails

row_countの値をEnumerable#countからPostgreSQLのPG::Result#ntuplesに変更して高速化した。

Jonathan Calvert
同Changelogより

🔗 Fix include? on strict-loaded HABTM association by skipkayhil · Pull Request #55196 · rails/rails

strict loadingされたhas_and_belongs_to_many関連付けの中に、永続化されていないレコードがincludeされているかどうかのチェックが正しくなかったのを修正。

Hartley McGuire
同Changelogより

🔗 Add ability to change the transaction isolation for all pools within a block by eileencodes · Pull Request #55176 · rails/rails

1つのブロック内にあるすべてのコネクションプールについてトランザクション分離レベルを変更できる機能を追加。

この機能は、アプリケーションでデータベーストランザクションの分離レベルをリクエスト単位やアクション単位で変更する必要が生じた場合に有用。

ActiveRecord.with_transaction_isolation_level(level) {}をaroundフィルタ内やミドルウェア内で呼び出すと、そのブロック内でアクセスされるすべてのコネクションプールに対してトランザクション分離レベルが設定され、それ以外のコネクションには設定されない。

これは、明示的なトランザクションでも暗黙のトランザクションでも利用可能。

ActiveRecord.with_transaction_isolation_level(:read_committed) do
  Tag.transaction do # トランザクションを明示的にオープンする
    Tag.create!
  end
end
ActiveRecord.with_transaction_isolation_level(:read_committed) do
  Tag.create! # トランザクションを暗黙でオープンする
end

Eileen M. Uchitelle
同Changelogより

🔗 [Fix #54591] Raise an error in order dependent finder methods when the model has no order columns by joshuay03 · Pull Request #54608 · rails/rails

order値がないリレーションで、順序に依存するfinderメソッド(#first#lastなど)が呼び出され、かつそのモデルにフォールバック用の順序カラム(implicit_order_columnquery_constraintsprimary_key)が存在しない場合に、ActiveRecord::MissingRequiredOrderErrorをraiseするように変更された。

この変更によって、Rails 8.1に新しいフレームワークデフォルト値が導入される。また、この状況でエラーをraiseしない現在の振る舞いは非推奨化され、Rails 8.2で設定オプションから削除される予定。

config.active_record.raise_on_missing_required_finder_order_columns = true

Joshua Young
同Changelogより

🔗 :class_name should be invalid in polymorphic belongs_to by fxn · Pull Request #55089 · rails/rails

ポリモーフィックなbelongs_to関連付けで:class_nameオプションが無効になった。

理由: 対象となるレコードのクラス名は動的であり、typeカラムに保存されるので、このような関連付けで:class_nameを指定するのは無意味。

このオプションは、既存のポリモーフィック関連付け設定では単に削除される。
従来でもraiseするわけではなかったが、いずれにしろ設定としては無効。

Xavier Noria
同Changelogより

この改修については警告が表示されるようになっています。

参考: Deprecate :class_name for polymorphic belongs_to by fxn · Pull Request #55091 · rails/rails

🔗 Add namespaced version of the db:migrate:reset command. by JoeDupuis · Pull Request #55077 · rails/rails

マルチデータベース環境でdb:migrate:resetを名前空間付きで使えるようになった(db:migrate:reset:primary)。

Joé Dupuis
同Changelogより

🔗 Add affected_rows to ActiveRecord::Result by jenshenny · Pull Request #55060 · rails/rails

ActiveRecord::Resultaffected_rowsメソッドを追加。

Jenny Shen
同Changelogより

これにより、RETURNINGをサポートしていないDBアダプタでもinsert_allupsert_allで変更された行数を結果から取得できるようになります。

🔗 Enable passing retryable SqlLiterals to #where by skipkayhil · Pull Request #54951 · rails/rails

#whereに渡すSqlLiteralsretryable: trueでリトライ可能に変更できるようになった。

Hartley McGuire

同Changelogより

🔗 Set default for primary keys in insert_all/upsert_all by jenshenny · Pull Request #54962 · rails/rails

insert_allupsert_allの主キーにデフォルトを設定できるようになった。

従来のPostgreSQLでは、upsertで主キーがnull値の場合に新規レコードを更新および挿入できなかった。主キーとしてnil値をinsert_allupsert_allに渡すようにしたことで、アダプタで指定されたデフォルトの挿入値が暗黙で設定されるようになった。

Jenny Shen
同Changelogより

🔗 Add a load hook for ActiveRecord::DatabaseConfigurations by flavorjones · Pull Request #54959 · rails/rails

ActiveRecord::DatabaseConfigurationsを設定するための読み込みフックとしてactive_record_database_configurationsが追加された。

Mike Dalessio
同Changelogより

これは、Railtieイニシャライザからデータベース設定ハンドラを登録可能にするのが目的です。

🔗 Use TRUE and FALSE for booleans in SQLite by skipkayhil · Pull Request #54911 · rails/rails

SQLiteのクエリでブーリアンカラムに従来の10ではなくTRUEFALSEを使えるようになった。

Hartley McGuire
同Changelogより

Rails 8.1: 生SQLやArelのブーリアン型カラムをTRUEやFALSEと比較できるようになった(翻訳)

🔗 Bump minimum supported SQLite to 3.23.0 by skipkayhil · Pull Request #54907 · rails/rails

SQLiteの最小サポートバージョンが3.23.0に上がった。

Hartley McGuire
同Changelogより

🔗 Allow allocated Active Records to lookup associations by gmcgibbon · Pull Request #54892 · rails/rails

メモリ上にアロケーションされているActive Recordオブジェクトの関連付けも探索可能になった。

従来は、メモリ上にアロケーションされているActive Recordオブジェクトには関連付けキャッシュが設定されていなかったため、関連付け探索がクラッシュしていた。mochaなどのテストフレームワークではstub可能なインスタンスメソッドをチェックするためにallocateメソッドを使っていたため、これによって関連付けの探索がトリガーされて問題が生じることがあった。

Gannon McGibbon
同Changelogより

🔗 Encryption: allow turning on support_unencrypted_data at a per-attribute level by ghiculescu · Pull Request #51100 · rails/rails

Active Record暗号化でsupport_unencrypted_data: trueを属性単位で設定する機能を改善。

従来はActiveRecord::Encryption.config.support_unencrypted_data == trueが設定済みの場合しか利用できなかった。
改修後は、グローバル設定で暗号化がオフになっていても特定の属性でのみ暗号化をオプトイン可能になった。

# ActiveRecord::Encryption.config.support_unencrypted_data = true
class User < ActiveRecord::Base
  encrypts :name, support_unencrypted_data: false # 暗号化済みデータのみをサポート
  encrypts :email # 暗号化済みデータと非暗号化データを両方サポート
end
# ActiveRecord::Encryption.config.support_unencrypted_data = false
class User < ActiveRecord::Base
  encrypts :name, support_unencrypted_data: true # 暗号化済みデータと非暗号化データを両方サポート
  encrypts :email  # 暗号化済みデータのみをサポート
end

Alex Ghiculescu
同Changelogより

🔗 Model generator should be able to run without a database connection by flavorjones · Pull Request #54875 · rails/rails

データベースコネクション(カラム種別のバリデーション用)がなくてもモデルを生成できるようになった。

Mike Dalessio
同Changelogより

🔗 Refactor ActiveRecord Signed ID to use global Rails.application.message_verifiers by AliSepehri · Pull Request #54422 · rails/rails

署名済みIDベリファイアをRails.application.message_verifiersで設定可能になった。

この変更の前は、署名済みIDベリファイアを設定する主な方法は、モデルクラスごとにsigned_id_verifierを設定することだった。

Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)

このとき開発者がsigned_id_verifierを設定していなかった場合、ベリファイアはsecret_key_baseから派生したsecretと以下のオプションを用いてインスタンス化されることになる。

{ digest: "SHA256", serializer: JSON, url_safe: true }

このため、すべてのベリファイアで設定をローテーションしなければならず、作業が面倒になっていた。

今回の変更によって、config.active_record.use_legacy_signed_id_verifierという新しい設定項目が定義される。

デフォルト値の:generate_and_verifyの場合は、従来の振る舞いを維持する。
ただし:verifyに設定すると、署名済みIDベリファイアでRails.application.message_verifiersの設定(具体的にはRails.application.message_verifiers["active_record/signed_id"])が署名済みIDの生成や検証で使われるが、古い設定による検証も引き続き行われる。

この複雑さを回避するため、新しい振る舞いが適用されるのはsigned_id_verifier_secretがモデルクラスやその先祖クラスのどこにも設定されてない場合に限られている。
また、signed_id_verifier_secretは非推奨化された。現在モデルにsigned_id_verifier_secretを設定している場合は、以下のようにsigned_id_verifierに差し替えられる。

# 変更前
Post.signed_id_verifier_secret = "my secret"

# 変更後
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)

移行を容易にするため、signed_id_verifierclass_attribute(つまり継承可能)としても振る舞うが、signed_id_verifier_secretが設定されていない場合に限られる。

# 移行前
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false

# 移行後
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true

Post.signed_id_verifier_secret = "my secret" # => deprecation warning
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false

ただし、最終的には従来のモデルごとのベリファイアからRails.application.message_verifiersで管理される統一的な設定に移行することが推奨されている。
以下のようにActiveSupport::MessageVerifier#rotateを使うことで移行の負担を軽減できる。

# 移行前
# Postモデル固有の設定でPostの署名済みIDを生成・検証
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("post secret", ...)

# AFTER
# 統一設定を用いてPostの署名済みIDを生成・検証
Post.signed_id_verifier = Post.signed_id_verifier.dup
# 署名済みIDの検証時にPostの設定にフォールバックする
Post.signed_id_verifier.rotate("post secret", ...)

Ali SepehriJonathan Hefner
同Changelogより

🔗 With postgres adapter, prepend structure_load_flags instead of appending them. by AliceLoeser · Pull Request #54813 · rails/rails

PostgreSQLアダプタのstructure_loadextra_flagsの追加位置を修正。

PostgreSQLでstructure_load_flagsを指定すると、extra_flagsがデフォルトのフラグの直前ではなく直後に追加されていたため、追加フラグがPostgreSQLで効かなくなるという問題が発生していた。

Alice Loeser
同Changelogより

🔗 activerecord: Don't always append primary keys etc. to order conditions by issyl0 · Pull Request #54679 · rails/rails

implicit_order_columnオプションで主キーやCONSTRAINTをORDER BYに追加しない指定が可能になった。

implicit_order_columnオプションに渡す配列で複数のカラムを指定する場合、末尾の要素にnilを追加すると、主キーが順序条件に追加されなくなる。
これにより、生成されたクエリで使われるインデックスをより正確に制御可能になる。ただし、この機能は、指定されたカラムが完全に一意でない場合、APIが誤動作するリスクがあることに注意が必要。

Issy Long
同Changelogより

🔗 Allow per-database schema format by tsvallender · Pull Request #53666 · rails/rails

schema_formatをデータベースコンフィグで設定可能になった。

    primary:
      schema_format: ruby

これは、マルチデータベース環境のアプリでデータベースごとにスキーマのフォーマットを変える必要がある場合に便利。

T S Vallender
同Changelogより

🔗 Add support for index visibility for MySQL v8.0.0+ and MariaDB v10.6.0+ by mtaner · Pull Request #54332 · rails/rails

MySQL v8.0.0以降とMariaDB v10.6.0以降のインデックス非表示機能をサポート。

MySQL 8.0.0では、インデックスをINVISIBLEにすることで、クエリオプティマイザによる利用を無効化するオプションが追加された。これにより、インデックスのメンテナンスや更新を継続しながら、インデックスをクエリで利用不可にできる。これは、新しいINVISIBLEインデックスを追加したり既存のインデックスを削除したりする前に、インデックスをいったんINVISIBLEにしてクエリに悪影響を与えないようにする場合に有用。
詳しくはMySQL :: MySQL 8.0: Invisible Indexesを参照。

MariaDB 10.6.0では、クエリでインデックスにIGNOREを指定する形で同様の機能をサポートするようになった。詳しくはIgnored Indexes | MariaDB Documentationを参照。

Active Recordは、MySQL 8.0.0以降およびMariaDB 10.6.0以降のインデックス作成と変更でこのオプションをサポートするようになった。以下のようにカラムメソッドやインデックスメソッドに新しいインデックスオプション enabled: true/false を渡せる。

add_index :users, :email, enabled: false
enable_index :users, :email
add_column :users, :dob, :string, index: { enabled: false }

change_table :users do |t|
  t.index :name, enabled: false
  t.index :dob
  t.disable_index :dob
  t.column :username, :string, index: { enabled: false }
  t.references :account, index: { enabled: false }
end

create_table :users do |t|
  t.string :name, index: { enabled: false }
  t.string :email
  t.index :email, enabled: false
end

Merve Taner
同Changelogより

🔗 Ensure #reverse_order respects implicit_order_column by joshuay03 · Pull Request #54607 · rails/rails

ActiveRecord::Relation#reverse_orderで、primary_keyに加えてimplicit_order_columnも考慮されるよう修正。

Joshua Young
同Changelogより

🔗 Add column types to ActiveRecord::Result for SQLite3 by ankane · Pull Request #54594 · rails/rails

SQLite3の場合にActiveRecord::Resultでカラム種別も出力されるようになった。

Andrew Kane
同Changelogより

🔗 [Fix #53758] Raise ActiveRecord::ReadOnlyError when pessimistically locking with a readonly role by joshuay03 · Pull Request #54580 · rails/rails

ロールがreadonlyの状態で悲観的ロック(#lock!#with_lock#exec_queries)を試みるとActiveRecord::ReadOnlyErrorをraiseするよう修正。

Joshua Young
同Changelogより

🔗 Fix sqlite3 dbconsole not working outside Rails by skipkayhil · Pull Request #54498 · rails/rails

SQLite3AdapterdbconsoleがRailsアプリケーションの外で動かない問題を修正。

Hartley McGuire
同Changelogより

🔗 Fix migrating multiple DBs with pending migration action by gmcgibbon · Pull Request #54456 · rails/rails

マルチDBでActiveRecord::PendingMigrationアクションが動かない問題を修正。

Gannon McGibbon
同Changelogより

🔗 Enable statement-cached queries to be retryable by skipkayhil · Pull Request #54436 · rails/rails

コネクションエラー発生時に冪等な関連付けクエリを自動的にリトライするようになった。

Hartley McGuire
同Changelogより

🔗 Add allow_retry to sql.active_record by skipkayhil · Pull Request #54454 · rails/rails

sql.active_recordのinstrumentationにallow_retryを追加。

これによって、コネクションエラー時に自動リトライ可能なクエリを特定可能になる。

Hartley McGuire
同Changelogより

🔗 Support joins in update_all for Postgresql and SQlite by byroot · Pull Request #53950 · rails/rails

PostgreSQLとSQLite3でのUPDATEJOINの組み合わせを改善。

従来は、以下のようにUPDATEクエリでJOIN句を1個以上使うと、Active Recordでサブクエリが使われ、SET句内でJOINされたテーブルを参照できなくなっていた。

Comment.joins(:post).update_all("title = posts.title")

修正後は、LIMITORDERGROUP BYが使われていない限りサポートされるようになった。なお、これはMySQLではずっと前からサポートされていた。

Jean Boussier
同Changelogより

🔗 Clear AR connections in tests before forking for parallelization by flavorjones · Pull Request #54376 · rails/rails

mysql2アダプタのfork安全性の問題を回避するため、既存のコネクションをクリアするActiveSupport::Testing::Parallelization before-forkフックを導入した。

修正: #41776

Mike DalessioDonal McBreen
同Changelogより

🔗 PoolConfig no longer keeps a reference to the connection class (attempt 3) by flavorjones · Pull Request #54366 · rails/rails

PoolConfigがコネクションクラスへの参照を保持しないよう修正された。

コネクションクラスへの参照が保持されていると、developmentモードでの再読み込みで微妙な問題が発生していた。

修正: #54343

Mike Dalessio
同Changelogより

🔗 Fix active record instrumentation not thread safe: by Edouard-chin · Pull Request #54344 · rails/rails

非同期クエリでinstrumentationの通知が送信されない場合がある問題を修正。

Post.async_count
ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
  Post.count
end

一定の競合状態で非同期クエリを利用すると、まれにActive Support通知が送信されなくなることがあった。この問題は修正された。

Edouard Chin
同Changelogより

🔗 Eliminate queries loading dumped model schema on Postgres by jcoleman · Pull Request #54333 · rails/rails

PostgreSQLでダンプしたスキーマキャッシュの読み込み時にデータベースクエリが発生しないよう修正。

これにより、PostgreSQLデータベースでスキーマキャッシュファイルが構成されている場合、起動時に属性メソッドを定義するときに型マップの読み込みのためにデータベースコネクションをオープンする必要がなくなる(DB応答が不要になる)ため、回復力が向上する。

James Coleman
同Changelogより

🔗 JSON serialized attributes can return symbolized keys by matthaigh27 · Pull Request #54172 · rails/rails

ActiveRecord::Coder::JSONをオプション付きでインスタンス化可能になった。

JSONコーダーをインスタンス化するときにActiveRecord::Coder::JSONsymbolize_names: trueオプションを渡せるようになった。これにより以下が可能になった。

serialize :config, coder: ActiveRecord::Coder::JSON.new(symbolize_names: true)

matthaigh27
同Changelogより

🔗 Deprecate insert_all with unpersisted associations by Schwad · Pull Request #53920 · rails/rails

永続化されていないレコードを含む関連付けに対するinsert_allupsert_allが非推奨化された。

永続化されていないレコードを含む関連付けでこれらのメソッドを利用すると非推奨警告が表示されるようになった(永続化されていないレコードはこれらの操作後に削除される)。

Nick Schwaderer
同Changelogより

🔗 Make column name optional for index_exists? by aliismayilov · Pull Request #54298 · rails/rails

index_exists?メソッドに渡すカラム名が必須でなくなった。

これにより、remove_indexのシグネチャではカラム名から派生したインデックスを必要としないことと一貫するようになる。

Ali Ismayiliov
同Changelogより

🔗 Make payload[:name] of eager loading sql.active_record to "#{model.name} Eager Load". by zzak · Pull Request #54278 · rails/rails

eager loadingするときのsql.active_record通知イベントのペイロード名がいつも"SQL"だったのを"#{model.name} Eager Load"に変更した。

zzak
同Changelogより

🔗 Enable #exists? queries to be retryable by skipkayhil · Pull Request #54243 · rails/rails

#exists?クエリ(冪等)をコネクションエラーで自動リトライ可能にした。

Hartley McGuireclassidied
同Changelogより

🔗 Fix inconsistency between delete_all & update_all allowed methods: by Edouard-chin · Pull Request #54231 · rails/rails

update_allでサポートされていないメソッドを利用することが非推奨化された。

update_allのクエリにWITHWITH RECURSIVEDISTINCTステートメントが含まれている場合は非推奨警告メッセージを表示するようになった。これらのステートメントはこれまでサポートされておらず、SQLクエリ生成時に無視されていた。

これらは、今後リリースされるRailsではエラーになる。これにより、サポートされていないステートメントでエラーを発生するdelete_allの振る舞いと一貫するようになる。

Edouard Chin
同Changelogより

🔗 Sort table columns by name when dumping schema by jduff · Pull Request #53281 · rails/rails

schema.rb内のテーブルカラム名がアルファベット順でソートされるようになった。

従来は作成順でソートされていたため、同一のテーブルを2つのブランチで同時に変更するとコンフリクトしがちだった。

John Duff
同Changelogより

🔗 Introduce versions formatter for the schema dumper by fatkodima · Pull Request #53797 · rails/rails

スキーマダンパー用のバージョンフォーマッタを導入。

スキーマダンパーがstructure.sqlファイル内のバージョン情報をフォーマットする方法をオーバーライド可能になった。現在、バージョンは単純に降順でソートされる。
大規模なチームでは、このためリストの上位付近で多くのマージ競合が発生する可能性がある。

カスタムフォーマッタにカスタムソートロジック(例:バージョンのハッシュ値によるソート)を追加できるようになり、競合の数を大幅に削減可能になる。

fatkodima
同Changelogより

🔗 Allow to tag serialized attributes as comparable by byroot · Pull Request #53946 · rails/rails

シリアライズされた属性にcomparable: trueを指定することで==で比較可能になった。

シリアライズされた属性を扱うときに、オブジェクトのシリアライズされた表現が時間の経過とともに変化するという問題が生じやすい。これは、あるシリアライザから別のシリアライザに移行する場合(例: YAML→JSONやmsgpack)、または利用するシリアライザの出力が微妙に変更された場合に発生する。

たとえばlibyam は以前は末尾に余分な空白が含まれていたが、最近修正された。

このようなことが起こると、実際には変更されていないレコードが変更されたと報告されるレコードが多数発生し、良くてもデータベースへの書き込み回数が増加し、最悪の場合は厄介なバグとなる。

オブジェクトのデシリアライズされた表現を比較することが解決策となるが、Active Recordはデシリアライズされたオブジェクトに有効な==メソッドが常に存在することを当てにできない。そのため、この新機能はオプトイン形式となっており、指定しないと有効にならない。

serialize :config, type: Hash, coder: JSON, comparable: true

Jean Boussier
同Changelogより

🔗 Changing column nullability does not change default function by coding-chimp · Pull Request #53838 · rails/rails

MySQLで、カラムのNULL許容を変更してもデフォルト関数(例: created_at の (now()))が正しく更新されない問題を修正。

Bastian Bartmann
同Changelogより

🔗 Support loading SQLite3 extensions with config/database.yml by flavorjones · Pull Request #53827 · rails/rails

SQLite拡張をconfig/database.ymlファイルで設定可能になった。

データベース設定でextensions:オプションを使うことでSQLite拡張機能を読み込めるようになった(sqlite3>= v2.4.0が必要)。配列のメンバーには、ファイルシステムのパス、または「.to_path」に応答するモジュール名を指定可能。

development:
  adapter: sqlite3
  extensions:
    - SQLean::UUID                     # `.to_path`に応答するモジュール名
    - .sqlpkg/nalgeon/crypto/crypto.so # またはファイルシステムパス
    - <%= AppExtensions.location %>    # またはパスを返すRubyコード

Mike Dalessio
同Changelogより

🔗 AR::Middleware::ShardSelector support for granular database connection switching by flavorjones · Pull Request #53783 · rails/rails

ActiveRecord::Middleware::ShardSelectorでデータベースコネクションの切り替えをきめ細かく指定できるようになった。

config.active_record.shard_selectorに新しくclass_name:オプションが導入された。これにより、ShardSelectorミドルウェアによって切り替えられる抽象コネクションクラスをアプリケーションで指定可能になる。デフォルトのクラスは ActiveRecord::Base

たとえば、以下のコンフィグはシャードをAnimalsRecord.connected_toで切り替えるようShardSelectorミドルウェアに指示する。

config.active_record.shard_selector = { class_name: "AnimalsRecord" }

Mike Dalessio
同Changelogより

🔗 Reset AR::Relation in bulk insert and upsert methods by quadule · Pull Request #45943 · rails/rails

insert_allupsert_allの実行後にリレーションをリセットするようになった。

一括実行するinsert_allupsert_allをリレーションに対して使う場合は、reset を呼び出すようになった。これにより、update_allの振る舞いと一致するようになった。

Milo Winningham
同Changelogより

🔗 Use _N as a parallel tests databases suffixes by fatkodima · Pull Request #53790 · rails/rails

パラレルテストで使うデータベース名のサフィックスをアンダースコアの_Nに変更した。

変更前はハイフンの-Nデータベース名のがサフィックスとして使われていたが、これはデータベース名でハイフンをサポートしていない一部のRDBMSで問題を生じることがある。

fatkodima
同Changelogより

🔗 Maintain connection verification for 2 seconds after use by matthewd · Pull Request #53672 · rails/rails

データベースコネクションが直近(デフォルトでは2秒間)検証済みであるという情報を維持するようになった。これにより、1回のリクエストで再検証を繰り返すのを避けられる。

この改修によってRails 7.1のときと同様の検証頻度が再現されるようになる。つまりリクエスト期間中はコネクションが維持され、その間の検証は1回で済む。

Matthew Draper
同Changelogより

🔗 Allow to reset cache counters for multiple records by fatkodima · Pull Request #44971 · rails/rails

キャッシュカウンタを複数のレコードで一括リセットできるようになった。

Aircraft.reset_counters([1, 2, 3], :wheels_count)

この改修によって、IDをループで回して処理する独自実装と比較してずっと少ないクエリ数で済むようになる。
従来のクエリ数はO(ids.size * counters.size)だったが、改修後はO(ids.size + counters.size)のオーダーに改善された。

fatkodima
同Changelogより

🔗 Add affected_rows to sql.active_record by skipkayhil · Pull Request #53277 · rails/rails

sql.active_record通知にaffected_rowsキー(結果を返さないクエリについても影響を受けた行数を返す)が追加された。

Hartley McGuire
同Changelogより

🔗 Fix regression when calling sum with a grouped calculation: by Edouard-chin · Pull Request #53625 · rails/rails

groupの結果に対する計算でsumが動かなくなっていたのを修正。

User.group(:friendly).sumが動かなくなっていた。現在は修正済み。

Edouard Chin
同Changelogより

🔗 Add support for disabling transactions per database in ActiveRecord by mjcheetham · Pull Request #53139 · rails/rails

トランザクションテストをデータベース単位でオンオフできるようになった。

デフォルトのuse_transactional_tests設定を個別のデータベースについてテストクラスでオーバーライド可能になった。これは、テスト実行中に特定のデータベースの現在のステートに外部プロセスからアクセス可能にする必要が生じた場合に便利。

class MostlyTransactionalTest < ActiveSupport::TestCase
  self.use_transactional_tests = true
  skip_transactional_tests_for_database :shared
end

Matthew CheethamMorgan Mareve
同Changelogより

🔗 Cast query_cache value when using URL configuration by zzak · Pull Request #53491 · rails/rails

URLから取得したquery_cacheの値が文字列形式の場合に適切なデータ型にキャストするようになった("false"->falseなど)。

zzak
同Changelogより

🔗 NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX by kamipo · Pull Request #53456 · rails/rails

NULLS NOT DISTINCTが、従来のUNIQUE INDEX#48608)に加えてUNIQUE CONSTRAINTでも利用可能になった。

Ryuta Kamizono
同Changelogより

🔗 Translate no connection to the server to ConnectionNotEstablished by wata727 · Pull Request #53400 · rails/rails

従来のPG::UnableToSend: no connection to the serverエラーがリトライ可能なコネクション関連例外に置き換えられた。

Kazuma Watanabe
同Changelogより

関連記事

速報: Rails World 2025のDHHキーノートとRails 8.1beta1リリース

Rails 8.0 Changelog(全項目リンク付き)

Rails 7.2.0 Active Storage CHANGELOG(全項目リンク付き)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。