activemodel 7.2.2.1 → 8.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -45
  3. data/README.rdoc +1 -1
  4. data/lib/active_model/attribute/user_provided_default.rb +10 -0
  5. data/lib/active_model/attribute.rb +9 -1
  6. data/lib/active_model/attribute_assignment.rb +23 -2
  7. data/lib/active_model/attribute_methods.rb +5 -5
  8. data/lib/active_model/attribute_mutation_tracker.rb +5 -5
  9. data/lib/active_model/attribute_set.rb +1 -1
  10. data/lib/active_model/attributes/normalization.rb +192 -0
  11. data/lib/active_model/conversion.rb +1 -1
  12. data/lib/active_model/dirty.rb +16 -9
  13. data/lib/active_model/error.rb +3 -2
  14. data/lib/active_model/errors.rb +1 -4
  15. data/lib/active_model/gem_version.rb +3 -3
  16. data/lib/active_model/lint.rb +7 -3
  17. data/lib/active_model/model.rb +2 -2
  18. data/lib/active_model/naming.rb +0 -1
  19. data/lib/active_model/nested_error.rb +1 -3
  20. data/lib/active_model/railtie.rb +8 -4
  21. data/lib/active_model/secure_password.rb +61 -4
  22. data/lib/active_model/serialization.rb +21 -21
  23. data/lib/active_model/translation.rb +22 -5
  24. data/lib/active_model/type/big_integer.rb +21 -0
  25. data/lib/active_model/type/boolean.rb +1 -0
  26. data/lib/active_model/type/date.rb +1 -0
  27. data/lib/active_model/type/date_time.rb +8 -0
  28. data/lib/active_model/type/decimal.rb +1 -0
  29. data/lib/active_model/type/float.rb +9 -8
  30. data/lib/active_model/type/helpers/immutable.rb +13 -0
  31. data/lib/active_model/type/helpers/time_value.rb +20 -44
  32. data/lib/active_model/type/helpers.rb +1 -0
  33. data/lib/active_model/type/immutable_string.rb +2 -0
  34. data/lib/active_model/type/integer.rb +31 -19
  35. data/lib/active_model/type/string.rb +4 -0
  36. data/lib/active_model/type/value.rb +4 -4
  37. data/lib/active_model/validations/acceptance.rb +1 -1
  38. data/lib/active_model/validations/callbacks.rb +10 -0
  39. data/lib/active_model/validations/validates.rb +7 -2
  40. data/lib/active_model/validations.rb +57 -32
  41. data/lib/active_model.rb +6 -0
  42. metadata +11 -12
@@ -78,7 +78,12 @@ module ActiveModel
78
78
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
79
79
  # <tt>on: :custom_validation_context</tt> or
80
80
  # <tt>on: [:create, :custom_validation_context]</tt>)
81
- # * <tt>:if</tt> - Specifies a method, proc, or string to call to determine
81
+ # * <tt>:except_on</tt> - Specifies the contexts where this validation is not active.
82
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
83
+ # or an array of symbols. (e.g. <tt>except: :create</tt> or
84
+ # <tt>except_on: :custom_validation_context</tt> or
85
+ # <tt>except_on: [:create, :custom_validation_context]</tt>)
86
+ # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
82
87
  # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
83
88
  # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
84
89
  # proc or string should return or evaluate to a +true+ or +false+ value.
@@ -155,7 +160,7 @@ module ActiveModel
155
160
  # When creating custom validators, it might be useful to be able to specify
156
161
  # additional default keys. This can be done by overwriting this method.
157
162
  def _validates_default_keys
158
- [:if, :unless, :on, :allow_blank, :allow_nil, :strict]
163
+ [:if, :unless, :on, :allow_blank, :allow_nil, :strict, :except_on]
159
164
  end
160
165
 
161
166
  def _parse_validates_options(options)
@@ -45,27 +45,6 @@ module ActiveModel
45
45
  extend HelperMethods
46
46
  include HelperMethods
47
47
 
48
- ##
49
- # :method: validation_context
50
- # Returns the context when running validations.
51
- #
52
- # This is useful when running validations except a certain context (opposite to the +on+ option).
53
- #
54
- # class Person
55
- # include ActiveModel::Validations
56
- #
57
- # attr_accessor :name
58
- # validates :name, presence: true, if: -> { validation_context != :custom }
59
- # end
60
- #
61
- # person = Person.new
62
- # person.valid? #=> false
63
- # person.valid?(:new) #=> false
64
- # person.valid?(:custom) #=> true
65
-
66
- ##
67
- attr_accessor :validation_context
68
- private :validation_context=
69
48
  define_callbacks :validate, scope: :name
70
49
 
