activemodel 6.0.0

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +172 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +266 -0
  5. data/lib/active_model.rb +77 -0
  6. data/lib/active_model/attribute.rb +247 -0
  7. data/lib/active_model/attribute/user_provided_default.rb +51 -0
  8. data/lib/active_model/attribute_assignment.rb +57 -0
  9. data/lib/active_model/attribute_methods.rb +517 -0
  10. data/lib/active_model/attribute_mutation_tracker.rb +178 -0
  11. data/lib/active_model/attribute_set.rb +106 -0
  12. data/lib/active_model/attribute_set/builder.rb +124 -0
  13. data/lib/active_model/attribute_set/yaml_encoder.rb +40 -0
  14. data/lib/active_model/attributes.rb +138 -0
  15. data/lib/active_model/callbacks.rb +156 -0
  16. data/lib/active_model/conversion.rb +111 -0
  17. data/lib/active_model/dirty.rb +280 -0
  18. data/lib/active_model/errors.rb +601 -0
  19. data/lib/active_model/forbidden_attributes_protection.rb +31 -0
  20. data/lib/active_model/gem_version.rb +17 -0
  21. data/lib/active_model/lint.rb +118 -0
  22. data/lib/active_model/locale/en.yml +36 -0
  23. data/lib/active_model/model.rb +99 -0
  24. data/lib/active_model/naming.rb +334 -0
  25. data/lib/active_model/railtie.rb +20 -0
  26. data/lib/active_model/secure_password.rb +128 -0
  27. data/lib/active_model/serialization.rb +192 -0
  28. data/lib/active_model/serializers/json.rb +147 -0
  29. data/lib/active_model/translation.rb +70 -0
  30. data/lib/active_model/type.rb +53 -0
  31. data/lib/active_model/type/big_integer.rb +15 -0
  32. data/lib/active_model/type/binary.rb +52 -0
  33. data/lib/active_model/type/boolean.rb +47 -0
  34. data/lib/active_model/type/date.rb +53 -0
  35. data/lib/active_model/type/date_time.rb +47 -0
  36. data/lib/active_model/type/decimal.rb +70 -0
  37. data/lib/active_model/type/float.rb +34 -0
  38. data/lib/active_model/type/helpers.rb +7 -0
  39. data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +45 -0
  40. data/lib/active_model/type/helpers/mutable.rb +20 -0
  41. data/lib/active_model/type/helpers/numeric.rb +44 -0
  42. data/lib/active_model/type/helpers/time_value.rb +81 -0
  43. data/lib/active_model/type/helpers/timezone.rb +19 -0
  44. data/lib/active_model/type/immutable_string.rb +32 -0
  45. data/lib/active_model/type/integer.rb +58 -0
  46. data/lib/active_model/type/registry.rb +62 -0
  47. data/lib/active_model/type/string.rb +26 -0
  48. data/lib/active_model/type/time.rb +47 -0
  49. data/lib/active_model/type/value.rb +126 -0
  50. data/lib/active_model/validations.rb +437 -0
  51. data/lib/active_model/validations/absence.rb +33 -0
  52. data/lib/active_model/validations/acceptance.rb +102 -0
  53. data/lib/active_model/validations/callbacks.rb +122 -0
  54. data/lib/active_model/validations/clusivity.rb +54 -0
  55. data/lib/active_model/validations/confirmation.rb +80 -0
  56. data/lib/active_model/validations/exclusion.rb +49 -0
  57. data/lib/active_model/validations/format.rb +114 -0
  58. data/lib/active_model/validations/helper_methods.rb +15 -0
  59. data/lib/active_model/validations/inclusion.rb +47 -0
  60. data/lib/active_model/validations/length.rb +129 -0
  61. data/lib/active_model/validations/numericality.rb +189 -0
  62. data/lib/active_model/validations/presence.rb +39 -0
  63. data/lib/active_model/validations/validates.rb +174 -0
  64. data/lib/active_model/validations/with.rb +147 -0
  65. data/lib/active_model/validator.rb +183 -0
  66. data/lib/active_model/version.rb +10 -0
  67. metadata +125 -0
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/extract_options"
4
+
5
+ module ActiveModel
6
+ module Validations
7
+ class WithValidator < EachValidator # :nodoc:
8
+ def validate_each(record, attr, val)
9
+ method_name = options[:with]
10
+
11
+ if record.method(method_name).arity == 0
12
+ record.send method_name
13
+ else
14
+ record.send method_name, attr
15
+ end
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+ # Passes the record off to the class or classes specified and allows them
21
+ # to add errors based on more complex conditions.
22
+ #
23
+ # class Person
24
+ # include ActiveModel::Validations
25
+ # validates_with MyValidator
26
+ # end
27
+ #
28
+ # class MyValidator < ActiveModel::Validator
29
+ # def validate(record)
30
+ # if some_complex_logic
31
+ # record.errors.add :base, 'This record is invalid'
32
+ # end
33
+ # end
34
+ #
35
+ # private
36
+ # def some_complex_logic
37
+ # # ...
38
+ # end
39
+ # end
40
+ #
41
+ # You may also pass it multiple classes, like so:
42
+ #
43
+ # class Person
44
+ # include ActiveModel::Validations
45
+ # validates_with MyValidator, MyOtherValidator, on: :create
46
+ # end
47
+ #
48
+ # Configuration options:
49
+ # * <tt>:on</tt> - Specifies the contexts where this validation is active.
50
+ # Runs in all validation contexts by default +nil+. You can pass a symbol
51
+ # or an array of symbols. (e.g. <tt>on: :create</tt> or
52
+ # <tt>on: :custom_validation_context</tt> or
53
+ # <tt>on: [:create, :custom_validation_context]</tt>)
54
+ # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
55
+ # if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
56
+ # or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>).
57
+ # The method, proc or string should return or evaluate to a +true+ or
58
+ # +false+ value.
59
+ # * <tt>:unless</tt> - Specifies a method, proc or string to call to
60
+ # determine if the validation should not occur
61
+ # (e.g. <tt>unless: :skip_validation</tt>, or
62
+ # <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>).
63
+ # The method, proc or string should return or evaluate to a +true+ or
64
+ # +false+ value.
65
+ # * <tt>:strict</tt> - Specifies whether validation should be strict.
66
+ # See <tt>ActiveModel::Validations#validates!</tt> for more information.
67
+ #
68
+ # If you pass any additional configuration options, they will be passed
69
+ # to the class and available as +options+:
70
+ #
71
+ # class Person
72
+ # include ActiveModel::Validations
73
+ # validates_with MyValidator, my_custom_key: 'my custom value'
74
+ # end
75
+ #
76
+ # class MyValidator < ActiveModel::Validator
77
+ # def validate(record)
78
+ # options[:my_custom_key] # => "my custom value"
79
+ # end
80
+ # end
81
+ def validates_with(*args, &block)
82
+ options = args.extract_options!
83
+ options[:class] = self
84
+
85
+ args.each do |klass|
86
+ validator = klass.new(options, &block)
87
+
88
+ if validator.respond_to?(:attributes) && !validator.attributes.empty?
89
+ validator.attributes.each do |attribute|
90
+ _validators[attribute.to_sym] << validator
91
+ end
92
+ else
93
+ _validators[nil] << validator
94
+ end
95
+
96
+ validate(validator, options)
97
+ end
98
+ end
99
+ end
100
+
101
+ # Passes the record off to the class or classes specified and allows them
102
+ # to add errors based on more complex conditions.
103
+ #
104
+ # class Person
105
+ # include ActiveModel::Validations
106
+ #
107
+ # validate :instance_validations
108
+ #
109
+ # def instance_validations
110
+ # validates_with MyValidator
111
+ # end
112
+ # end
113
+ #
114
+ # Please consult the class method documentation for more information on
115
+ # creating your own validator.
116
+ #
117
+ # You may also pass it multiple classes, like so:
118
+ #
119
+ # class Person
120
+ # include ActiveModel::Validations
121
+ #
122
+ # validate :instance_validations, on: :create
123
+ #
124
+ # def instance_validations
125
+ # validates_with MyValidator, MyOtherValidator
126
+ # end
127
+ # end
128
+ #
129
+ # Standard configuration options (<tt>:on</tt>, <tt>:if</tt> and
130
+ # <tt>:unless</tt>), which are available on the class version of
131
+ # +validates_with+, should instead be placed on the +validates+ method
132
+ # as these are applied and tested in the callback.
133
+ #
134
+ # If you pass any additional configuration options, they will be passed
135
+ # to the class and available as +options+, please refer to the
136
+ # class version of this method for more information.
137
+ def validates_with(*args, &block)
138
+ options = args.extract_options!
139
+ options[:class] = self.class
140
+
141
+ args.each do |klass|
142
+ validator = klass.new(options, &block)
143
+ validator.validate(self)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/anonymous"
4
+
5
+ module ActiveModel
6
+ # == Active \Model \Validator
7
+ #
8
+ # A simple base class that can be used along with
9
+ # ActiveModel::Validations::ClassMethods.validates_with
10
+ #
11
+ # class Person
12
+ # include ActiveModel::Validations
13
+ # validates_with MyValidator
14
+ # end
15
+ #
16
+ # class MyValidator < ActiveModel::Validator
17
+ # def validate(record)
18
+ # if some_complex_logic
19
+ # record.errors.add(:base, "This record is invalid")
20
+ # end
21
+ # end
22
+ #
23
+ # private
24
+ # def some_complex_logic
25
+ # # ...
26
+ # end
27
+ # end
28
+ #
29
+ # Any class that inherits from ActiveModel::Validator must implement a method
30
+ # called +validate+ which accepts a +record+.
31
+ #
32
+ # class Person
33
+ # include ActiveModel::Validations
34
+ # validates_with MyValidator
35
+ # end
36
+ #
37
+ # class MyValidator < ActiveModel::Validator
38
+ # def validate(record)
39
+ # record # => The person instance being validated
40
+ # options # => Any non-standard options passed to validates_with
41
+ # end
42
+ # end
43
+ #
44
+ # To cause a validation error, you must add to the +record+'s errors directly
45
+ # from within the validators message.
46
+ #
47
+ # class MyValidator < ActiveModel::Validator
48
+ # def validate(record)
49
+ # record.errors.add :base, "This is some custom error message"
50
+ # record.errors.add :first_name, "This is some complex validation"
51
+ # # etc...
52
+ # end
53
+ # end
54
+ #
55
+ # To add behavior to the initialize method, use the following signature:
56
+ #
57
+ # class MyValidator < ActiveModel::Validator
58
+ # def initialize(options)
59
+ # super
60
+ # @my_custom_field = options[:field_name] || :first_name
61
+ # end
62
+ # end
63
+ #
64
+ # Note that the validator is initialized only once for the whole application
65
+ # life cycle, and not on each validation run.
66
+ #
67
+ # The easiest way to add custom validators for validating individual attributes
68
+ # is with the convenient <tt>ActiveModel::EachValidator</tt>.
69
+ #
70
+ # class TitleValidator < ActiveModel::EachValidator
71
+ # def validate_each(record, attribute, value)
72
+ # record.errors.add attribute, 'must be Mr., Mrs., or Dr.' unless %w(Mr. Mrs. Dr.).include?(value)
73
+ # end
74
+ # end
75
+ #
76
+ # This can now be used in combination with the +validates+ method
77
+ # (see <tt>ActiveModel::Validations::ClassMethods.validates</tt> for more on this).
78
+ #
79
+ # class Person
80
+ # include ActiveModel::Validations
81
+ # attr_accessor :title
82
+ #
83
+ # validates :title, presence: true, title: true
84
+ # end
85
+ #
86
+ # It can be useful to access the class that is using that validator when there are prerequisites such
87
+ # as an +attr_accessor+ being present. This class is accessible via <tt>options[:class]</tt> in the constructor.
88
+ # To setup your validator override the constructor.
89
+ #
90
+ # class MyValidator < ActiveModel::Validator
91
+ # def initialize(options={})
92
+ # super
93
+ # options[:class].attr_accessor :custom_attribute
94
+ # end
95
+ # end
96
+ class Validator
97
+ attr_reader :options
98
+
99
+ # Returns the kind of the validator.
100
+ #
101
+ # PresenceValidator.kind # => :presence
102
+ # AcceptanceValidator.kind # => :acceptance
103
+ def self.kind
104
+ @kind ||= name.split("::").last.underscore.chomp("_validator").to_sym unless anonymous?
105
+ end
106
+
107
+ # Accepts options that will be made available through the +options+ reader.
108
+ def initialize(options = {})
109
+ @options = options.except(:class).freeze
110
+ end
111
+
112
+ # Returns the kind for this validator.
113
+ #
114
+ # PresenceValidator.new(attributes: [:username]).kind # => :presence
115
+ # AcceptanceValidator.new(attributes: [:terms]).kind # => :acceptance
116
+ def kind
117
+ self.class.kind
118
+ end
119
+
120
+ # Override this method in subclasses with validation logic, adding errors
121
+ # to the records +errors+ array where necessary.
122
+ def validate(record)
123
+ raise NotImplementedError, "Subclasses must implement a validate(record) method."
124
+ end
125
+ end
126
+
127
+ # +EachValidator+ is a validator which iterates through the attributes given
128
+ # in the options hash invoking the <tt>validate_each</tt> method passing in the
129
+ # record, attribute and value.
130
+ #
131
+ # All \Active \Model validations are built on top of this validator.
132
+ class EachValidator < Validator #:nodoc:
133
+ attr_reader :attributes
134
+
135
+ # Returns a new validator instance. All options will be available via the
136
+ # +options+ reader, however the <tt>:attributes</tt> option will be removed
137
+ # and instead be made available through the +attributes+ reader.
138
+ def initialize(options)
139
+ @attributes = Array(options.delete(:attributes))
140
+ raise ArgumentError, ":attributes cannot be blank" if @attributes.empty?
141
+ super
142
+ check_validity!
143
+ end
144
+
145
+ # Performs validation on the supplied record. By default this will call
146
+ # +validate_each+ to determine validity therefore subclasses should
147
+ # override +validate_each+ with validation logic.
148
+ def validate(record)
149
+ attributes.each do |attribute|
150
+ value = record.read_attribute_for_validation(attribute)
151
+ next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
152
+ validate_each(record, attribute, value)
153
+ end
154
+ end
155
+
156
+ # Override this method in subclasses with the validation logic, adding
157
+ # errors to the records +errors+ array where necessary.
158
+ def validate_each(record, attribute, value)
159
+ raise NotImplementedError, "Subclasses must implement a validate_each(record, attribute, value) method"
160
+ end
161
+
162
+ # Hook method that gets called by the initializer allowing verification
163
+ # that the arguments supplied are valid. You could for example raise an
164
+ # +ArgumentError+ when invalid options are supplied.
165
+ def check_validity!
166
+ end
167
+ end
168
+
169
+ # +BlockValidator+ is a special +EachValidator+ which receives a block on initialization
170
+ # and call this block for each attribute being validated. +validates_each+ uses this validator.
171
+ class BlockValidator < EachValidator #:nodoc:
172
+ def initialize(options, &block)
173
+ @block = block
174
+ super
175
+ end
176
+
177
+ private
178
+
179
+ def validate_each(record, attribute, value)
180
+ @block.call(record, attribute, value)
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gem_version"
4
+
5
+ module ActiveModel
6
+ # Returns the version of the currently loaded \Active \Model as a <tt>Gem::Version</tt>
7
+ def self.version
8
+ gem_version
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activemodel
3
+ version: !ruby/object:Gem::Version
4
+ version: 6.0.0
5
+ platform: ruby
6
+ authors:
7
+ - David Heinemeier Hansson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ description: A toolkit for building modeling frameworks like Active Record. Rich support
28
+ for attributes, callbacks, validations, serialization, internationalization, and
29
+ testing.
30
+ email: david@loudthinking.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - MIT-LICENSE
37
+ - README.rdoc
38
+ - lib/active_model.rb
39
+ - lib/active_model/attribute.rb
40
+ - lib/active_model/attribute/user_provided_default.rb
41
+ - lib/active_model/attribute_assignment.rb
42
+ - lib/active_model/attribute_methods.rb
43
+ - lib/active_model/attribute_mutation_tracker.rb
44
+ - lib/active_model/attribute_set.rb
45
+ - lib/active_model/attribute_set/builder.rb
46
+ - lib/active_model/attribute_set/yaml_encoder.rb
47
+ - lib/active_model/attributes.rb
48
+ - lib/active_model/callbacks.rb
49
+ - lib/active_model/conversion.rb
50
+ - lib/active_model/dirty.rb
51
+ - lib/active_model/errors.rb
52
+ - lib/active_model/forbidden_attributes_protection.rb
53
+ - lib/active_model/gem_version.rb
54
+ - lib/active_model/lint.rb
55
+ - lib/active_model/locale/en.yml
56
+ - lib/active_model/model.rb
57
+ - lib/active_model/naming.rb
58
+ - lib/active_model/railtie.rb
59
+ - lib/active_model/secure_password.rb
60
+ - lib/active_model/serialization.rb
61
+ - lib/active_model/serializers/json.rb
62
+ - lib/active_model/translation.rb
63
+ - lib/active_model/type.rb
64
+ - lib/active_model/type/big_integer.rb
65
+ - lib/active_model/type/binary.rb
66
+ - lib/active_model/type/boolean.rb
67
+ - lib/active_model/type/date.rb
68
+ - lib/active_model/type/date_time.rb
69
+ - lib/active_model/type/decimal.rb
70
+ - lib/active_model/type/float.rb
71
+ - lib/active_model/type/helpers.rb
72
+ - lib/active_model/type/helpers/accepts_multiparameter_time.rb
73
+ - lib/active_model/type/helpers/mutable.rb
74
+ - lib/active_model/type/helpers/numeric.rb
75
+ - lib/active_model/type/helpers/time_value.rb
76
+ - lib/active_model/type/helpers/timezone.rb
77
+ - lib/active_model/type/immutable_string.rb
78
+ - lib/active_model/type/integer.rb
79
+ - lib/active_model/type/registry.rb
80
+ - lib/active_model/type/string.rb
81
+ - lib/active_model/type/time.rb
82
+ - lib/active_model/type/value.rb
83
+ - lib/active_model/validations.rb
84
+ - lib/active_model/validations/absence.rb
85
+ - lib/active_model/validations/acceptance.rb
86
+ - lib/active_model/validations/callbacks.rb
87
+ - lib/active_model/validations/clusivity.rb
88
+ - lib/active_model/validations/confirmation.rb
89
+ - lib/active_model/validations/exclusion.rb
90
+ - lib/active_model/validations/format.rb
91
+ - lib/active_model/validations/helper_methods.rb
92
+ - lib/active_model/validations/inclusion.rb
93
+ - lib/active_model/validations/length.rb
94
+ - lib/active_model/validations/numericality.rb
95
+ - lib/active_model/validations/presence.rb
96
+ - lib/active_model/validations/validates.rb
97
+ - lib/active_model/validations/with.rb
98
+ - lib/active_model/validator.rb
99
+ - lib/active_model/version.rb
100
+ homepage: https://rubyonrails.org
101
+ licenses:
102
+ - MIT
103
+ metadata:
104
+ source_code_uri: https://github.com/rails/rails/tree/v6.0.0/activemodel
105
+ changelog_uri: https://github.com/rails/rails/blob/v6.0.0/activemodel/CHANGELOG.md
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: 2.5.0
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubygems_version: 3.0.1
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: A toolkit for building modeling frameworks (part of Rails).
125
+ test_files: []