diff --git a/gems/activemodel/6.0/_test/test.rb b/gems/activemodel/6.0/_test/test.rb index 7d0c7864..a3d3b406 100644 --- a/gems/activemodel/6.0/_test/test.rb +++ b/gems/activemodel/6.0/_test/test.rb @@ -5,8 +5,17 @@ class Person validates :name, presence: true, length: { maximum: 100 } validates :email, presence: true, if: [:foo?, -> { age >= 20 }] + validate :should_be_satisfied_special_email_rule def foo? = true + + def should_be_satisfied_special_email_rule + if Time.current >= Time.zone.local(2024, 10) + errors.add(:email, -> (_person, _options) { "must be satisfied at least 3 rules after #{Time.zone.local(2024, 10)}" }) if [/a-z/, /A-Z/, /0-9/, /[+]/].count {|rule| email.match?(rule) } > 3 + else + errors.add(:email, 'must be satisfied at least 2 rules') if [/a-z/, /A-Z/, /0-9/].count {|rule| email.match?(rule) } > 2 + end + end end person = Person.new(name: 'John Doe') diff --git a/gems/activemodel/6.0/_test/test.rbs b/gems/activemodel/6.0/_test/test.rbs index b3c14da2..7387aced 100644 --- a/gems/activemodel/6.0/_test/test.rbs +++ b/gems/activemodel/6.0/_test/test.rbs @@ -8,4 +8,5 @@ class Person attr_accessor email: String def foo?: () -> bool + def should_be_satisfied_special_email_rule: () -> void end diff --git a/gems/activemodel/6.0/activemodel-generated.rbs b/gems/activemodel/6.0/activemodel-generated.rbs index a751383e..8b8c11ed 100644 --- a/gems/activemodel/6.0/activemodel-generated.rbs +++ b/gems/activemodel/6.0/activemodel-generated.rbs @@ -1500,49 +1500,6 @@ module ActiveModel # person.errors.to_hash(true) # => {:name=>["name cannot be nil"]} def to_hash: (?bool full_messages) -> untyped - # Adds +message+ to the error messages and used validator type to +details+ on +attribute+. - # More than one error can be added to the same +attribute+. - # If no +message+ is supplied, :invalid is assumed. - # - # person.errors.add(:name) - # # => ["is invalid"] - # person.errors.add(:name, :not_implemented, message: "must be implemented") - # # => ["is invalid", "must be implemented"] - # - # person.errors.messages - # # => {:name=>["is invalid", "must be implemented"]} - # - # person.errors.details - # # => {:name=>[{error: :not_implemented}, {error: :invalid}]} - # - # If +message+ is a symbol, it will be translated using the appropriate - # scope (see +generate_message+). - # - # If +message+ is a proc, it will be called, allowing for things like - # Time.now to be used within an error. - # - # If the :strict option is set to +true+, it will raise - # ActiveModel::StrictValidationFailed instead of adding the error. - # :strict option can also be set to any other exception. - # - # person.errors.add(:name, :invalid, strict: true) - # # => ActiveModel::StrictValidationFailed: Name is invalid - # person.errors.add(:name, :invalid, strict: NameIsInvalid) - # # => NameIsInvalid: Name is invalid - # - # person.errors.messages # => {} - # - # +attribute+ should be set to :base if the error is not - # directly associated with a single attribute. - # - # person.errors.add(:base, :name_or_email_blank, - # message: "either name or email must be present") - # person.errors.messages - # # => {:base=>["either name or email must be present"]} - # person.errors.details - # # => {:base=>[{error: :name_or_email_blank}]} - def add: (untyped attribute, ?::Symbol message, ?::Hash[untyped, untyped] options) -> untyped - # Returns +true+ if an error on the attribute with the given message is # present, or +false+ otherwise. +message+ is treated the same as for +add+. # diff --git a/gems/activemodel/6.0/activemodel.rbs b/gems/activemodel/6.0/activemodel.rbs index 92e5f202..66e048d8 100644 --- a/gems/activemodel/6.0/activemodel.rbs +++ b/gems/activemodel/6.0/activemodel.rbs @@ -251,7 +251,7 @@ module ActiveModel # person = Person.new # person.valid? # => false # person.errors # => # - def errors: () -> untyped + def errors: () -> Errors # Runs all the specified validations and returns +true+ if no errors were # added otherwise +false+. @@ -498,3 +498,50 @@ module ActiveModel end end end + +module ActiveModel + class Errors + # Adds +message+ to the error messages and used validator type to +details+ on +attribute+. + # More than one error can be added to the same +attribute+. + # If no +message+ is supplied, :invalid is assumed. + # + # person.errors.add(:name) + # # => ["is invalid"] + # person.errors.add(:name, :not_implemented, message: "must be implemented") + # # => ["is invalid", "must be implemented"] + # + # person.errors.messages + # # => {:name=>["is invalid", "must be implemented"]} + # + # person.errors.details + # # => {:name=>[{error: :not_implemented}, {error: :invalid}]} + # + # If +message+ is a symbol, it will be translated using the appropriate + # scope (see +generate_message+). + # + # If +message+ is a proc, it will be called, allowing for things like + # Time.now to be used within an error. + # + # If the :strict option is set to +true+, it will raise + # ActiveModel::StrictValidationFailed instead of adding the error. + # :strict option can also be set to any other exception. + # + # person.errors.add(:name, :invalid, strict: true) + # # => ActiveModel::StrictValidationFailed: Name is invalid + # person.errors.add(:name, :invalid, strict: NameIsInvalid) + # # => NameIsInvalid: Name is invalid + # + # person.errors.messages # => {} + # + # +attribute+ should be set to :base if the error is not + # directly associated with a single attribute. + # + # person.errors.add(:base, :name_or_email_blank, + # message: "either name or email must be present") + # person.errors.messages + # # => {:base=>["either name or email must be present"]} + # person.errors.details + # # => {:base=>[{error: :name_or_email_blank}]} + def add: (untyped attribute, ?::Symbol | ::String | ^(untyped base, ::Hash[untyped, untyped]) -> (::Symbol | ::String) type, ?::Hash[untyped, untyped] options) -> void + end +end