71
50
  class_attribute :_validators, instance_writer: false, default: Hash.new { |h, k| h[k] = [] }
@@ -84,12 +63,18 @@ module ActiveModel
84
63
  # end
85
64
  # end
86
65
  #
87
- # Options:
66
+ # ==== Options
67
+ #
88
68
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
89
69
  # Runs in all validation contexts by default +nil+. You can pass a symbol
90
70
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
91
71
  # <tt>on: :custom_validation_context</tt> or
92
72
  # <tt>on: [:create, :custom_validation_context]</tt>)
73
+ # * <tt>:except_on</tt> - Specifies the contexts where this validation is not active.
74
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
75
+ # or an array of symbols. (e.g. <tt>except: :create</tt> or
76
+ # <tt>except_on: :custom_validation_context</tt> or
77
+ # <tt>except_on: [:create, :custom_validation_context]</tt>)
93
78
  # * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.
94
79
  # * <tt>:allow_blank</tt> - Skip validation if attribute is blank.
95
80
  # * <tt>:if</tt> - Specifies a method, proc, or string to call to determine
@@ -105,7 +90,7 @@ module ActiveModel
105
90
  validates_with BlockValidator, _merge_attributes(attr_names), &block
106
91
  end
107
92
 
108
- VALID_OPTIONS_FOR_VALIDATE = [:on, :if, :unless, :prepend].freeze # :nodoc:
93
+ VALID_OPTIONS_FOR_VALIDATE = [:on, :if, :unless, :prepend, :except_on].freeze # :nodoc:
109
94
 
110
95
  # Adds a validation method or block to the class. This is useful when
111
96
  # overriding the +validate+ instance method becomes too unwieldy and
@@ -150,20 +135,26 @@ module ActiveModel
150
135
  # Note that the return value of validation methods is not relevant.
151
136
  # It's not possible to halt the validate callback chain.
152
137
  #
153
- # Options:
138
+ # ==== Options
139
+ #
154
140
  # * <tt>:on</tt> - Specifies the contexts where this validation is active.
155
141
  # Runs in all validation contexts by default +nil+. You can pass a symbol
156
142
  # or an array of symbols. (e.g. <tt>on: :create</tt> or
157
143
  # <tt>on: :custom_validation_context</tt> or
158
144
  # <tt>on: [:create, :custom_validation_context]</tt>)
159
- # * <tt>:if</tt> - Specifies a method, proc, or string to call to determine
145
+ # * <tt>:except_on</tt> - Specifies the contexts where this validation is not active.
146
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
147
+ # or an array of symbols. (e.g. <tt>except: :create</tt> or
148
+ # <tt>except_on: :custom_validation_context</tt> or
149
+ # <tt>except_on: [:create, :custom_validation_context]</tt>)
150
+ # * <tt>:if</tt> - Specifies a method or proc to call to determine
160
151
  # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
161
- # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
162
- # proc or string should return or evaluate to a +true+ or +false+ value.
163
- # * <tt>:unless</tt> - Specifies a method, proc, or string to call to
152
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method or
153
+ # proc should return or evaluate to a +true+ or +false+ value.
154
+ # * <tt>:unless</tt> - Specifies a method or proc to call to
164
155
  # determine if the validation should not occur (e.g. <tt>unless: :skip_validation</tt>,
165
156
  # or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
166
- # method, proc, or string should return or evaluate to a +true+ or +false+
157
+ # method or proc should return or evaluate to a +true+ or +false+
167
158
  # value.
168
159
  #
169
160
  # NOTE: Calling +validate+ multiple times on the same method will overwrite previous definitions.
@@ -183,6 +174,15 @@ module ActiveModel
183
174
  options = options.merge(if: [predicate_for_validation_context(options[:on]), *options[:if]])
184
175
  end
185
176
 
177
+ if options.key?(:except_on)
178
+ options = options.dup
179
+ options[:except_on] = Array(options[:except_on])
180
+ options[:unless] = [
181
+ ->(o) { options[:except_on].intersect?(Array(o.validation_context)) },
182
+ *options[:unless]
183
+ ]
184
+ end
185
+
186
186
  set_callback(:validate, *args, options, &block)
187
187
  end
188
188
 
@@ -361,15 +361,23 @@ module ActiveModel
361
361
  # person.valid? # => true
362
362
  # person.valid?(:new) # => false
363
363
  def valid?(context = nil)
364
- current_context, self.validation_context = validation_context, context
364
+ current_context = validation_context
365
+ context_for_validation.context = context
365
366
  errors.clear
366
367
  run_validations!
367
368
  ensure
368
- self.validation_context = current_context
369
+ context_for_validation.context = current_context
369
370
  end
370
371
 
371
372
  alias_method :validate, :valid?
372
373
 
