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

Rails 7.1.0 Active Support CHANGELOG(翻訳)

概要

MITライセンスに基づいて翻訳・公開いたします。

参考: Active Support コア拡張機能 - Railsガイド
参考: Active Support の Instrumentation 機能 - Railsガイド

rc2以後の更新はありません。

🔗 Active Support CHANGELOG(7.1.0.rc2)

🔗 Fix AS::MessagePack with ENV["RAILS_MAX_THREADS"] by jonathanhefner · Pull Request #49447 · rails/rails

ActiveSupport::MessagePackENV["RAILS_MAX_THREADS"]の値を文字列として扱っていたのを修正。

Jonathan Hefner
同CHANGELOGより

🔗 Active Support CHANGELOG(7.1.0.rc1)

🔗 Add a public API for broadcasting logs by Edouard-chin · Pull Request #48615 · rails/rails

ログをブロードキャストする新しいpublic APIを追加。

この機能はしばらく存在していたが、従来はprivate APIだった。
ログのブロードキャストは、ログメッセージをSTDOUTやファイルなどの別の場所にも送信可能にする。development環境では、デフォルトでSTDOUTおよびdevelopment.logファイルにログを出力するのに使われる。

基本的な使い方。

stdout_logger = Logger.new(STDOUT)
file_logger = Logger.new("development.log")
broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger, file_logger)

broadcast.info("Hello!") # この"Hello!"メッセージはSTDOUTとログの両方に出力される

ブロードキャストに送信先を追加する。

broadcast = ActiveSupport::BroadcastLogger.new
broadcast.broadcast_to(Logger.new(STDERR))

ブロードキャストから送信先を削除する。

stdout_logger = Logger.new(STDOUT)
broadcast = ActiveSupport::BroadcastLogger.new(stdout_logger)

broadcast.stop_broadcasting_to(stdout_logger)

Edouard Chin
同CHANGELOGより

この#48615によってrc1でdeveloper.logにエントリが出力されなくなる問題が発生し(#48615コメント)、以下のプルリクで修正されました。

参考: Fix the BroadcastLogger being initialized too late: by Edouard-chin · Pull Request #49417 · rails/rails

🔗 Fix Range#overlap? ignoring empty ranges by skipkayhil · Pull Request #49356 · rails/rails

Ruby 3.3より前でRange#overlap?で空のrangeが正しく処理されていなかったのを修正。

Nobuyoshi Nakada, Shouichi Kamiya, Hartley McGuire
同CHANGELOGより

# 同PRより: 修正前の動作
(2...2).overlap? 1..2 # => true
(1..2).overlap? 2...2 # => true

🔗 Use Ruby 3.3 Range#overlap? if available by yahonda · Pull Request #49317 · rails/rails

可能な場合はRuby 3.3のRange#overlap?を利用するようになった。

Yasuo Honda
同CHANGELOGより

🔗 Active Support CHANGELOG(v7.1.0.beta1)

🔗 Add drb, mutex_m and base64 that are bundled gem candidates for Ruby 3.4 by yahonda · Pull Request #48907 · rails/rails

Ruby 3.4のbundled gem候補であるdrbmutex_mbase64を追加。

Yasuo Honda
同CHANGELOGより

ruby/drb - GitHub
ruby/mutex_m - GitHub
ruby/base64 - GitHub

🔗 Lazily deserialize cache entries by jonathanhefner · Pull Request #48754 · rails/rails

キャッシュエントリの期限切れおよびバージョン不一致を、値をデシリアライズせずに検出できるようになった(キャッシュフォーマット7.1以上、またはカスタムシリアライザを使う場合)。

Jonathan Hefner
同CHANGELOGより

参考: 週刊Railsウォッチ20230823: キャッシュエントリの値をデシリアライズせずに期限切れ/不一致を検出可能になった

🔗 Make all cache stores return a boolean for #delete by p8 · Pull Request #48638 · rails/rails

キャッシュストアの#deleteがブーリアン値を返すようになった。

従来のRedisCacheStore#deleteは、エントリが存在する場合に1、存在しない場合に0を返していた。
この改修により、他のストアと同様に、エントリが存在する場合はtrue、存在しない場合はfalseを返すようになった。

以前のFileStoreはキャッシュが存在しない場合にnilを返していたが、これもfalseを返すようになった。

Petrik de Heus
同CHANGELOGより

参考: 週刊Railsウォッチ20230823: すべてのキャッシュストアが#deleteメソッドでブーリアン値を返すようになった

🔗 Support replacing cache compressor by jonathanhefner · Pull Request #48451 · rails/rails

Active Supportキャッシュストアのデフォルトのコンプレッサーを:compressorオプションで差し替え可能になった。

指定するコンプレッサーは、以下のようにdeflateinflateに応答しなければならない。

module MyCompressor
  def self.deflate(string)
    # (圧縮ロジック)
  end

  def self.inflate(compressed)
    # (解凍ロジック)
  end
end

config.cache_store = :redis_cache_store, { compressor: MyCompressor }

Jonathan Hefner
同CHANGELOGより

Active Supportキャッシュストアで:serializerオプションをサポート。

指定するシリアライザは、coderオプションと同様にdumploadに応答しなければならない。
ただし、シリアライザがシリアライズする責務があるのはキャッシュされた値だけだが、コーダーは ActiveSupport::Cache::Entry インスタンス全体をシリアライズする責務がある点が異なる。
さらに、シリアライザの出力は自動的に圧縮される場合もあるが、コーダーは独自の圧縮について責務を持つ。

コーダーの代わりにシリアライザを指定することで、パフォーマンス最適化(キャッシュフォーマット7.1で導入されたベア文字列最適化など)も有効になる。

:serializerオプションと:coderオプションは相互排他になっている。両方を同時に指定するとArgumentErrorが発生する。

Jonathan Hefner
同CHANGELOGより

参考: 週刊Railsウォッチ20230823: キャッシュストアの圧縮やシリアライザをカスタマイズ可能になった

🔗 Fix ActiveSupport::Inflector.humanize(nil) by robinjam · Pull Request #48800 · rails/rails

ActiveSupport::Inflector.humanize(nil)NoMethodError: undefined method 'end_with?' for nil:NilClassエラーが発生する問題を修正。

James Robinson
同CHANGELOGより

🔗 Don't show secrets for MessageVerifier#inspect and KeyGenerator#inspect by p8 · Pull Request #48680 · rails/rails

ActiveSupport::KeyGenerator#inspectでsecretsが露出しないようになった。

修正前:

ActiveSupport::KeyGenerator.new(secret).inspect
"#<ActiveSupport::KeyGenerator:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"

修正後:

ActiveSupport::KeyGenerator::Aes256Gcm(secret).inspect
"#<ActiveSupport::KeyGenerator:0x0000000104888038>"

Petrik de Heus
同CHANGELOGより

この修正はRails 7.0.7でリリース済みです

🔗 Add lower bound to Listen gem requirement by skipkayhil · Pull Request #48622 · rails/rails

EventedFileUpdateCheckerがlisten gemと互換性がない場合のエラーメッセージを改善

Hartley McGuire
同CHANGELOGより

