activemodel 6.1.7.10 → 7.0.0.alpha1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -224
- data/MIT-LICENSE +2 -1
- data/README.rdoc +3 -3
- data/lib/active_model/api.rb +99 -0
- data/lib/active_model/attribute.rb +4 -0
- data/lib/active_model/attribute_methods.rb +99 -52
- data/lib/active_model/attribute_set.rb +4 -1
- data/lib/active_model/attributes.rb +15 -12
- data/lib/active_model/callbacks.rb +1 -1
- data/lib/active_model/conversion.rb +2 -2
- data/lib/active_model/dirty.rb +5 -4
- data/lib/active_model/errors.rb +17 -3
- data/lib/active_model/gem_version.rb +4 -4
- data/lib/active_model/locale/en.yml +1 -0
- data/lib/active_model/model.rb +6 -59
- data/lib/active_model/naming.rb +15 -8
- data/lib/active_model/secure_password.rb +0 -1
- data/lib/active_model/serialization.rb +7 -2
- data/lib/active_model/translation.rb +1 -1
- data/lib/active_model/type/helpers/numeric.rb +9 -1
- data/lib/active_model/type/helpers/time_value.rb +2 -2
- data/lib/active_model/type/integer.rb +4 -1
- data/lib/active_model/type/registry.rb +8 -38
- data/lib/active_model/type/time.rb +1 -1
- data/lib/active_model/type.rb +6 -6
- data/lib/active_model/validations/absence.rb +1 -1
- data/lib/active_model/validations/clusivity.rb +1 -1
- data/lib/active_model/validations/comparability.rb +29 -0
- data/lib/active_model/validations/comparison.rb +82 -0
- data/lib/active_model/validations/confirmation.rb +4 -4
- data/lib/active_model/validations/numericality.rb +27 -20
- data/lib/active_model/validations.rb +4 -4
- data/lib/active_model/validator.rb +2 -2
- data/lib/active_model.rb +2 -1
- metadata +14 -12
@@ -25,6 +25,10 @@ module ActiveModel
|
|
25
25
|
attributes.transform_values(&:value_before_type_cast)
|
26
26
|
end
|
27
27
|
|
28
|
+
def values_for_database
|
29
|
+
attributes.transform_values(&:value_for_database)
|
30
|
+
end
|
31
|
+
|
28
32
|
def to_hash
|
29
33
|
keys.index_with { |name| self[name].value }
|
30
34
|
end
|
@@ -54,7 +58,6 @@ module ActiveModel
|
|
54
58
|
|
55
59
|
def write_cast_value(name, value)
|
56
60
|
@attributes[name] = self[name].with_cast_value(value)
|
57
|
-
value
|
58
61
|
end
|
59
62
|
|
60
63
|
def freeze
|
@@ -4,25 +4,26 @@ require "active_model/attribute_set"
|
|
4
4
|
require "active_model/attribute/user_provided_default"
|
5
5
|
|
6
6
|
module ActiveModel
|
7
|
-
module Attributes
|
7
|
+
module Attributes # :nodoc:
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
include ActiveModel::AttributeMethods
|
10
10
|
|
11
11
|
included do
|
12
|
-
attribute_method_suffix "="
|
12
|
+
attribute_method_suffix "=", parameters: "value"
|
13
13
|
class_attribute :attribute_types, :_default_attributes, instance_accessor: false
|
14
14
|
self.attribute_types = Hash.new(Type.default_value)
|
15
15
|
self._default_attributes = AttributeSet.new({})
|
16
16
|
end
|
17
17
|
|
18
18
|
module ClassMethods
|
19
|
-
def attribute(name,
|
19
|
+
def attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options)
|
20
20
|
name = name.to_s
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
|
22
|
+
cast_type = Type.lookup(cast_type, **options) if Symbol === cast_type
|
23
|
+
cast_type ||= attribute_types[name]
|
24
|
+
|
25
|
+
self.attribute_types = attribute_types.merge(name => cast_type)
|
26
|
+
define_default_attribute(name, default, cast_type)
|
26
27
|
define_attribute_method(name)
|
27
28
|
end
|
28
29
|
|
@@ -46,10 +47,12 @@ module ActiveModel
|
|
46
47
|
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
47
48
|
owner, name, writer: true,
|
48
49
|
) do |temp_method_name, attr_name_expr|
|
49
|
-
owner
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
owner.define_cached_method("#{name}=", as: temp_method_name, namespace: :active_model) do |batch|
|
51
|
+
batch <<
|
52
|
+
"def #{temp_method_name}(value)" <<
|
53
|
+
" _write_attribute(#{attr_name_expr}, value)" <<
|
54
|
+
"end"
|
55
|
+
end
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
@@ -63,7 +63,7 @@ module ActiveModel
|
|
63
63
|
# NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
|
64
64
|
#
|
65
65
|
module Callbacks
|
66
|
-
def self.extended(base)
|
66
|
+
def self.extended(base) # :nodoc:
|
67
67
|
base.class_eval do
|
68
68
|
include ActiveSupport::Callbacks
|
69
69
|
end
|
@@ -96,10 +96,10 @@ module ActiveModel
|
|
96
96
|
self.class._to_partial_path
|
97
97
|
end
|
98
98
|
|
99
|
-
module ClassMethods
|
99
|
+
module ClassMethods # :nodoc:
|
100
100
|
# Provide a class level cache for #to_partial_path. This is an
|
101
101
|
# internal method and should not be accessed directly.
|
102
|
-
def _to_partial_path
|
102
|
+
def _to_partial_path # :nodoc:
|
103
103
|
@_to_partial_path ||= begin
|
104
104
|
element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(name))
|
105
105
|
collection = ActiveSupport::Inflector.tableize(name)
|
data/lib/active_model/dirty.rb
CHANGED
@@ -123,10 +123,11 @@ module ActiveModel
|
|
123
123
|
include ActiveModel::AttributeMethods
|
124
124
|
|
125
125
|
included do
|
126
|
-
attribute_method_suffix "
|
127
|
-
attribute_method_suffix "
|
128
|
-
|
129
|
-
attribute_method_affix prefix: "
|
126
|
+
attribute_method_suffix "_previously_changed?", "_changed?", parameters: "**options"
|
127
|
+
attribute_method_suffix "_change", "_will_change!", "_was", parameters: false
|
128
|
+
attribute_method_suffix "_previous_change", "_previously_was", parameters: false
|
129
|
+
attribute_method_affix prefix: "restore_", suffix: "!", parameters: false
|
130
|
+
attribute_method_affix prefix: "clear_", suffix: "_change", parameters: false
|
130
131
|
end
|
131
132
|
|
132
133
|
def initialize_dup(other) # :nodoc:
|
data/lib/active_model/errors.rb
CHANGED
@@ -378,6 +378,14 @@ module ActiveModel
|
|
378
378
|
# If +type+ is a symbol, it will be translated using the appropriate
|
379
379
|
# scope (see +generate_message+).
|
380
380
|
#
|
381
|
+
# person.errors.add(:name, :blank)
|
382
|
+
# person.errors.messages
|
383
|
+
# # => {:name=>["can't be blank"]}
|
384
|
+
#
|
385
|
+
# person.errors.add(:name, :too_long, { count: 25 })
|
386
|
+
# person.errors.messages
|
387
|
+
# # => ["is too long (maximum is 25 characters)"]
|
388
|
+
#
|
381
389
|
# If +type+ is a proc, it will be called, allowing for things like
|
382
390
|
# <tt>Time.now</tt> to be used within an error.
|
383
391
|
#
|
@@ -563,6 +571,12 @@ module ActiveModel
|
|
563
571
|
add_from_legacy_details_hash(data["details"]) if data.key?("details")
|
564
572
|
end
|
565
573
|
|
574
|
+
def inspect # :nodoc:
|
575
|
+
inspection = @errors.inspect
|
576
|
+
|
577
|
+
"#<#{self.class.name} #{inspection}>"
|
578
|
+
end
|
579
|
+
|
566
580
|
private
|
567
581
|
def normalize_arguments(attribute, type, **options)
|
568
582
|
# Evaluate proc first
|
@@ -596,7 +610,7 @@ module ActiveModel
|
|
596
610
|
end
|
597
611
|
end
|
598
612
|
|
599
|
-
class DeprecationHandlingMessageHash < SimpleDelegator
|
613
|
+
class DeprecationHandlingMessageHash < SimpleDelegator # :nodoc:
|
600
614
|
def initialize(errors)
|
601
615
|
@errors = errors
|
602
616
|
super(prepare_content)
|
@@ -635,7 +649,7 @@ module ActiveModel
|
|
635
649
|
end
|
636
650
|
end
|
637
651
|
|
638
|
-
class DeprecationHandlingMessageArray < SimpleDelegator
|
652
|
+
class DeprecationHandlingMessageArray < SimpleDelegator # :nodoc:
|
639
653
|
def initialize(content, errors, attribute)
|
640
654
|
@errors = errors
|
641
655
|
@attribute = attribute
|
@@ -657,7 +671,7 @@ module ActiveModel
|
|
657
671
|
end
|
658
672
|
end
|
659
673
|
|
660
|
-
class DeprecationHandlingDetailsHash < SimpleDelegator
|
674
|
+
class DeprecationHandlingDetailsHash < SimpleDelegator # :nodoc:
|
661
675
|
def initialize(details)
|
662
676
|
details.default = []
|
663
677
|
details.freeze
|
data/lib/active_model/model.rb
CHANGED
@@ -3,11 +3,10 @@
|
|
3
3
|
module ActiveModel
|
4
4
|
# == Active \Model \Basic \Model
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# hash of attributes, pretty much like Active Record does.
|
6
|
+
# Allows implementing models similar to <tt>ActiveRecord::Base</tt>.
|
7
|
+
# Includes <tt>ActiveModel::API</tt> for the required interface for an
|
8
|
+
# object to interact with Action Pack and Action View, but can be
|
9
|
+
# extended with other functionalities.
|
11
10
|
#
|
12
11
|
# A minimal implementation could be:
|
13
12
|
#
|
@@ -20,23 +19,7 @@ module ActiveModel
|
|
20
19
|
# person.name # => "bob"
|
21
20
|
# person.age # => "18"
|
22
21
|
#
|
23
|
-
#
|
24
|
-
# to return +false+, which is the most common case. You may want to override
|
25
|
-
# it in your class to simulate a different scenario:
|
26
|
-
#
|
27
|
-
# class Person
|
28
|
-
# include ActiveModel::Model
|
29
|
-
# attr_accessor :id, :name
|
30
|
-
#
|
31
|
-
# def persisted?
|
32
|
-
# self.id == 1
|
33
|
-
# end
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
# person = Person.new(id: 1, name: 'bob')
|
37
|
-
# person.persisted? # => true
|
38
|
-
#
|
39
|
-
# Also, if for some reason you need to run code on <tt>initialize</tt>, make
|
22
|
+
# If for some reason you need to run code on <tt>initialize</tt>, make
|
40
23
|
# sure you call +super+ if you want the attributes hash initialization to
|
41
24
|
# happen.
|
42
25
|
#
|
@@ -58,42 +41,6 @@ module ActiveModel
|
|
58
41
|
# (see below).
|
59
42
|
module Model
|
60
43
|
extend ActiveSupport::Concern
|
61
|
-
include ActiveModel::
|
62
|
-
include ActiveModel::Validations
|
63
|
-
include ActiveModel::Conversion
|
64
|
-
|
65
|
-
included do
|
66
|
-
extend ActiveModel::Naming
|
67
|
-
extend ActiveModel::Translation
|
68
|
-
end
|
69
|
-
|
70
|
-
# Initializes a new model with the given +params+.
|
71
|
-
#
|
72
|
-
# class Person
|
73
|
-
# include ActiveModel::Model
|
74
|
-
# attr_accessor :name, :age
|
75
|
-
# end
|
76
|
-
#
|
77
|
-
# person = Person.new(name: 'bob', age: '18')
|
78
|
-
# person.name # => "bob"
|
79
|
-
# person.age # => "18"
|
80
|
-
def initialize(attributes = {})
|
81
|
-
assign_attributes(attributes) if attributes
|
82
|
-
|
83
|
-
super()
|
84
|
-
end
|
85
|
-
|
86
|
-
# Indicates if the model is persisted. Default is +false+.
|
87
|
-
#
|
88
|
-
# class Person
|
89
|
-
# include ActiveModel::Model
|
90
|
-
# attr_accessor :id, :name
|
91
|
-
# end
|
92
|
-
#
|
93
|
-
# person = Person.new(id: 1, name: 'bob')
|
94
|
-
# person.persisted? # => false
|
95
|
-
def persisted?
|
96
|
-
false
|
97
|
-
end
|
44
|
+
include ActiveModel::API
|
98
45
|
end
|
99
46
|
end
|
data/lib/active_model/naming.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/hash/except"
|
4
4
|
require "active_support/core_ext/module/introspection"
|
5
5
|
require "active_support/core_ext/module/redefine_method"
|
6
|
+
require "active_support/core_ext/module/delegation"
|
6
7
|
|
7
8
|
module ActiveModel
|
8
9
|
class Name
|
@@ -153,6 +154,7 @@ module ActiveModel
|
|
153
154
|
# Returns a new ActiveModel::Name instance. By default, the +namespace+
|
154
155
|
# and +name+ option will take the namespace and name of the given class
|
155
156
|
# respectively.
|
157
|
+
# Use +locale+ argument for singularize and pluralize model name.
|
156
158
|
#
|
157
159
|
# module Foo
|
158
160
|
# class Bar
|
@@ -161,7 +163,7 @@ module ActiveModel
|
|
161
163
|
#
|
162
164
|
# ActiveModel::Name.new(Foo::Bar).to_s
|
163
165
|
# # => "Foo::Bar"
|
164
|
-
def initialize(klass, namespace = nil, name = nil)
|
166
|
+
def initialize(klass, namespace = nil, name = nil, locale = :en)
|
165
167
|
@name = name || klass.name
|
166
168
|
|
167
169
|
raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if @name.blank?
|
@@ -169,16 +171,17 @@ module ActiveModel
|
|
169
171
|
@unnamespaced = @name.delete_prefix("#{namespace.name}::") if namespace
|
170
172
|
@klass = klass
|
171
173
|
@singular = _singularize(@name)
|
172
|
-
@plural = ActiveSupport::Inflector.pluralize(@singular)
|
174
|
+
@plural = ActiveSupport::Inflector.pluralize(@singular, locale)
|
175
|
+
@uncountable = @plural == @singular
|
173
176
|
@element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(@name))
|
174
177
|
@human = ActiveSupport::Inflector.humanize(@element)
|
175
178
|
@collection = ActiveSupport::Inflector.tableize(@name)
|
176
179
|
@param_key = (namespace ? _singularize(@unnamespaced) : @singular)
|
177
180
|
@i18n_key = @name.underscore.to_sym
|
178
181
|
|
179
|
-
@route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural.dup)
|
180
|
-
@singular_route_key = ActiveSupport::Inflector.singularize(@route_key)
|
181
|
-
@route_key << "_index" if @
|
182
|
+
@route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key, locale) : @plural.dup)
|
183
|
+
@singular_route_key = ActiveSupport::Inflector.singularize(@route_key, locale)
|
184
|
+
@route_key << "_index" if @uncountable
|
182
185
|
end
|
183
186
|
|
184
187
|
# Transform the model name into a more human format, using I18n. By default,
|
@@ -206,6 +209,10 @@ module ActiveModel
|
|
206
209
|
I18n.translate(defaults.shift, **options)
|
207
210
|
end
|
208
211
|
|
212
|
+
def uncountable?
|
213
|
+
@uncountable
|
214
|
+
end
|
215
|
+
|
209
216
|
private
|
210
217
|
def _singularize(string)
|
211
218
|
ActiveSupport::Inflector.underscore(string).tr("/", "_")
|
@@ -232,7 +239,7 @@ module ActiveModel
|
|
232
239
|
# is required to pass the \Active \Model Lint test. So either extending the
|
233
240
|
# provided method below, or rolling your own is required.
|
234
241
|
module Naming
|
235
|
-
def self.extended(base)
|
242
|
+
def self.extended(base) # :nodoc:
|
236
243
|
base.silence_redefinition_of_method :model_name
|
237
244
|
base.delegate :model_name, to: :class
|
238
245
|
end
|
@@ -279,7 +286,7 @@ module ActiveModel
|
|
279
286
|
# ActiveModel::Naming.uncountable?(Sheep) # => true
|
280
287
|
# ActiveModel::Naming.uncountable?(Post) # => false
|
281
288
|
def self.uncountable?(record_or_class)
|
282
|
-
|
289
|
+
model_name_from_record_or_class(record_or_class).uncountable?
|
283
290
|
end
|
284
291
|
|
285
292
|
# Returns string to use while generating route names. It differs for
|
@@ -321,7 +328,7 @@ module ActiveModel
|
|
321
328
|
model_name_from_record_or_class(record_or_class).param_key
|
322
329
|
end
|
323
330
|
|
324
|
-
def self.model_name_from_record_or_class(record_or_class)
|
331
|
+
def self.model_name_from_record_or_class(record_or_class) # :nodoc:
|
325
332
|
if record_or_class.respond_to?(:to_model)
|
326
333
|
record_or_class.to_model.model_name
|
327
334
|
else
|
@@ -94,7 +94,6 @@ module ActiveModel
|
|
94
94
|
|
95
95
|
define_method("#{attribute}=") do |unencrypted_password|
|
96
96
|
if unencrypted_password.nil?
|
97
|
-
instance_variable_set("@#{attribute}", nil)
|
98
97
|
self.public_send("#{attribute}_digest=", nil)
|
99
98
|
elsif !unencrypted_password.empty?
|
100
99
|
instance_variable_set("@#{attribute}", unencrypted_password)
|
@@ -123,7 +123,7 @@ module ActiveModel
|
|
123
123
|
# user.serializable_hash(include: { notes: { only: 'title' }})
|
124
124
|
# # => {"name" => "Napoleon", "notes" => [{"title"=>"Battle of Austerlitz"}]}
|
125
125
|
def serializable_hash(options = nil)
|
126
|
-
attribute_names =
|
126
|
+
attribute_names = self.attribute_names
|
127
127
|
|
128
128
|
return serializable_attributes(attribute_names) if options.blank?
|
129
129
|
|
@@ -148,6 +148,11 @@ module ActiveModel
|
|
148
148
|
hash
|
149
149
|
end
|
150
150
|
|
151
|
+
# Returns an array of attribute names as strings
|
152
|
+
def attribute_names # :nodoc:
|
153
|
+
attributes.keys
|
154
|
+
end
|
155
|
+
|
151
156
|
private
|
152
157
|
# Hook method defining how an attribute value should be retrieved for
|
153
158
|
# serialization. By default this is assumed to be an instance named after
|
@@ -177,7 +182,7 @@ module ActiveModel
|
|
177
182
|
# +association+ - name of the association
|
178
183
|
# +records+ - the association record(s) to be serialized
|
179
184
|
# +opts+ - options for the association records
|
180
|
-
def serializable_add_includes(options = {})
|
185
|
+
def serializable_add_includes(options = {}) # :nodoc:
|
181
186
|
return unless includes = options[:include]
|
182
187
|
|
183
188
|
unless includes.is_a?(Hash)
|
@@ -17,7 +17,7 @@ module ActiveModel
|
|
17
17
|
#
|
18
18
|
# This also provides the required class methods for hooking into the
|
19
19
|
# Rails internationalization API, including being able to define a
|
20
|
-
# class
|
20
|
+
# class-based +i18n_scope+ and +lookup_ancestors+ to find translations in
|
21
21
|
# parent classes.
|
22
22
|
module Translation
|
23
23
|
include ActiveModel::Naming
|
@@ -25,10 +25,18 @@ module ActiveModel
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def changed?(old_value, _new_value, new_value_before_type_cast) # :nodoc:
|
28
|
-
super || number_to_non_number?(old_value, new_value_before_type_cast)
|
28
|
+
(super || number_to_non_number?(old_value, new_value_before_type_cast)) &&
|
29
|
+
!equal_nan?(old_value, new_value_before_type_cast)
|
29
30
|
end
|
30
31
|
|
31
32
|
private
|
33
|
+
def equal_nan?(old_value, new_value)
|
34
|
+
(old_value.is_a?(::Float) || old_value.is_a?(BigDecimal)) &&
|
35
|
+
old_value.nan? &&
|
36
|
+
old_value.instance_of?(new_value.class) &&
|
37
|
+
new_value.nan?
|
38
|
+
end
|
39
|
+
|
32
40
|
def number_to_non_number?(old_value, new_value_before_type_cast)
|
33
41
|
old_value != nil && non_numeric_string?(new_value_before_type_cast.to_s)
|
34
42
|
end
|
@@ -12,9 +12,9 @@ module ActiveModel
|
|
12
12
|
|
13
13
|
if value.acts_like?(:time)
|
14
14
|
if is_utc?
|
15
|
-
value = value.getutc if
|
15
|
+
value = value.getutc if !value.utc?
|
16
16
|
else
|
17
|
-
value = value.getlocal
|
17
|
+
value = value.getlocal
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -1,68 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveModel
|
4
|
-
# :stopdoc:
|
5
4
|
module Type
|
6
|
-
class Registry
|
5
|
+
class Registry # :nodoc:
|
7
6
|
def initialize
|
8
|
-
@registrations =
|
7
|
+
@registrations = {}
|
9
8
|
end
|
10
9
|
|
11
|
-
def
|
10
|
+
def initialize_copy(other)
|
12
11
|
@registrations = @registrations.dup
|
13
12
|
super
|
14
13
|
end
|
15
14
|
|
16
|
-
def register(type_name, klass = nil,
|
15
|
+
def register(type_name, klass = nil, &block)
|
17
16
|
unless block_given?
|
18
17
|
block = proc { |_, *args| klass.new(*args) }
|
19
18
|
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
|
20
19
|
end
|
21
|
-
registrations
|
20
|
+
registrations[type_name] = block
|
22
21
|
end
|
23
22
|
|
24
23
|
def lookup(symbol, *args)
|
25
|
-
registration =
|
24
|
+
registration = registrations[symbol]
|
26
25
|
|
27
26
|
if registration
|
28
|
-
registration.call(
|
27
|
+
registration.call(symbol, *args)
|
29
28
|
else
|
30
29
|
raise ArgumentError, "Unknown type #{symbol.inspect}"
|
31
30
|
end
|
32
31
|
end
|
33
|
-
ruby2_keywords(:lookup)
|
32
|
+
ruby2_keywords(:lookup)
|
34
33
|
|
35
34
|
private
|
36
35
|
attr_reader :registrations
|
37
|
-
|
38
|
-
def registration_klass
|
39
|
-
Registration
|
40
|
-
end
|
41
|
-
|
42
|
-
def find_registration(symbol, *args, **kwargs)
|
43
|
-
registrations.find { |r| r.matches?(symbol, *args, **kwargs) }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class Registration
|
48
|
-
# Options must be taken because of https://bugs.ruby-lang.org/issues/10856
|
49
|
-
def initialize(name, block, **)
|
50
|
-
@name = name
|
51
|
-
@block = block
|
52
|
-
end
|
53
|
-
|
54
|
-
def call(_registry, *args)
|
55
|
-
block.call(*args)
|
56
|
-
end
|
57
|
-
ruby2_keywords(:call) if respond_to?(:ruby2_keywords, true)
|
58
|
-
|
59
|
-
def matches?(type_name, *args, **kwargs)
|
60
|
-
type_name == name
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
attr_reader :name, :block
|
65
36
|
end
|
66
37
|
end
|
67
|
-
# :startdoc:
|
68
38
|
end
|
@@ -33,7 +33,7 @@ module ActiveModel
|
|
33
33
|
return apply_seconds_precision(value) unless value.is_a?(::String)
|
34
34
|
return if value.empty?
|
35
35
|
|
36
|
-
dummy_time_value = value.sub(/\A
|
36
|
+
dummy_time_value = value.sub(/\A\d{4}-\d\d-\d\d(?:T|\s)|/, "2000-01-01 ")
|
37
37
|
|
38
38
|
fast_string_to_time(dummy_time_value) || begin
|
39
39
|
time_hash = ::Date._parse(dummy_time_value)
|
data/lib/active_model/type.rb
CHANGED
@@ -24,15 +24,15 @@ module ActiveModel
|
|
24
24
|
class << self
|
25
25
|
attr_accessor :registry # :nodoc:
|
26
26
|
|
27
|
-
# Add a new type to the registry, allowing it to be
|
28
|
-
|
29
|
-
|
27
|
+
# Add a new type to the registry, allowing it to be referenced as a
|
28
|
+
# symbol by {attribute}[rdoc-ref:Attributes::ClassMethods#attribute].
|
29
|
+
def register(type_name, klass = nil, &block)
|
30
|
+
registry.register(type_name, klass, &block)
|
30
31
|
end
|
31
32
|
|
32
|
-
def lookup(
|
33
|
-
registry.lookup(
|
33
|
+
def lookup(...) # :nodoc:
|
34
|
+
registry.lookup(...)
|
34
35
|
end
|
35
|
-
ruby2_keywords(:lookup) if respond_to?(:ruby2_keywords, true)
|
36
36
|
|
37
37
|
def default_value # :nodoc:
|
38
38
|
@default_value ||= Value.new
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActiveModel
|
4
4
|
module Validations
|
5
5
|
# == \Active \Model Absence Validator
|
6
|
-
class AbsenceValidator < EachValidator
|
6
|
+
class AbsenceValidator < EachValidator # :nodoc:
|
7
7
|
def validate_each(record, attr_name, value)
|
8
8
|
record.errors.add(attr_name, :present, **options) if value.present?
|
9
9
|
end
|
@@ -4,7 +4,7 @@ require "active_support/core_ext/range"
|
|
4
4
|
|
5
5
|
module ActiveModel
|
6
6
|
module Validations
|
7
|
-
module Clusivity
|
7
|
+
module Clusivity # :nodoc:
|
8
8
|
ERROR_MESSAGE = "An object with the method #include? or a proc, lambda or symbol is required, " \
|
9
9
|
"and must be supplied as the :in (or :within) option of the configuration hash"
|
10
10
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module Validations
|
5
|
+
module Comparability # :nodoc:
|
6
|
+
COMPARE_CHECKS = { greater_than: :>, greater_than_or_equal_to: :>=,
|
7
|
+
equal_to: :==, less_than: :<, less_than_or_equal_to: :<=,
|
8
|
+
other_than: :!= }.freeze
|
9
|
+
|
10
|
+
def option_value(record, option_value)
|
11
|
+
case option_value
|
12
|
+
when Proc
|
13
|
+
option_value.call(record)
|
14
|
+
when Symbol
|
15
|
+
record.send(option_value)
|
16
|
+
else
|
17
|
+
option_value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def error_options(value, option_value)
|
22
|
+
options.except(*COMPARE_CHECKS.keys).merge!(
|
23
|
+
count: option_value,
|
24
|
+
value: value
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|