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

Rails 7.1.0 Active Model CHANGELOG(翻訳)

概要

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

参考: Active Model の基礎 - Railsガイド

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

🔗 Active Model CHANGELOG(v7.1.0.rc1)

🔗 Revert typography change in user facing errors · rails/rails@acfa045

エラーメッセージで表示されるタイポグラフィの変更(#45463)を削除。
たとえば“can’t be blank”は再び“can't be blank”と表示されるようになった。

Rafael Mendonça França
同CHANGELOGより

🔗 Active Model CHANGELOG(v7.1.0.beta1)

🔗 Support composite identifiers in to_key by nvasilevski · Pull Request #48998 · rails/rails

to_keyで複合idをサポート。

#idが既に配列になっている場合、to_key#idArrayにラップしないようになる。

Nikita Vasilevsky
同CHANGELOGより

参考: Rails API to_key -- ActiveModel::Conversion

🔗 Allow redefining to_param delimiter using param_delimiter by nvasilevski · Pull Request #49020 · rails/rails

to_paramで使われるデリミタを設定できるActiveModel::Conversion.param_delimiterを追加。

Nikita Vasilevsky
同CHANGELOGより

参考: 週刊Railsウォッチ20230906: to_paramのデリミタをparam_delimiterで変更可能になった

🔗 Call proxy methods from alias_attribute generated methods by nvasilevski · Pull Request #48533 · rails/rails

undefine_attribute_methodsメソッドが、属性メソッドに加えてエイリアス属性メソッドも未定義化するようになった。

Nikita Vasilevsky
同CHANGELOGより

参考: Rails API undefine_attribute_methods -- ActiveModel::AttributeMethods::ClassMethods

🔗 Fix AM::Error.full_message to remove ":base" by zzak · Pull Request #48871 · rails/rails

Error.full_messageで出力されるメッセージから":base"を削除。

zzak
同CHANGELOGより

🔗 Add a load hook for ActiveModel::Model by lewispb · Pull Request #48698 · rails/rails

ActiveRecord::Baseの読み込みフックと一致する読み込みフック(名前は active_model)をActiveModel::Modelに追加し、ActiveModel::Modelクラスの一部を上書き可能にした。

Lewis Buckley
同CHANGELOGより

🔗 Improve Password Length Validation for BCrypt Compatibility by guilleiguaran · Pull Request #47708 · rails/rails

ActiveModel::SecurePasswordのパスワード長バリデーションで、バイトサイズにおけるBCrypt互換性を考慮するよう改善。

従来のパスワード長バリデーションでは文字数カウントだけを考慮していたが、これはBCryptの「72バイト」サイズ制限を正確に反映しない場合がある。この変更では、文字数とバイトサイズの両方を考慮したバリデーションを行うと同時に、文字長のバリデーションが変わらないようにした。

user = User.new(password: "a" * 73)  # 73文字
user.valid? # => false
user.errors[:password] # => ["is too long"]


user = User.new(password: "あ" * 25)  # 25文字だが75バイト
user.valid? # => false
user.errors[:password] # => ["is too long"]

ChatGPT, Guillermo Iguaran
同CHANGELOGより

参考: 週刊Railsウォッチ20230502: ActiveModel::SecurePasswordのサイズバリデーションをBCrypt仕様の上限に合わせて修正

🔗 Enhance has_secure_password to also generate a password_salt method by lazaronixon · Pull Request #47490 · rails/rails

has_secure_passwordが、パスワードダイジェストを計算用のsaltを返す#{attribute}_saltメソッドを生成するようになった。

このsaltはパスワードが変更されると必ず変更されるので、generates_token_forで一度だけ使えるパスワードリセットトークンを作成するのに利用可能。

class User < ActiveRecord::Base
  has_secure_password

  generates_token_for :password_reset, expires_in: 15.minutes do
    password_salt&.last(10)
  end
end

Lázaro Nixon
同CHANGELOGより

参考: 週刊Railsウォッチ20230328: has_secure_passwordがsalt生成メソッドを生成するよう修正

🔗 Improve typography of user facing validation messages by jdufresne · Pull Request #45463 · rails/rails

追記(2023/09/27)

このプルリクはその後参考: acfa045で取り消されました。

ユーザー向けエラーメッセージのタイポグラフィを改善。
英語の短縮形では、UnicodeのAPOSTROPHE(U+0027RIGHT SINGLE QUOTATION MARK(U+2019に置き換えた。

たとえば、従来の「can't be blank」は「can’t be blank」と表示されるようになる。

Jon Dufresne
同CHANGELOGより

参考: Rails v7.1.0 で can't be blankcan’t be blank に変わる - アジャイルSEの憂鬱

🔗 Add class name to ActiveModel::MissingAttributeError error message by p8 · Pull Request #47569 · rails/rails

ActiveModel::MissingAttributeErrorエラーメッセージにクラス名を表示するようになった。

属性を持っていないクラス名を以下のようにエラーメッセージで表示する。

user = User.first
user.pets.select(:id).first.user_id
# => ActiveModel::MissingAttributeError: missing attribute 'user_id' for Pet

Petrik de Heus
同CHANGELOGより

参考: 週刊Railsウォッチ20230328: MissingAttributeErrorでクラス名を表示するようになった

🔗 Fix as_json call on ActiveModel::Type's child classes. by nashby · Pull Request #46535 · rails/rails

ActiveModel::Type::Value#as_jsonで予想外の結果を回避するためNoMethodErrorをraiseするようになった。

Vasiliy Ermolovich
同CHANGELOGより

🔗 Avoid double cast in types that only override cast by jonathanhefner · Pull Request #46219 · rails/rails

Active Modelの組み込み型を継承し、serializeメソッドをオーバーライドしないカスタム属性について、データベース向けに属性値をシリアライズするときの最適化が行われるようになった。

たとえば、以下のようなカスタム属性があるとする。

class DowncasedString < ActiveModel::Type::String
  def cast(value)
    super&.downcase
  end
end

ActiveRecord::Type.register(:downcased_string, DowncasedString)

class User < ActiveRecord::Base
  attribute :email, :downcased_string
end

user = User.new(email: "FooBar@example.com")

データベース向けのemail属性シリアライズが、およそ2倍高速化される。よりコストの高いcastについては、さらなる改善が見込まれそう。

Jonathan Hefner
同CHANGELOGより

🔗 Support password challenge via has_secure_password by jonathanhefner · Pull Request #43688 · rails/rails

has_secure_passwordで、password_challengeアクセサとバリデーションによるパスワードチャレンジ機能をサポートするようになった。

パスワードチャレンジは、現在のユーザーが本物のパスワード所有者であることを確認するための予防策である。パスワードチャレンジは、モデルの機密性の高いフィールド(パスワード自身など)を変更するときに使うものであり、パスワード入力間違いを防ぐためのパスワード確認入力とは異なることに注意。

password_challengeが設定済みの場合、その値のダイジェストが現在永続化済みの password_digest(すなわちpassword_digest_was)と一致しているかどうかをバリデーションでチェックするようになる。

これにより、パスワードチャレンジを通常のupdate呼び出しの一部として実行可能になり、パスワードチャレンジエラーを他のバリデーションエラーと同じ方法で処理できるようになる。

たとえば、コントローラで以下のように書く代わりに、

password_params = params.require(:password).permit(
  :password_challenge,
  :password,
  :password_confirmation,
)

password_challenge = password_params.delete(:password_challenge)
@password_challenge_failed = !current_user.authenticate(password_challenge)

if !@password_challenge_failed && current_user.update(password_params)
  # ...
end

以下のように書ける。

password_params = params.require(:password).permit(
  :password_challenge,
  :password,
  :password_confirmation,
).with_defaults(password_challenge: "")

if current_user.update(password_params)
  # ...
end

ビューでは、@password_challenge_failedを独自にチェックする必要なしに、password_challengeフィールドのエラーを他のフォームフィールドと同様にレンダリングすることも、config.action_view.field_error_proc設定で表示をカスタマイズすることも可能になる。

Jonathan Hefner
同CHANGELOGより

参考: 週刊Railsウォッチ20220801: SecurePasswordの改善2つ

🔗 Support infinite ranges for LengthValidators :in/:within options by fatkodima · Pull Request #45138 · rails/rails

LengthValidator:inオプションや:withinでbeginless rangeやendless rangeをサポート。

validates_length_of :first_name, in: ..30

fatkodima
同CHANGELOGより

Rails 7.1: Active Modelバリデーションのin・withinオプションでbeginless/endless rangeをサポート(翻訳)

🔗 Add beginless range support to clusivity by bjeanes · Pull Request #45123 · rails/rails

validates_inclusion_ofvalidates_exclusion_ofでbeginless rangeやendless rangeをサポート。

validates_inclusion_of :birth_date, in: -> { (..Date.today) }

Bo Jeanes
同CHANGELOGより

Rails 7: Ruby 2.7の"beginless range"がサポートされる(翻訳)

🔗 Make validators accept lambdas without record argument by fatkodima · Pull Request #45118 · rails/rails

バリデータにrecord引数なしのlambdaを渡せるようになった。

# 変更前
validates_comparison_of :birth_date, less_than_or_equal_to: ->(_record) { Date.today }

# 変更後
validates_comparison_of :birth_date, less_than_or_equal_to: -> { Date.today }

fatkodima
同CHANGELOGより

参考: 週刊Railsウォッチ20220523: バリデーションでlambdaをrecord引数なしで渡せるように修正

🔗 Fix casting long strings to Date, Time or DateTime by fatkodima · Pull Request #45005 · rails/rails

長い文字列をDateTimeDateTimeに変換するとエラーになる問題を修正。

fatkodima
同CHANGELOGより

参考: 週刊Railsウォッチ20220516: 長い文字列をDate・Time・DateTimeにキャストしたときにエラーにならないよう修正

🔗 Use different namespace for proxy calls · rails/rails@81519de

プロキシ呼び出し用のキャッシュ名前空間を変更。

現在のモデルは、同じメソッド名に対して異なる属性本体を持つことが可能であるため、競合が発生する可能性がある。新しい名前空間:active_model_proxyを追加することで、この問題を修正する。

Chris Salzberg
同CHANGELOGより


以前の変更については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では、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。