この修正はRails 7.0.7でリリース済みです

🔗 Add :report behavior to ActiveSupport::Deprecation by etiennebarrie · Pull Request #48578 · rails/rails

ActiveSupport::Deprecationの振る舞いに:report指定可能になった。

config.active_support.deprecation = :reportを設定すると、非推奨警告をActiveSupport::ErrorReporterに通知するようになる。

非推奨メッセージは処理済みエラーとして重大度:warningで通知される。

production環境で発生した非推奨警告をバグトラッカーで通知するのに便利。

Étienne Barrié
同CHANGELOGより

参考: 週刊Railsウォッチ20230725: Deprecation::Behavior:reportを追加

🔗 Rename Range#overlaps? to Range#overlap? by c960657 · Pull Request #48565 · rails/rails

Range#overlaps?#overlap?にリネーム(後方互換性のためエイリアスも追加)。

Christian Schmidt
同CHANGELOGより

🔗 Fix EncryptedConfiguration not behaving like Hash by skipkayhil · Pull Request #48556 · rails/rails

EncryptedConfigurationが一部のHashメソッドで誤った値を返していたのを修正。

Hartley McGuire
同CHANGELOGより

参考: 週刊Railsウォッチ20230719: EncryptedConfigurationが一部のHashメソッドで誤った値を返していたのを修正

🔗 Don't show secrets for MessageEncryptor#inspect by p8 · Pull Request #48499 · rails/rails

MessageEncryptor#inspectでsecretsが露出しないようになった。

修正前:

ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
"#<ActiveSupport::MessageEncryptor:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"

修正後:

ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm").inspect
"#<ActiveSupport::MessageEncryptor:0x0000000104888038>"

Petrik de Heus
同CHANGELOGより

参考: Rails API ActiveSupport::MessageEncryptor

🔗 Don't show contents for EncryptedConfiguration#inspect by p8 · Pull Request #48498 · rails/rails

EncryptedConfiguration#inspectでコンテンツが露出しないようになった。

修正前:

Rails.application.credentials.inspect
"#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8 ... @config={:secret=>\"something secret\"} ... @key_file_contents=\"915e4ea054e011022398dc242\" ...>"

修正後:

Rails.application.credentials.inspect
"#<ActiveSupport::EncryptedConfiguration:0x000000010d2b38e8>"

Petrik de Heus
同CHANGELOGより

参考: Rails API ActiveSupport::EncryptedConfiguration

🔗 update ERB::Util.html_escape_once to always return an html_safe string by flavorjones · Pull Request #48265 · rails/rails

ERB::Util.html_escape_onceが常にhtml_safeな文字列を返すように更新。

従来、このメソッドの戻り値には文字列のhtml_safe?プロパティが保持されていたが、この文字列は既にエスケープ済みであるため、html_safeとしてマーキングしないとエンティティが二重にエスケープされる。

以下のビュースニペットを例とする。

<p><%= html_escape_once("this & that & the other") %></p>

この変更前は、上が二重エスケープされて以下のようにレンダリングされていた。

<p>this & that & the other</p>

変更後は以下のように正しくレンダリングされるようになった。

<p>this & that & the other</p>

修正: #48256

Mike Dalessio
同CHANGELOGより

参考: 週刊Railsウォッチ20230613: ERB::Util.html_escape_onceのエスケープ済み文字がhtml_safeでマーキングされていなかったのを修正

🔗 Deprecate SafeBuffer#clone_empty by flavorjones · Pull Request #48264 · rails/rails

SafeBuffer#clone_emptyを非推奨化。

このメソッドはRails 4.2.0以降内部で使われていない。

Mike Dalessio
同CHANGELOGより

参考: 週刊Railsウォッチ20230613: SafeBuffer#clone_emptyが非推奨化

🔗 Support :message_pack as message serializer by jonathanhefner · Pull Request #47964 · rails/rails

関連: Support :message_pack as cookies serializer by jonathanhefner · Pull Request #48103 · rails/rails
関連: Add ActiveSupport::MessagePack by jonathanhefner · Pull Request #47770 · rails/rails

MessageEncryptorMessageVerifierconfig.active_support.message_serializerにシリアライザとして:message_pack:message_pack_allow_marshalを指定できるようになった。
これらのシリアライザではmsgpack gem(1.7.0以上)が必要。

msgpack/msgpack-ruby - GitHub

MessagePackフォーマットはペイロードサイズを削減し、パフォーマンスも向上する。また、以下のようにJSONでサポートされていない一部のRuby型のシリアライズ/デシリアライズもサポートしている。

verifier = ActiveSupport::MessageVerifier.new("secret")
data = [{ a: 1 }, { b: 2 }.with_indifferent_access, 1.to_d, Time.at(0, 123)]
message = verifier.generate(data)

# サポート前(config.active_support.message_serializer = :json)
verifier.verified(message)
# => [{"a"=>1}, {"b"=>2}, "1.0", "1969-12-31T18:00:00.000-06:00"]
verifier.verified(message).map(&:class)
# => [Hash, Hash, String, String]

# サポート後(config.active_support.message_serializer = :message_pack)
verifier.verified(message)
# => [{:a=>1}, {"b"=>2}, 0.1e1, 1969-12-31 18:00:00.000123 -0600]
verifier.verified(message).map(&:class)
# => [Hash, ActiveSupport::HashWithIndifferentAccess, BigDecimal, Time]
  • :message_packシリアライザは、必要に応じてデシリアライズをActiveSupport::JSONにフォールバック可能。
  • :message_pack_allow_marshalシリアライザは、デシリアライズをActiveSupport::JSONに加えてMarshalにもフォールバック可能。

また、:marshal:json:json_allow_marshalシリアライザは、いずれも必要に応じてActiveSupport::MessagePackにフォールバック可能になった。

これらの振る舞いによって古いメッセージを引き続き読み取れるようになり、移行が容易になる。

Jonathan Hefner
同CHANGELOGより

参考: 週刊Railsウォッチ20230607: cookieシリアライザとメッセージシリアライザでも:message_pack形式をサポート

🔗 Improve cache performance for bare string values by jonathanhefner · Pull Request #48122 · rails/rails

新しいキャッシュフォーマット7.1が利用可能になった。
ビューフラグメントなどでのベア文字列(bare strings)も最適化されるようになった。