374
+ def freeze
375
+ errors
376
+ context_for_validation
377
+
378
+ super
379
+ end
380
+
373
381
  # Performs the opposite of <tt>valid?</tt>. Returns +true+ if errors were
374
382
  # added, +false+ otherwise.
375
383
  #
@@ -430,11 +438,24 @@ module ActiveModel
430
438
  # end
431
439
  alias :read_attribute_for_validation :send
432
440
 
441
+ # Returns the context when running validations.
442
+ def validation_context
443
+ context_for_validation.context
444
+ end
445
+
433
446
  private
447
+ def validation_context=(context)
448
+ context_for_validation.context = context
449
+ end
450
+
451
+ def context_for_validation
452
+ @context_for_validation ||= ValidationContext.new
453
+ end
454
+
434
455
  def init_internals
435
456
  super
436
457
  @errors = nil
437
- @validation_context = nil
458
+ @context_for_validation = nil
438
459
  end
439
460
 
440
461
  def run_validations!
@@ -466,6 +487,10 @@ module ActiveModel
466
487
  super(I18n.t(:"#{@model.class.i18n_scope}.errors.messages.model_invalid", errors: errors, default: :"errors.messages.model_invalid"))
467
488
  end
468
489
  end
490
+
491
+ class ValidationContext # :nodoc:
492
+ attr_accessor :context
493
+ end
469
494
  end
470
495
 
471
496
  Dir[File.expand_path("validations/*.rb", __dir__)].each { |file| require file }
data/lib/active_model.rb CHANGED
@@ -56,6 +56,12 @@ module ActiveModel
56
56
  autoload :Validations
57
57
  autoload :Validator
58
58
 
59
+ module Attributes
60
+ extend ActiveSupport::Autoload
61
+
62
+ autoload :Normalization
63
+ end
64
+
59
65
  eager_autoload do
60
66
  autoload :Errors
61
67
  autoload :Error
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.2.1
4
+ version: 8.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - '='
18
17
  - !ruby/object:Gem::Version
19
- version: 7.2.2.1
18
+ version: 8.1.2
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - '='
25
24
  - !ruby/object:Gem::Version
26
- version: 7.2.2.1
25
+ version: 8.1.2
27
26
  description: A toolkit for building modeling frameworks like Active Record. Rich support
28
27
  for attributes, callbacks, validations, serialization, internationalization, and
29
28
  testing.
@@ -48,6 +47,7 @@ files:
48
47
  - lib/active_model/attribute_set/builder.rb
49
48
  - lib/active_model/attribute_set/yaml_encoder.rb
50
49
  - lib/active_model/attributes.rb
50
+ - lib/active_model/attributes/normalization.rb
51
51
  - lib/active_model/callbacks.rb
52
52
  - lib/active_model/conversion.rb
53
53
  - lib/active_model/deprecator.rb
@@ -76,6 +76,7 @@ files:
76
76
  - lib/active_model/type/float.rb
77
77
  - lib/active_model/type/helpers.rb
78
78
  - lib/active_model/type/helpers/accepts_multiparameter_time.rb
79
+ - lib/active_model/type/helpers/immutable.rb
79
80
  - lib/active_model/type/helpers/mutable.rb
80
81
  - lib/active_model/type/helpers/numeric.rb
81
82
  - lib/active_model/type/helpers/time_value.rb
@@ -112,12 +113,11 @@ licenses:
112
113
  - MIT
113
114
  metadata:
114
115
  bug_tracker_uri: https://github.com/rails/rails/issues
115
- changelog_uri: https://github.com/rails/rails/blob/v7.2.2.1/activemodel/CHANGELOG.md
116
- documentation_uri: https://api.rubyonrails.org/v7.2.2.1/
116
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.2/activemodel/CHANGELOG.md
117
+ documentation_uri: https://api.rubyonrails.org/v8.1.2/
117
118
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
118
- source_code_uri: https://github.com/rails/rails/tree/v7.2.2.1/activemodel
119
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.2/activemodel
119
120
  rubygems_mfa_required: 'true'
120
- post_install_message:
121
121
  rdoc_options: []
122
122
  require_paths:
123
123
  - lib
@@ -125,15 +125,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
125
  requirements:
126
126
  - - ">="
127
127
  - !ruby/object:Gem::Version
128
- version: 3.1.0
128
+ version: 3.2.0
129
129
  required_rubygems_version: !ruby/object:Gem::Requirement
130
130
  requirements:
131
131
  - - ">="
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  requirements: []
135
- rubygems_version: 3.5.22
136
- signing_key:
135
+ rubygems_version: 4.0.3
137
136
  specification_version: 4
138
137
  summary: A toolkit for building modeling frameworks (part of Rails).
139
138
  test_files: []