😽

before_validation や after_validation コールバック内で原因となった context を知る方法

2023/01/18に公開

Railsの ActiveRecord や ActiveModel で、バリデーション前後に処理を行いたいとき、 before_validation および after_validation を使うことがあります。

ActiveModelオブジェクトの親子関係があるとき、親の valid?(context) を子の valid?(context) に伝搬させたいことが稀にあります。

person = Person.new
person.name = "Yuichi"
person.phone = Phone.new(country_code: '+81', number: '09000000000')
person.valid?(:create_by_user) # => person.phone.valid?(:create_by_user) に伝搬させたい

valid(context) や save(context: context) によるバリデーション中の context はどうやって知るのか?

validation_context メソッドで取得できます!

https://github.com/rails/rails/blob/9bfb8f56967e34b141d3966bd8499c25af088172/activemodel/lib/active_model/validations.rb#L48-L72

サンプルコード

# たとえばこう
class Person
  include ActiveModel::Model
  include ActiveModel::Validations::Callbacks
  include ActiveModel::Attributes

  after_validation do |person|
    person.errors.add :phone, :invalid unless phone.valid?(person.validation_context)
  end
end

まとめ

validation_context で、現在実行中のバリデーションのコンテキストを、実行中のバリデーションの中から知ることができました。
バリデーションのcontextはうまく使えば、状況に応じて実施すべきバリデーションが異なるケースに、たとえばControllerにバリデーションを書くようなことせず、モデルに整理することができるのでコードが散らからずすっきりします。うまく使っていきたいですね。

タケユー・ウェブ株式会社

Discussion