新しいキャッシュフォーマット7.1は新規アプリではデフォルトで利用される。
既存のアプリでは、config/application.rbまたはconfig/environments/*.rbで以下を設定することで有効になる。

config.load_defaults 7.1
# または
config.active_support.cache_format_version = 7.1

キャッシュフォーマット6.17.0で書き込まれたエントリも、7.1フォーマットで引き続き読み取り可能になっている。Rails 7.1へのアップデートを、アップグレード前のサーバーにローリングデプロイする場合は、アップグレード後のサーバーでキャッシュを読み取り可能にしたうえで、1回目のデプロイではキャッシュフォーマットを変更しないようにしておき、以後のデプロイで7.1キャッシュフォーマットを有効にしなければならない。

Jonathan Hefner
同CHANGELOGより

🔗 Use cache :coder option to specify :message_pack by jonathanhefner · Pull Request #48449 · rails/rails

参考: Support replacing cache compressor by jonathanhefner · Pull Request #48451 · rails/rails

Active Supportのキャッシュストアで :serializerオプションにActiveSupport::MessagePackベースの設定済みシリアライザを指定できるようになった。

config.cache_store = :redis_cache_store, { serializer: :message_pack }

この:message_packシリアライザはキャッシュエントリのサイズを削減し、パフォーマンスも向上する。ただしmsgpack gem(1.7.0以上)が必要。

msgpack/msgpack-ruby - GitHub

:message_packシリアライザは、デフォルトのシリアライザが書き込んだキャッシュエントリを読み取り可能。また、デフォルトのシリアライザも:message_packシリアライザが書き込んだエントリを読み取り可能。
これらの振る舞いによって、キャッシュ全体を無効化せずにシリアライザを移行しやすくなる。

Jonathan Hefner
同CHANGELOGより

参考: 週刊Railsウォッチ20230704: キャッシュの:message_pack:coderオプションで指定する方法に変更する

🔗 Object#deep_dup no longer duplicate named classes and modules. by casperisfine · Pull Request #48106 · rails/rails

関連: Prevent non-anonymous modules from becoming frozen by jonathanhefner · Pull Request #48178 · rails/rails

Object#deep_dupが名前付きのクラスやモジュールを複製しないようになった。

変更前:

hash = { class: Object, module: Kernel }
hash.deep_dup # => {:class=>#<Class:0x00000001063ffc80>, :module=>#<Module:0x00000001063ffa00>}

変更後:

hash = { class: Object, module: Kernel }
hash.deep_dup # => {:class=>Object, :module=>Kernel}

Jean Boussier
同CHANGELOGより

🔗 Consistently raise an ArgumentError if the ActiveSupport::Cache key is blank by joshuay03 · Pull Request #48043 · rails/rails

ActiveSupport::Cacheのキーが空(nil, "", [], {})の場合に必ずArgumentErrorを発生するようになった。

Joshua Young
同CHANGELOGより

参考: 週刊Railsウォッチ20230524: キャッシュストアでキーがnil""の場合の振る舞いを統一した

🔗 Deprecate ActiveSupport::Deprecation singleton usage by etiennebarrie · Pull Request #47354 · rails/rails

シングルトンのActiveSupport::Deprecation利用の非推奨をAPIドキュメントに記載。

ActiveSupport::Deprecationをシングルトンとして利用することは非推奨とされている(最もありがちなのはActiveSupport::Deprecation.warn)。
Gemの作者は、deprecatorActiveSupport::Deprecationオブジェクト)を独自に作成したものを使って非推奨警告を表示すること。

deprecator引数を指定せずに以下を呼び出すことも、同様に非推奨とされている。

  • Module.deprecate
  • deprecate_constant
  • DeprecatedObjectProxy
  • DeprecatedInstanceVariableProxy
  • DeprecatedConstantProxy
  • deprecation関連のテストアサーション

ActiveSupport::Deprecation.silenceメソッドや、behavior=, disallowed_behavior=, disallowed_warnings=などの設定メソッドを利用するときは、今後アプリケーションのdeprecatorsを対象とすべき。

Rails.application.deprecators.silence do
  # 非推奨警告を表示するコード
end

自分のgemにRailtieやEngineが含まれている場合は、以下のようにアプリケーションのdeprecatorsdeprecatorを追加することが推奨される。これにより、関連する非推奨設定オプションが適用されるようになる。たとえば、production環境でconfig.active_support.report_deprecationsfalseに設定すると、そのgemのdeprecatorも無効になる。

initializer "my_gem.deprecator" do |app|
  app.deprecators[:my_gem] = MyGem.deprecator
end

Étienne Barrié
同CHANGELOGより

参考: Rails API ActiveSupport::Deprecation

🔗 Implement Object#with by byroot · Pull Request #46681 · rails/rails

Active SupportにObject#withを追加。
ブロックの実行前にpublic属性を設定してブロックが終わったら元に戻す。

client.timeout # => 5
client.with(timeout: 1) do
  client.timeout # => 1
end
client.timeout # => 5

Jean Boussier
同CHANGELOGより

参考: 週刊Railsウォッチ20230328: Active SupportにObject#withが追加された

🔗 Remove deprecated support to generate incorrect RFC 4122 UUIDs · rails/rails@7b4affc

Digest::UUIDで定数が定義されていない名前空間IDを渡すと誤ったRFC 4122 UUIDが生成される非推奨のサポートを削除。

Rafael Mendonça França
同CHANGELOGより

config.active_support.use_rfc4122_namespaced_uuidsを非推奨化。

Rafael Mendonça França
同CHANGELOGより

参考: config.active_support.use_rfc4122_namespaced_uuids -- Rails アプリケーションを設定する - Railsガイド

🔗 Remove implicit conversion of objects into String by `ActiveSupport… · rails/rails@f02998d

ActiveSupport::SafeBufferでオブジェクトが暗黙でStringに変換される振る舞いを削除。

Rafael Mendonça França
同CHANGELOGより

参考: Rails API ActiveSupport::SafeBuffer

🔗 Remove deprecated `active_support/core_ext/range/include_time_with_zo… · rails/rails@f0ddb77

非推奨化されていたactive_support/core_ext/range/include_time_with_zoneファイルを削除。

Rafael Mendonça França
同CHANGELOGより

参考: Deprecate using Range#include? to check the inclusion of a value in a date time range by vishaltelangre · Pull Request #38186 · rails/rails

🔗 Remove deprecated override of ActiveSupport::TimeWithZone.name · rails/rails@34e296d

config.active_support.remove_deprecated_time_with_zone_nameを非推奨化。

Rafael Mendonça França
同CHANGELOGより

ActiveSupport::TimeWithZone.nameの非推奨化されたオーバーライドを削除。

Rafael Mendonça França
同CHANGELOGより

参考: Deprecate ActiveSupport::TimeWithZone.name by pixeltrix · Pull Request #41835 · rails/rails

🔗 Remove deprecated option to passing a format to #to_s · rails/rails@e420c33

config.active_support.disable_to_s_conversionを非推奨化。

Rafael Mendonça França
同CHANGELOGより

以下のクラスでフォーマットを#to_sに渡す非推奨のオプションを削除。

  • Array
  • Range
  • Date
  • DateTime
  • Time
  • BigDecimal
  • Float
  • Integer

Rafael Mendonça França
同CHANGELOGより

参考: Deprecate to_s(format) in favor of to_formatted_s(format) by rafaelfranca · Pull Request #43772 · rails/rails

🔗 Remove deprecated ActiveSupport::PerThreadRegistry · rails/rails@4eb6441

非推奨化されていたActiveSupport::PerThreadRegistryを削除。

Rafael Mendonça França
同CHANGELOGより

参考: Eliminate internal uses of PerThreadRegistry and deprecate it by casperisfine · Pull Request #43673 · rails/rails

🔗 Remove deprecated override of Enumerable#sum · rails/rails@3ec6297

Enumerable#sumの非推奨化されていたオーバーライドを削除。

Rafael Mendonça França
同CHANGELOGより

参考: Allow Relation#sum to take an init parameters by casperisfine · Pull Request #42190 · rails/rails

🔗 Deprecate initialize memcache store with dalli client by aledustet · Pull Request #47340 · rails/rails

ActiveSupport::Cache::MemCacheStoreDalli::Clientのインスタンスで初期化することを非推奨化。

既に初期化されたDalli::ClientインスタンスをActiveSupport::Cache::MemCacheStoreに渡す、ドキュメント化されていないオプションを非推奨化する。認識されていないオプションでこのようなクライアントが設定される可能性があり、予期しない動作を引き起こす可能性がある。今後は、ドキュメントにかかれているようにアドレスを渡すこと。

aledustet
同CHANGELOGより

petergoldstein/dalli - GitHub

🔗 Stub Time.new() in TimeHelpers#travel_to by fatkodima · Pull Request #47315 · rails/rails

TimeHelpers#travel_toTime.new()がスタブ化されるよう修正。

travel_to Time.new(2004, 11, 24) do
  # `travel_to`ブロック内の`Time.new`はスタブ化される
  assert_equal 2004, Time.new.year
end

fatkodima
同CHANGELOGより

参考: §16.1 時間に依存するコードをテストする -- Rails テスティングガイド - Railsガイド

🔗 Use throw for message error handling control flow by jonathanhefner · Pull Request #47326 · rails/rails

ActiveSupport::MessageEncryptor#decrypt_and_verifyが、暗号化方式にかかわらずActiveSupport::MessageEncryptor::InvalidMessageエラーを発生するよう修正。

従来は、MessageEncryptorでAES-256-CBCなどの非AEAD暗号が使われていた場合に、誤ってActiveSupport::MessageVerifier::InvalidSignatureが表示されることがあった。
修正後は、どの暗号化方式でも同じエラーを発生するようになった。

encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-gcm")
message = encryptor.encrypt_and_sign("message")
encryptor.decrypt_and_verify(message.next)
# => raises ActiveSupport::MessageEncryptor::InvalidMessage

encryptor = ActiveSupport::MessageEncryptor.new("x" * 32, cipher: "aes-256-cbc")
message = encryptor.encrypt_and_sign("message")
encryptor.decrypt_and_verify(message.next)
# 修正前
# => raises ActiveSupport::MessageVerifier::InvalidSignature
# 修正後:
# => raises ActiveSupport::MessageEncryptor::InvalidMessage

Jonathan Hefner
同CHANGELOGより

参考: 認証付き暗号 - Wikipedia -- AEAD

ActiveSupport::MessageVerifier#verifyで元のnil値をサポートするようになった。

従来は、MessageVerifier#verifiedMessageEncryptor#decrypt_and_verifyでは元のnil値を利用できるにもかかわらず、MessageVerifier#verifyでは利用できなかった。

encryptor = ActiveSupport::MessageEncryptor.new(secret)
message = encryptor.encrypt_and_sign(nil)

encryptor.decrypt_and_verify(message)
# => nil

verifier = ActiveSupport::MessageVerifier.new(secret)
message = verifier.generate(nil)

verifier.verified(message)
# => nil

verifier.verify(message)
# 修正前:
# => raises ActiveSupport::MessageVerifier::InvalidSignature
# 修正後:
# => nil

Jonathan Hefner
同CHANGELOGより

🔗 maintain html_safe? on sliced HTML safe strings by ggmichaelgo · Pull Request #47344 · rails/rails

sliceslice!chrメソッドでスライスしたhtml_safe文字列でもhtml_safe?が変わらないよう修正。

従来は、html_safe文字列を[]メソッドでスライスした場合にしかhtml_safe?の結果が維持されなかった。
修正後は、sliceslice!chrメソッドでスライスした場合にも、[]メソッドと同様にhtml_safe?の結果が維持されるようになった。

string = "<div>test</div>".html_safe
string.slice(0, 1).html_safe? # => true
string.slice!(0, 1).html_safe? # => true
# slice!の後もhtml_safe?の結果は変わらない
string.html_safe? # => true
string.chr.html_safe? # => true

Michael Go
同CHANGELOGより

参考: § 11.6 スライス -- Active Support コア拡張機能 - Railsガイド

🔗 Add Object#in? support for open ranges by joiggama · Pull Request #47316 · rails/rails

Object#in?にbeginless/endless rangeのサポートを追加。

assert Date.today.in?(..Date.tomorrow)
assert_not Date.today.in?(Date.tomorrow..)

Ignacio Galindo
同CHANGELOGより

参考: class Range (Ruby 3.2 リファレンスマニュアル)

🔗 Make raise_on_missing_translations raise on any missing translation by ghiculescu · Pull Request #47105 · rails/rails

config.i18n.raise_on_missing_translations = trueを設定することで、訳文が見つからない場合に常にエラーを発生するようになった。

従来はビューまたはコントローラで呼び出された場合にしかエラーにならなかった。
修正後は、認識されていないキーをI18n.tに渡すと常にエラーを発生するようになる。

この振る舞いを変更したくない場合は、i18nの例外ハンドラをカスタマイズ可能。詳しくは以下を参照。

Alex Ghiculescu
同CHANGELOGより

参考: 週刊Railsウォッチ20230214: config.i18n.raise_on_missing_translations = trueをビューやコントローラ以外でも効くように変更

🔗 ActiveSupport::CurrentAttributes: raise if a restricted attribute name is used. by ghiculescu · Pull Request #47017 · rails/rails

ActiveSupport::CurrentAttributesで利用すべきでない属性名が使われている場合にエラーを発生するようになった。

setresetなどの属性名はCurrentAttributesのpublic APIと衝突するため利用できない。

Alex Ghiculescu
同CHANGELOGより

参考: 週刊Railsウォッチ20230207: ActiveSupport::CurrentAttributesで使ってはいけない属性名をraiseするようになった

🔗 Let HWIA#transform_keys take a Hash argument like Ruby's Hash#transform_keys by amatsuda · Pull Request #46846 · rails/rails

HashWithIndifferentAccess#transform_keysがRubyのHash#transform_keysと同様にHash引数を受け取れるようになった。

Akira Matsuda
同CHANGELOGより

参考: Hash#transform_keys (Ruby 3.2 リファレンスマニュアル)
参考: 週刊Railsウォッチ20230207: HashWithIndifferentAccess#transform_keysがRubyのHash#transform_keysと同様にHash引数を受け取れるようになった

🔗 Let delegate define method with proper arity when delegating to a class by amatsuda · Pull Request #46875 · rails/rails

delegateでクラスに委譲するときに引数のアリティ(個数)を揃えてメソッドを定義するようになった。

この変更により、定義されるメソッドが高速化される(引数なしの場合3.5倍高速になる)。
ただしこのメリットを得るには、委譲を宣言する前に委譲のターゲットとなるメソッドが定義済みでなければならない。

# 定義されるメソッドは従来の3.5倍高速になる
class C
  def self.x() end
  delegate :x, to: :class
end

class C
  # これも動くが、`delegate`が`x`の定義を見つけられないため
  # 以前の振る舞いにフォールバックする
  delegate :x, to: :class
  def self.x() end
end

Akira Matsuda
同CHANGELOGより

参考: Method#arity (Ruby 3.2 リファレンスマニュアル)
参考: 週刊Railsウォッチ20230207: クラスに委譲する場合のdelegateを高速化した

🔗 Include amount changed by in assert_difference failure message · rails/rails@293349c

assert_differenceのメッセージに実際の変更を表示するようになった。

これにより、従来わかりにくかった失敗のデバッグがやりやすくなる。

変更前:

"User.count" didn't change by 32.
Expected: 1611
  Actual: 1579

変更後:

"User.count" didn't change by 32, but by 0.
Expected: 1611
  Actual: 1579

Alex Ghiculescu
同CHANGELOGより

参考: § 2.7 Rails固有のアサーション -- Rails テスティングガイド - Railsガイド

🔗 Add ability to match exception messages to assert_raises assertion · rails/rails@767ecc4

assert_raisesの例外メッセージをmatch:でフィルタできるようになった。

従来以下のように書いていたのを、

error = assert_raises(ArgumentError) do
  perform_service(param: 'exception')
end
assert_match(/incorrect param/i, error.message)

以下のように書けるようになった。

assert_raises(ArgumentError, match: /incorrect param/i) do
  perform_service(param: 'exception')
end

fatkodima
同CHANGELOGより

参考: Rails API assert_raises -- ActiveSupport::Testing::Assertions

🔗 Add Rails.env.local? by dhh · Pull Request #46786 · rails/rails

Rails.env.local?というショートハンドを追加(Rails.env.development? || Rails.env.test?と同等)。

DHH
同CHANGELOGより

Rails 7.1: Rails.env.local?で環境がdevelpment/testかどうかをチェック(翻訳)

🔗 TimeHelpers: include with_usec keyword parameter on travel & freeze too by serprex · Pull Request #46663 · rails/rails

ActiveSupport::Testing::TimeHelpersの以下のメソッドにwith_usecキーワード引数を渡せるようになった。

  • freeze_time
  • travel
  • travel_to

with_usec: trueを渡すことで、タイムトラベル先の時刻がchange(usec: 0)でマイクロ秒部分を切り捨てないようになる。

KevSlashNull, and serprex
同CHANGELOGより

参考: マイクロ秒 - Wikipedia -- "usec"と記述する慣習があります

🔗 Support using a method name to define the ActiveSupport::CurrentAttributes.resets callback by ghiculescu · Pull Request #45698 · rails/rails

ActiveSupport::CurrentAttributesresetsbefore_resetコールバックにメソッド名を渡せるようになった。

ブロック形式のAPIが引き続き推奨されているが、どちらのAPIもサポートされる。

class Current < ActiveSupport::CurrentAttributes
  resets { Time.zone = nil }
  resets :clear_time_zone
end

Alex Ghiculescu
同CHANGELOGより

参考: Rails API ActiveSupport::CurrentAttributes

🔗 Ensure pipe is closed after test run by sambostock · Pull Request #45667 · rails/rails

ActiveSupport::Testing::Isolation::Forkingがパイプを確実にクローズするよう修正。

従来はForking.run_in_isolationによってパイプの終端が2つオープンされていた。このforkプロセスは読み込みの終端をクローズし、そこに書き込んでから終了していた(おそらくその終端でファイルデスクリプタもクローズされていた)。その親プロセスが書き込みの終端をクローズし、そこから読み込んでからreturnすると、読み込みの終端が決してクローズしなくなっていた。

これによってオープンされたままのファイルデスクリプタが蓄積すると、上限に達したときにエラーになる可能性があった。

Sam Bostock
同CHANGELOGより

🔗 Fix Time#change and #advance around the end of DST by jonathanhefner · Pull Request #46251 · rails/rails

夏時間(DST: Daylight Saving Time)の終了前後の時刻におけるTime#changeTime#advanceの振る舞いを修正。

従来は、DSTの最終期間中(final stretch)にTime#changeTime#advanceで時刻を作成すると、ローカル時刻では常に非DSTのオフセット時刻を選択していた。

# US/EasternのDSTは2021-11-07 2:00:00 AMの直前に終了する
ENV["TZ"] = "US/Eastern"

time = Time.local(2021, 11, 07, 00, 59, 59) + 1
# => 2021-11-07 01:00:00 -0400
time.change(day: 07)
# => 2021-11-07 01:00:00 -0500
time.advance(seconds: 0)
# => 2021-11-07 01:00:00 -0500

time = Time.local(2021, 11, 06, 01, 00, 00)
# => 2021-11-06 01:00:00 -0400
time.change(day: 07)
# => 2021-11-07 01:00:00 -0500
time.advance(days: 1)
# => 2021-11-07 01:00:00 -0500

また、TimeZoneオブジェクトの時刻では常にDSTオフセットを選択していた。

Time.zone = "US/Eastern"

time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
# => 2021-11-07 01:00:00 -0500
time.change(day: 07)
# => 2021-11-07 01:00:00 -0400
time.advance(seconds: 0)
# => 2021-11-07 01:00:00 -0400

time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
# => 2021-11-08 01:00:00 -0500
time.change(day: 07)
# => 2021-11-07 01:00:00 -0400
time.advance(days: -1)
# => 2021-11-07 01:00:00 -0400

修正後のTime#changeTime#advanceは、可能な場合に元の時刻のオフセットに一致するオフセットを選択するようになる。

ENV["TZ"] = "US/Eastern"

time = Time.local(2021, 11, 07, 00, 59, 59) + 1
# => 2021-11-07 01:00:00 -0400
time.change(day: 07)
# => 2021-11-07 01:00:00 -0400
time.advance(seconds: 0)
# => 2021-11-07 01:00:00 -0400

time = Time.local(2021, 11, 06, 01, 00, 00)
# => 2021-11-06 01:00:00 -0400
time.change(day: 07)
# => 2021-11-07 01:00:00 -0400
time.advance(days: 1)
# => 2021-11-07 01:00:00 -0400

Time.zone = "US/Eastern"

time = Time.new(2021, 11, 07, 02, 00, 00, Time.zone) - 3600
# => 2021-11-07 01:00:00 -0500
time.change(day: 07)
# => 2021-11-07 01:00:00 -0500
time.advance(seconds: 0)
# => 2021-11-07 01:00:00 -0500

time = Time.new(2021, 11, 8, 01, 00, 00, Time.zone)
# => 2021-11-08 01:00:00 -0500
time.change(day: 07)
# => 2021-11-07 01:00:00 -0500
time.advance(days: -1)
# => 2021-11-07 01:00:00 -0500

Kevin Hall, Takayoshi Nishida, and Jonathan Hefner
同CHANGELOGより

参考: 週刊Railsウォッチ20221115: 夏時間が終わるときのTime#change#advanceを修正

🔗 MemoryStore: preserve entry ttl when incrementing by byroot · Pull Request #46305 · rails/rails

MemoryStoreのエントリが増減したときにエントリのTTLが変わらないよう修正。

これは、MemCachedStoreやRedisCacheStoreの振る舞いとの一貫性を高めるために行った。

Jean Boussier
同CHANGELOGより

参考: § 2.3 ActiveSupport::Cache::MemoryStore -- Rails のキャッシュ機構 - Railsガイド

🔗 Allow ErrorReporter to handle several error classes by spickermann · Pull Request #46299 · rails/rails

Rails.error.handleRails.error.recordを複数のエラークラスでフィルタできるようになった。

Rails.error.handle(IOError, ArgumentError) do
  1 + '1' # TypeErrorになる
end

1 + 1 # TypeErrorsはIOErrorsでもArgumentErrorでもないので、これは「処理されない」

Martin Spickermann
同CHANGELOGより

参考: 週刊Railsウォッチ20221101: ErrorReporterで複数のエラークラスを扱えるようになった

🔗 Filter reloaded classes in Class#subclasses and Class#descendants core exts by casperisfine · Pull Request #46144 · rails/rails

再読み込みされたクラスがClass#subclassesClass#descendantsで自動的に除外されるようになった。

従来は、参照解除されたがガベージコレクションされていない再読み込み可能クラスの古い実装が返される可能性があった。

変更後、そうしたクラスはDescendantTracker#subclassesDescendantTracker#descendantsなどで自動的に除外されるようになった。

Jean Boussier
同CHANGELOGより

参考: Rails API ActiveSupport::DescendantsTracker

🔗 Rails.error.report now marks errors as reported to avoid reporting them twice by casperisfine · Pull Request #46131 · rails/rails

Rails.error.reportがエラーを2回通知するのを避けるため通知済みとマーキングするようになった。

ユーザーが、エラー伝達の途中で外部のコンテキストを明示的にエラー通知したい場合があるかもしれない。この機能によって、エラーを外部の実行コンテキストから安全にキャッチしてエラーを通知することも可能になる。

Jean Boussier
同CHANGELOGより

参考: 週刊Railsウォッチ20221018: エラーの二重出力回避のためRails.error.reportを修正

🔗 Add assert_error_reported and assert_no_error_reported by casperisfine · Pull Request #46029 · rails/rails

assert_error_reportedassert_no_error_reportedを追加。

発生したエラーが処理済みかどうかのアサーションを手軽に行えるようになる。

report = assert_error_reported(IOError) do
  # ...
end
assert_equal "Oops", report.error.message
assert_equal "admin", report.context[:section]
assert_equal :warning, report.severity
assert_predicate report, :handled?

Jean Boussier
同CHANGELOGより

参考: Rails API ActiveSupport::Testing::ErrorReporterAssertions

🔗 Pass deprecator to AS::Deprecation callbacks by jonathanhefner · Pull Request #46037 · rails/rails

ActiveSupport::Deprecation::Behaviorのコールバックにdeprecatorのインスタンスを引数として渡せるようになった。これによって、deprecatorのステートに応じてコールバックの振る舞いを変更しやすくなる(例: deprecatorのdebugフラグに基づいて振る舞いを変える)。

以下のようなアリティ3のコールバックやsplat(*)引数を使うコールバックでは、deprecatorのインスタンスを第3引数として渡せる。

  • ->(message, callstack, deprecator) { ... }
  • ->(*args) { ... }
  • ->(message, *other_args) { ... }

以下のようなアリティ2または4のコールバックの振る舞いは従来と同じ。

  • ->(message, callstack) { ... }
  • ->(message, callstack, deprecation_horizon, gem_name) { ... }
  • ->(message, callstack, *deprecation_details) { ... }

Jonathan Hefner
同CHANGELOGより

参考: §メソッド定義 -- クラス/メソッドの定義 (Ruby 3.2 リファレンスマニュアル)(splat *

🔗 Fix disallowed_warnings for non-global deprecators by jonathanhefner · Pull Request #46026 · rails/rails

ActiveSupport::Deprecationのインスタンスメソッド#disallowed_warningsによる設定がそのインスタンスで効くようになった。

これによって、ActiveSupport::Deprecationの個別のインスタンスで独自の#disallowed_warningsを設定可能になり、ActiveSupport::Deprecation.disallowed_warnings(クラスメソッド)はグローバルなActiveSupport::Deprecation.warnにのみ影響するようになった。

修正前

ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
deprecator.disallowed_warnings = ["bar"]

ActiveSupport::Deprecation.warn("foo") # => ActiveSupport::DeprecationExceptionをraise
ActiveSupport::Deprecation.warn("bar") # => "DEPRECATION WARNING: bar"を出力
deprecator.warn("foo")                 # => ActiveSupport::DeprecationExceptionをraise
deprecator.warn("bar")                 # => "DEPRECATION WARNING: bar"を出力

修正後

ActiveSupport::Deprecation.disallowed_warnings = ["foo"]
deprecator = ActiveSupport::Deprecation.new("2.0", "MyCoolGem")
deprecator.disallowed_warnings = ["bar"]

ActiveSupport::Deprecation.warn("foo") # => ActiveSupport::DeprecationExceptionをraise
ActiveSupport::Deprecation.warn("bar") # => "DEPRECATION WARNING: bar"を出力
deprecator.warn("foo")                 # => "DEPRECATION WARNING: foo"を出力
deprecator.warn("bar")                 # => ActiveSupport::DeprecationExceptionをraise

なお、ActiveSupport::Deprecationの以下を含むグローバルなメソッドは非推奨化された

  • ActiveSupport::Deprecation.warn
  • ActiveSupport::Deprecation.disallowed_warnings

Jonathan Hefner
同CHANGELOGより

参考: Rails API ActiveSupport::Deprecation

🔗 Add italic and underline support to ActiveSupport::LogSubscriber#color by gmcgibbon · Pull Request #45976 · rails/rails

ActiveSupport::LogSubscriber#coloritalicunderlineをサポート。

従来は位置引数で太字のみがサポートされていた。
これによってログの色付けで太字・イタリック・下線をオプションで指定できるようになる。

info color("Hello world!", :red, bold: true, underline: true)

Gannon McGibbon
同CHANGELOGより

参考: Rails API ActiveSupport::LogSubscriber

🔗 Add String#downcase_first method by markaschneider · Pull Request #45827 · rails/rails

String#downcase_firstメソッドを追加。

これはString#upcase_firstと対になる。

Mark Schneider
同CHANGELOGより

参考: Rails API downcase_first -- String

🔗 Freeze thread_mattr_accessor default values by jonathanhefner · Pull Request #45918 · rails/rails

thread_mattr_accessorが、freezeされていないデフォルト値で.dup.freezeを呼び出すようになった。

これは、共有されているデフォルトオブジェクトを異なるスレッドが改変しようとするのを防ぐ基本的な保護を提供する。

Jonathan Hefner
同CHANGELOGより

参考: Rails API thread_mattr_accessor -- Module

🔗 Raise or Rails.error.report if ActiveSupport::Cache is given an invalid expiration time by trevorturk · Pull Request #45892 · rails/rails

ActiveSupport::Cache::Storeraise_on_invalid_cache_expiration_timeコンフィグを追加。

Rails.cachefetchwriteに値が無効なexpires_atまたはexpires_inが渡されたときにArgumentErrorを発生するかどうかを指定する。

コンフィグのオプションはtrueまたはfalseで指定する。
falseの場合はhandledとしてログ出力される。
config.load_defaults >= 7.1ではデフォルトでtrueに設定される。

Trevor Turk
同CHANGELOGより

参考: config.active_support.raise_on_invalid_cache_expiration_time -- Rails アプリケーションを設定する - Railsガイド

🔗 Pass options accessor to Cache#fetch block by casperisfine · Pull Request #45905 · rails/rails

ActiveSupport::Cache::Store#fetchでオプションのアクセサをブロックに渡せるようになった。

これにより、以下のようにキャッシュオプションをオーバーライド可能になる。

Rails.cache.fetch("3rd-party-token") do |name, options|
  token = fetch_token_from_remote
  # キャッシュのTTLがトークンのTTLと一致するように設定
  options.expires_in = token.expires_in
  token
end

Andrii Gladkyi, Jean Boussier
同CHANGELOGより

参考: 週刊Railsウォッチ20220926: ActiveSupport::Cache::Store#fetchのブロックでoptionsアクセサを渡せるようになった

🔗 Fix thread_mattr_accessor default option behavior by tdeo · Pull Request #43337 · rails/rails

thread_mattr_accessordefaultオプションがサブクラスと新しいスレッドにも適用されるよう修正。

従来のdefault値は属性ライターが定義される瞬間にのみ設定されていたため、サブクラスや他のスレッドで属性がその値で初期化されなかった。

修正: ##43312

Thierry Deo
同CHANGELOGより

参考: Rails API thread_mattr_accessor -- Module

🔗 Redis 5.0.0 compatibility by casperisfine · Pull Request #45856 · rails/rails

Redisキャッシュストアがredis-rb 5.0互換になった。

Jean Boussier
同CHANGELOGより

redis/redis-rb - GitHub

参考: この修正はRails 7.0.4でリリース済みです

🔗 Add skip_nil: support to ActiveSupport::Cache::Store#fetch_multi by pbstriker38 · Pull Request #45619 · rails/rails

ActiveSupport::Cache::Store#fetch_multiskip_nil:オプションを追加。

Daniel Alfaro
同CHANGELOGより

# 同PRより
key = SecureRandom.uuid
other_key = SecureRandom.uuid

values = @cache.fetch_multi(key, other_key, skip_nil: true) { |k| k == key ? k : nil }

参考: Rails API fetch_multi -- ActiveSupport::Cache::Store

🔗 Add quarter to date/time by swanson · Pull Request #45009 · rails/rails

date/time系クラスにquarterメソッドを追加。

Matt Swanson
同CHANGELOGより

参考: Rails API quarter -- DateAndTime::Calculations

🔗 Fix NoMethodError on custom ActiveSupport::Deprecation behavior by r7kamura · Pull Request #45521 · rails/rails

カスタマイズしたActiveSupport::Deprecationbehavior=におけるNoMethodErrorを修正。

ActiveSupport::Deprecation.behavior=には、callに応答する任意のオブジェクトを渡せることになっているが、実際の内部実装ではこのオブジェクトがarityに応答することが前提となっていたため、Procオブジェクトしか渡せなかった。

この変更では、カスタムの振る舞いにおけるarityの制約を削除した。

Ryo Nakamura
同CHANGELOGより

この修正は、Rails 7.0.4でリリース済みです

🔗 Add urlsafe option to MessageVerifier initializer by shouichi · Pull Request #45419 · rails/rails

参考: Rename :urlsafe option to :url_safe by jonathanhefner · Pull Request #45550 · rails/rails

MessageEncryptor:url_safeオプションをサポート。

MessageEncryptorのコンストラクタにも、MessageVerifierのコンストラクタと同様に:url_safeオプションを渡せるようになった。このオプションを有効にすると、メッセージのエンコーディングがURL安全になる。

Jonathan Hefner
同CHANGELOGより

参考: Rails API ActiveSupport::MessageEncryptor

🔗 Add urlsafe option to MessageVerifier initializer by shouichi · Pull Request #45419 · rails/rails

参考: Rename :urlsafe option to :url_safe by jonathanhefner · Pull Request #45550 · rails/rails

ActiveSupport::MessageVerifierイニシャライザにurl_safeオプションを追加。

ActiveSupport::MessageVerifier.newにオプションのurl_safe引数を渡せるようになった。
以下のようにurl_safe: trueを渡すことで、生成される文字列がURL安全になる。

verifier = ActiveSupport::MessageVerifier.new(url_safe: true)
message = verifier.generate(data) # => URL安全な文字列

後方互換性のため、このオプションはデフォルトでfalseに設定される。

Shouichi Kamiya
同CHANGELOGより

参考: 週刊Railsウォッチ20220627: MessageVerifierのイニシャライザにurlsafeオプションが追加

🔗 Enable connection pooling by default for MemCacheStore and RedisCacheStore by fatkodima · Pull Request #45235 · rails/rails

MemCacheStoreRedisCacheStoreのコネクションプールがデフォルトで有効になった。

コネクションプールを無効にしたい場合は、キャッシュストアのコンフィグで:poolオプションにfalseを渡す。

config.cache_store = :mem_cache_store, "cache.example.com", pool: false

fatkodima
同CHANGELOGより

参考: #45111も参照。
参考: 週刊Railsウォッチ20220613: MemCacheStoreRedisCacheStoreのコネクションプーリングがデフォルトでオンになる

🔗 Add force: support to ActiveSupport::Cache::Store#fetch_multi by fatkodima · Pull Request #45174 · rails/rails

ActiveSupport::Cache::Store#fetch_multiforce:オプションを追加。

fatkodima
同CHANGELOGより

同PRより
key = SecureRandom.uuid
other_key = SecureRandom.uuid
@cache.write(key, "bar")

values = @cache.fetch_multi(key, other_key, force: true) { |value| value * 2 }

参考: Rails API fetch_multi -- ActiveSupport::Cache::Store

🔗 Deprecate :pool_size and :pool_timeout options for configuring connection pooling in cache stores by fatkodima · Pull Request #45111 · rails/rails

キャッシュストアのコネクションプール設定で:pool_sizeオプションと:pool_timeoutオプションを非推奨化。

以下のようにコンフィグでpool: trueを指定することで、コネクションプールがデフォルト設定で有効になる。

config.cache_store = :redis_cache_store, pool: true

または以下のように:poolオプションでも指定できる。

config.cache_store = :redis_cache_store, pool: { size: 10, timeout: 2 }

fatkodima
同CHANGELOGより

参考: #45235も参照。
参考: 週刊Railsウォッチ20220613: MemCacheStoreRedisCacheStoreのコネクションプーリングがデフォルトでオンになる

🔗 Add initial value support to ActiveSupport::Cache #increment and #decrement calls by andrejbl · Pull Request #45068 · rails/rails

ActiveSupport::Cache::Storeのサブクラスで新しい値を#incrementメソッドや#decrementメソッドで設定できるようになった。

従来は、未設定のキーに#increment#decrementを実行すると失敗してnilが返された。
この修正によって、デフォルト値を前提としてキーを作成するようになった。

Andrej Blagojević, Eugene Kenny
同CHANGELOGより

# 同PRより
@cache.increment("baz")
=> 1
@cache.increment("bar", 2)
=> 2
@cache.decrement("foo", 1)
=> -1   # `MemCacheStore`の場合は0

🔗 Add skip_nil: support to RedisCacheStore by joeyparis · Pull Request #42909 · rails/rails

RedisCacheStoreskip_nil:オプションを追加。

Joey Paris
同CHANGELOGより

🔗 Fix MemoryStore#write(name, val, unless_exist: true) with expired entry by asavageiv · Pull Request #45073 · rails/rails

ActiveSupport::Cache::MemoryStore#write(name, val, unless_exist:true)が、失効したキーを正しく書き込むよう修正。

Alan Savage
同CHANGELOGより

参考: 週刊Railsウォッチ20220516: MemoryStore#write(name, val, unless_exist: true)に失効したエントリを渡したときのチェック方法を修正

🔗 Error reporting API: Add a context source attribute by casperisfine · Pull Request #44998 · rails/rails

ActiveSupport::ErrorReportersource:パラメータを渡すとforwardするようになった。

これにより、ライブラリがエラー発生元にシグナリングして、エラーレポーターが一部の発生元を手軽に無視できるようになる。

Jean Boussier
同CHANGELOGより

🔗 Fix and add protections for XSS in names. · rails/rails@649516c

ActionView::HelpersERB::UtilにXSS保護を追加。

XML仕様に基づいてタグ名や属性名に含まれる危険な文字をエスケープするERB::Util.xml_name_escapeを追加した。

Álvaro Martín Fraguas
同CHANGELOGより

参考: このセキュリティ修正は7.0.2.4でリリース済みです
参考: 週刊Railsウォッチ20220510: ActionView::HelpersERB::UtilのXSS修正と保護の追加

🔗 Respect the formatter keyword arg in ActiveSupport::Logger.new by stevenharman · Pull Request #44942 · rails/rails

ActiveSupport::Logger.new:formatterキーワード引数が反映されるよう修正。

標準ライブラリLogger::newは、:formatterキーワード引数を渡すことでロガーのフォーマッタを設定できる。
従来は、ActiveSupport::Logger::SimpleFormatterのインスタンスによって常にフォーマッタが設定されていたため、ActiveSupport::Logger.newでこの引数が無視されていた。

Steven Harman
同CHANGELOGより

参考: 週刊Railsウォッチ20220510: ActiveSupport::Logger.new:formatterキーワード引数が効くようになった

🔗 Deprecate preserving the pre-Ruby 2.4 behavior of to_time by pixeltrix · Pull Request #44728 · rails/rails

to_timeで維持されていたRuby 2.4より前の古い振る舞いを非推奨化。

Ruby 2.4以降は、to_timeがデフォルトでレシーバーのオフセットを維持するように変更された。当時のRailsは古いバージョンのRubyもサポートしていたため、移行プロセスを支援するために互換性レイヤーを追加していた。
Rails 5.0以降の新しいアプリケーションでは、Ruby 2.4以降の振る舞いがデフォルトとなり、Rails 7.0ではRuby 2.7以降のみをサポートするため、この互換性レイヤを安全に削除できる。

ノイズを最小限に抑えるため、コンフィグが false に設定されている場合にのみ非推奨警告を表示する。互換性レイヤの削除が影響を及ぼすシナリオはこれのみ。

Andrew White
同CHANGELOGより

参考: 週刊Railsウォッチ20220328: to_timeの古い振る舞いを非推奨化

🔗 Pathname.blank? only returns true for Pathname.new("") by byroot · Pull Request #44485 · rails/rails

Pathname.new("")Pathname.blank?が常にtrueを返すよう修正。

従来は、最終的にPathname#empty?が呼び出され、このパスが存在するがディレクトリまたはファイルが空の場合にtrueを返していた。

これはおそらく期待通りの振る舞いではない。

Jean Boussier
同CHANGELOGより

参考: 週刊Railsウォッチ20220308: パス名が空("")の場合にのみPathname.blank?がtrueを返すよう修正

🔗 Remove child event tracking from ActiveSupport::Subscriber by jhawthorn · Pull Request #43390 · rails/rails

Notification::Event#children#parent_of?を非推奨化。

John Hawthorn
同CHANGELOGより

🔗 Unify Message{Encryptor,Verifier} serializer config by jonathanhefner · Pull Request #47963 · rails/rails

config.load_defaults 7.1で、ActiveSupport::MessageVerifierのデフォルトのシリアライザをMarshalからActiveSupport::JSONに変更。

Marshalでシリアライズされたメッセージは引き続き読み取り可能だが、新規メッセージはActiveSupport::JSONでシリアライズされるようになる。

詳しくはRailsガイドのconfig.active_support.message_serializerを参照。

Saba Kiaei, David Buckley, and Jonathan Hefner
同CHANGELOGより

config.load_defaults 7.1で、ActiveSupport::MessageEncryptorのデフォルトのシリアライザをMarshalからActiveSupport::JSONに変更。

Marshalでシリアライズされたメッセージは引き続き読み取り可能だが、新規メッセージはActiveSupport::JSONでシリアライズされるようになる。

詳しくはRailsガイドのconfig.active_support.message_serializerを参照。

Zack Deveau, Martin Gingras, and Jonathan Hefner
同CHANGELOGより

🔗 Add TestCase#stub_const by dhh · Pull Request #44294 · rails/rails

ActiveSupport::TestCaseに、定数をブロック内でスタブ化する#stub_constを追加。

DHH
同CHANGELOGより

参考: 週刊Railsウォッチ20220208: TestCase#stub_constを追加

🔗 Use YAML.unsafe_load for encrypted configuration · rails/rails@d5b65c0

ActiveSupport::EncryptedConfigurationがPsych 4互換になるよう修正。

Stephen Sugden
同CHANGELOGより

ruby/psych - GitHub

🔗 atomic write race condition by dpep · Pull Request #44151 · rails/rails

File.atomic_writeのエラーハンドリングを改善。

Daniel Pepper
同CHANGELOGより

参考: 週刊Railsウォッチ20220124: atomic_writeの競合状態の挙動を修正

🔗 Ruby 3.1: Handle Class#subclasses existing without Class#descendants by casperisfine · Pull Request #43951 · rails/rails

ClassDescendantsTracker#descendantsがRuby 3.1互換になるよう修正。

RubyネイティブのClass#descendantsはRuby 3.1リリース前に導入を取り消された(14394#note-33)が、同じくRubyネイティブのClass#subclassesは取り消されなかったため、この機能の検出が壊れていた。

Jean Boussier
同CHANGELOGより

この修正はRails 7.0.1でリリース済みです
参考: Class#subclasses (Ruby 3.2 リファレンスマニュアル)


以前の変更については7-0-stableのCHANGELOGを参照。

関連記事

Rails 7.1に入る主要な機能まとめ(1)update_attribute!、CTEサポートほか(翻訳)

Rails 7.1に入る主要な機能まとめ(2)error_highlight対応、routes --grepほか(翻訳)

Rails 7.1に入る主要な機能まとめ(3)Docker関連ファイル導入ほか(翻訳)


CONTACT

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