activemodel 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []