activemodel 7.0.8.1 → 7.1.0.beta1
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 +132 -196
- data/MIT-LICENSE +1 -1
- data/README.rdoc +9 -9
- data/lib/active_model/access.rb +16 -0
- data/lib/active_model/api.rb +5 -5
- data/lib/active_model/attribute/user_provided_default.rb +4 -0
- data/lib/active_model/attribute.rb +26 -1
- data/lib/active_model/attribute_assignment.rb +1 -1
- data/lib/active_model/attribute_methods.rb +102 -63
- data/lib/active_model/attribute_registration.rb +77 -0
- data/lib/active_model/attribute_set.rb +9 -0
- data/lib/active_model/attributes.rb +62 -45
- data/lib/active_model/callbacks.rb +5 -5
- data/lib/active_model/conversion.rb +14 -4
- data/lib/active_model/deprecator.rb +7 -0
- data/lib/active_model/dirty.rb +134 -13
- data/lib/active_model/error.rb +4 -3
- data/lib/active_model/errors.rb +17 -12
- data/lib/active_model/forbidden_attributes_protection.rb +2 -0
- data/lib/active_model/gem_version.rb +4 -4
- data/lib/active_model/lint.rb +1 -1
- data/lib/active_model/locale/en.yml +4 -3
- data/lib/active_model/model.rb +26 -2
- data/lib/active_model/naming.rb +29 -10
- data/lib/active_model/railtie.rb +4 -0
- data/lib/active_model/secure_password.rb +61 -23
- data/lib/active_model/serialization.rb +3 -3
- data/lib/active_model/serializers/json.rb +1 -1
- data/lib/active_model/translation.rb +18 -16
- data/lib/active_model/type/big_integer.rb +23 -1
- data/lib/active_model/type/binary.rb +7 -1
- data/lib/active_model/type/boolean.rb +11 -9
- data/lib/active_model/type/date.rb +28 -2
- data/lib/active_model/type/date_time.rb +45 -3
- data/lib/active_model/type/decimal.rb +39 -1
- data/lib/active_model/type/float.rb +30 -1
- data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +5 -1
- data/lib/active_model/type/helpers/numeric.rb +4 -0
- data/lib/active_model/type/helpers/time_value.rb +28 -12
- data/lib/active_model/type/immutable_string.rb +37 -1
- data/lib/active_model/type/integer.rb +44 -1
- data/lib/active_model/type/serialize_cast_value.rb +47 -0
- data/lib/active_model/type/string.rb +9 -1
- data/lib/active_model/type/time.rb +48 -7
- data/lib/active_model/type/value.rb +17 -1
- data/lib/active_model/type.rb +1 -0
- data/lib/active_model/validations/absence.rb +1 -1
- data/lib/active_model/validations/acceptance.rb +1 -1
- data/lib/active_model/validations/callbacks.rb +4 -4
- data/lib/active_model/validations/clusivity.rb +5 -8
- data/lib/active_model/validations/comparability.rb +0 -11
- data/lib/active_model/validations/comparison.rb +15 -7
- data/lib/active_model/validations/confirmation.rb +1 -1
- data/lib/active_model/validations/format.rb +6 -7
- data/lib/active_model/validations/length.rb +10 -8
- data/lib/active_model/validations/numericality.rb +35 -23
- data/lib/active_model/validations/presence.rb +2 -2
- data/lib/active_model/validations/resolve_value.rb +26 -0
- data/lib/active_model/validations/validates.rb +4 -4
- data/lib/active_model/validations/with.rb +9 -2
- data/lib/active_model/validations.rb +45 -10
- data/lib/active_model/validator.rb +7 -5
- data/lib/active_model/version.rb +1 -1
- data/lib/active_model.rb +5 -1
- metadata +15 -10
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveModel
|
4
|
-
#
|
4
|
+
# = Active \Model \Conversion
|
5
5
|
#
|
6
6
|
# Handles default conversions: to_model, to_key, to_param, and to_partial_path.
|
7
7
|
#
|
@@ -24,6 +24,14 @@ module ActiveModel
|
|
24
24
|
module Conversion
|
25
25
|
extend ActiveSupport::Concern
|
26
26
|
|
27
|
+
included do
|
28
|
+
##
|
29
|
+
# :singleton-method:
|
30
|
+
#
|
31
|
+
# Accepts a string that will be used as a delimiter of object's key values in the `to_param` method.
|
32
|
+
class_attribute :param_delimiter, instance_reader: false, default: "-"
|
33
|
+
end
|
34
|
+
|
27
35
|
# If your object is already designed to implement all of the \Active \Model
|
28
36
|
# you can use the default <tt>:to_model</tt> implementation, which simply
|
29
37
|
# returns +self+.
|
@@ -58,7 +66,7 @@ module ActiveModel
|
|
58
66
|
# person.to_key # => [1]
|
59
67
|
def to_key
|
60
68
|
key = respond_to?(:id) && id
|
61
|
-
key ?
|
69
|
+
key ? Array(key) : nil
|
62
70
|
end
|
63
71
|
|
64
72
|
# Returns a +string+ representing the object's key suitable for use in URLs,
|
@@ -80,7 +88,7 @@ module ActiveModel
|
|
80
88
|
# person = Person.new(1)
|
81
89
|
# person.to_param # => "1"
|
82
90
|
def to_param
|
83
|
-
(persisted? && key = to_key) ? key.join(
|
91
|
+
(persisted? && (key = to_key) && key.all?) ? key.join(self.class.param_delimiter) : nil
|
84
92
|
end
|
85
93
|
|
86
94
|
# Returns a +string+ identifying the path associated with the object.
|
@@ -100,7 +108,9 @@ module ActiveModel
|
|
100
108
|
# Provide a class level cache for #to_partial_path. This is an
|
101
109
|
# internal method and should not be accessed directly.
|
102
110
|
def _to_partial_path # :nodoc:
|
103
|
-
@_to_partial_path ||=
|
111
|
+
@_to_partial_path ||= if respond_to?(:model_name)
|
112
|
+
"#{model_name.collection}/#{model_name.element}"
|
113
|
+
else
|
104
114
|
element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(name))
|
105
115
|
collection = ActiveSupport::Inflector.tableize(name)
|
106
116
|
"#{collection}/#{element}"
|
data/lib/active_model/dirty.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_model/attribute_mutation_tracker"
|
4
4
|
|
5
5
|
module ActiveModel
|
6
|
-
#
|
6
|
+
# = Active \Model \Dirty
|
7
7
|
#
|
8
8
|
# Provides a way to track changes in your object in the same way as
|
9
9
|
# Active Record does.
|
@@ -13,8 +13,7 @@ module ActiveModel
|
|
13
13
|
# * <tt>include ActiveModel::Dirty</tt> in your object.
|
14
14
|
# * Call <tt>define_attribute_methods</tt> passing each method you want to
|
15
15
|
# track.
|
16
|
-
# * Call <tt
|
17
|
-
# attribute.
|
16
|
+
# * Call <tt>*_will_change!</tt> before each change to the tracked attribute.
|
18
17
|
# * Call <tt>changes_applied</tt> after the changes are persisted.
|
19
18
|
# * Call <tt>clear_changes_information</tt> when you want to reset the changes
|
20
19
|
# information.
|
@@ -109,20 +108,136 @@ module ActiveModel
|
|
109
108
|
# person.changes # => {"name" => ["Bill", "Bob"]}
|
110
109
|
#
|
111
110
|
# If an attribute is modified in-place then make use of
|
112
|
-
#
|
111
|
+
# {*_will_change!}[rdoc-label:method-i-2A_will_change-21] to mark that the attribute is changing.
|
113
112
|
# Otherwise \Active \Model can't track changes to in-place attributes. Note
|
114
113
|
# that Active Record can detect in-place modifications automatically. You do
|
115
|
-
# not need to call <tt
|
114
|
+
# not need to call <tt>*_will_change!</tt> on Active Record models.
|
116
115
|
#
|
117
116
|
# person.name_will_change!
|
118
117
|
# person.name_change # => ["Bill", "Bill"]
|
119
118
|
# person.name << 'y'
|
120
119
|
# person.name_change # => ["Bill", "Billy"]
|
120
|
+
#
|
121
|
+
# Methods can be invoked as +name_changed?+ or by passing an argument to the
|
122
|
+
# generic method <tt>attribute_changed?("name")</tt>.
|
121
123
|
module Dirty
|
122
124
|
extend ActiveSupport::Concern
|
123
125
|
include ActiveModel::AttributeMethods
|
124
126
|
|
125
127
|
included do
|
128
|
+
##
|
129
|
+
# :method: *_previously_changed?
|
130
|
+
#
|
131
|
+
# :call-seq: *_previously_changed?(**options)
|
132
|
+
#
|
133
|
+
# This method is generated for each attribute.
|
134
|
+
#
|
135
|
+
# Returns true if the attribute previously had unsaved changes.
|
136
|
+
#
|
137
|
+
# person = Person.new
|
138
|
+
# person.name = 'Britanny'
|
139
|
+
# person.save
|
140
|
+
# person.name_previously_changed? # => true
|
141
|
+
# person.name_previously_changed?(from: nil, to: 'Britanny') # => true
|
142
|
+
|
143
|
+
##
|
144
|
+
# :method: *_changed?
|
145
|
+
#
|
146
|
+
# This method is generated for each attribute.
|
147
|
+
#
|
148
|
+
# Returns true if the attribute has unsaved changes.
|
149
|
+
#
|
150
|
+
# person = Person.new
|
151
|
+
# person.name = 'Andrew'
|
152
|
+
# person.name_changed? # => true
|
153
|
+
|
154
|
+
##
|
155
|
+
# :method: *_change
|
156
|
+
#
|
157
|
+
# This method is generated for each attribute.
|
158
|
+
#
|
159
|
+
# Returns the old and the new value of the attribute.
|
160
|
+
#
|
161
|
+
# person = Person.new
|
162
|
+
# person.name = 'Nick'
|
163
|
+
# person.name_change # => [nil, 'Nick']
|
164
|
+
|
165
|
+
##
|
166
|
+
# :method: *_will_change!
|
167
|
+
#
|
168
|
+
# This method is generated for each attribute.
|
169
|
+
#
|
170
|
+
# If an attribute is modified in-place then make use of
|
171
|
+
# <tt>*_will_change!</tt> to mark that the attribute is changing.
|
172
|
+
# Otherwise Active Model can’t track changes to in-place attributes. Note
|
173
|
+
# that Active Record can detect in-place modifications automatically. You
|
174
|
+
# do not need to call <tt>*_will_change!</tt> on Active Record
|
175
|
+
# models.
|
176
|
+
#
|
177
|
+
# person = Person.new('Sandy')
|
178
|
+
# person.name_will_change!
|
179
|
+
# person.name_change # => ['Sandy', 'Sandy']
|
180
|
+
|
181
|
+
##
|
182
|
+
# :method: *_was
|
183
|
+
#
|
184
|
+
# This method is generated for each attribute.
|
185
|
+
#
|
186
|
+
# Returns the old value of the attribute.
|
187
|
+
#
|
188
|
+
# person = Person.new(name: 'Steph')
|
189
|
+
# person.name = 'Stephanie'
|
190
|
+
# person.name_change # => ['Steph', 'Stephanie']
|
191
|
+
|
192
|
+
##
|
193
|
+
# :method: *_previous_change
|
194
|
+
#
|
195
|
+
# This method is generated for each attribute.
|
196
|
+
#
|
197
|
+
# Returns the old and the new value of the attribute before the last save.
|
198
|
+
#
|
199
|
+
# person = Person.new
|
200
|
+
# person.name = 'Emmanuel'
|
201
|
+
# person.save
|
202
|
+
# person.name_previous_change # => [nil, 'Emmanuel']
|
203
|
+
|
204
|
+
##
|
205
|
+
# :method: *_previously_was
|
206
|
+
#
|
207
|
+
# This method is generated for each attribute.
|
208
|
+
#
|
209
|
+
# Returns the old value of the attribute before the last save.
|
210
|
+
#
|
211
|
+
# person = Person.new
|
212
|
+
# person.name = 'Sage'
|
213
|
+
# person.save
|
214
|
+
# person.name_previously_was # => nil
|
215
|
+
|
216
|
+
##
|
217
|
+
# :method: restore_*!
|
218
|
+
#
|
219
|
+
# This method is generated for each attribute.
|
220
|
+
#
|
221
|
+
# Restores the attribute to the old value.
|
222
|
+
#
|
223
|
+
# person = Person.new
|
224
|
+
# person.name = 'Amanda'
|
225
|
+
# person.restore_name!
|
226
|
+
# person.name # => nil
|
227
|
+
|
228
|
+
##
|
229
|
+
# :method: clear_*_change
|
230
|
+
#
|
231
|
+
# This method is generated for each attribute.
|
232
|
+
#
|
233
|
+
# Clears all dirty data of the attribute: current changes and previous changes.
|
234
|
+
#
|
235
|
+
# person = Person.new(name: 'Chris')
|
236
|
+
# person.name = 'Jason'
|
237
|
+
# person.name_change # => ['Chris', 'Jason']
|
238
|
+
# person.clear_name_change
|
239
|
+
# person.name_change # => nil
|
240
|
+
|
126
241
|
attribute_method_suffix "_previously_changed?", "_changed?", parameters: "**options"
|
127
242
|
attribute_method_suffix "_change", "_will_change!", "_was", parameters: false
|
128
243
|
attribute_method_suffix "_previous_change", "_previously_was", parameters: false
|
@@ -174,23 +289,23 @@ module ActiveModel
|
|
174
289
|
mutations_from_database.changed_attribute_names
|
175
290
|
end
|
176
291
|
|
177
|
-
# Dispatch target for
|
178
|
-
def attribute_changed?(attr_name, **options)
|
292
|
+
# Dispatch target for {*_changed}[rdoc-label:method-i-2A_changed-3F] attribute methods.
|
293
|
+
def attribute_changed?(attr_name, **options)
|
179
294
|
mutations_from_database.changed?(attr_name.to_s, **options)
|
180
295
|
end
|
181
296
|
|
182
|
-
# Dispatch target for
|
183
|
-
def attribute_was(attr_name)
|
297
|
+
# Dispatch target for {*_was}[rdoc-label:method-i-2A_was] attribute methods.
|
298
|
+
def attribute_was(attr_name)
|
184
299
|
mutations_from_database.original_value(attr_name.to_s)
|
185
300
|
end
|
186
301
|
|
187
|
-
# Dispatch target for
|
188
|
-
def attribute_previously_changed?(attr_name, **options)
|
302
|
+
# Dispatch target for {*_previously_changed}[rdoc-label:method-i-2A_previously_changed-3F] attribute methods.
|
303
|
+
def attribute_previously_changed?(attr_name, **options)
|
189
304
|
mutations_before_last_save.changed?(attr_name.to_s, **options)
|
190
305
|
end
|
191
306
|
|
192
|
-
# Dispatch target for
|
193
|
-
def attribute_previously_was(attr_name)
|
307
|
+
# Dispatch target for {*_previously_was}[rdoc-label:method-i-2A_previously_was] attribute methods.
|
308
|
+
def attribute_previously_was(attr_name)
|
194
309
|
mutations_before_last_save.original_value(attr_name.to_s)
|
195
310
|
end
|
196
311
|
|
@@ -247,6 +362,12 @@ module ActiveModel
|
|
247
362
|
end
|
248
363
|
|
249
364
|
private
|
365
|
+
def init_internals
|
366
|
+
super
|
367
|
+
@mutations_before_last_save = nil
|
368
|
+
@mutations_from_database = nil
|
369
|
+
end
|
370
|
+
|
250
371
|
def clear_attribute_change(attr_name)
|
251
372
|
mutations_from_database.forget_change(attr_name.to_s)
|
252
373
|
end
|
data/lib/active_model/error.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/class/attribute"
|
4
4
|
|
5
5
|
module ActiveModel
|
6
|
-
#
|
6
|
+
# = Active \Model \Error
|
7
7
|
#
|
8
8
|
# Represents one single error
|
9
9
|
class Error
|
@@ -121,9 +121,10 @@ module ActiveModel
|
|
121
121
|
attr_reader :attribute
|
122
122
|
# The type of error, defaults to +:invalid+ unless specified
|
123
123
|
attr_reader :type
|
124
|
-
# The raw value provided as the second parameter when calling
|
124
|
+
# The raw value provided as the second parameter when calling
|
125
|
+
# <tt>errors#add</tt>
|
125
126
|
attr_reader :raw_type
|
126
|
-
# The options provided when calling
|
127
|
+
# The options provided when calling <tt>errors#add</tt>
|
127
128
|
attr_reader :options
|
128
129
|
|
129
130
|
# Returns the error message.
|
data/lib/active_model/errors.rb
CHANGED
@@ -3,13 +3,12 @@
|
|
3
3
|
require "active_support/core_ext/array/conversions"
|
4
4
|
require "active_support/core_ext/string/inflections"
|
5
5
|
require "active_support/core_ext/object/deep_dup"
|
6
|
-
require "active_support/core_ext/string/filters"
|
7
6
|
require "active_model/error"
|
8
7
|
require "active_model/nested_error"
|
9
8
|
require "forwardable"
|
10
9
|
|
11
10
|
module ActiveModel
|
12
|
-
#
|
11
|
+
# = Active \Model \Errors
|
13
12
|
#
|
14
13
|
# Provides error related functionalities you can include in your object
|
15
14
|
# for handling error messages and interacting with Action View helpers.
|
@@ -215,7 +214,7 @@ module ActiveModel
|
|
215
214
|
|
216
215
|
# Returns a Hash that can be used as the JSON representation for this
|
217
216
|
# object. You can pass the <tt>:full_messages</tt> option. This determines
|
218
|
-
# if the
|
217
|
+
# if the JSON object should contain full messages or not (false by default).
|
219
218
|
#
|
220
219
|
# person.errors.as_json # => {:name=>["cannot be nil"]}
|
221
220
|
# person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]}
|
@@ -285,9 +284,9 @@ module ActiveModel
|
|
285
284
|
#
|
286
285
|
# person.errors.add(:name, :blank)
|
287
286
|
# person.errors.messages
|
288
|
-
# # => {:name=>["can
|
287
|
+
# # => {:name=>["can’t be blank"]}
|
289
288
|
#
|
290
|
-
# person.errors.add(:name, :too_long,
|
289
|
+
# person.errors.add(:name, :too_long, count: 25)
|
291
290
|
# person.errors.messages
|
292
291
|
# # => ["is too long (maximum is 25 characters)"]
|
293
292
|
#
|
@@ -333,12 +332,12 @@ module ActiveModel
|
|
333
332
|
#
|
334
333
|
# person.errors.add :name, :blank
|
335
334
|
# person.errors.added? :name, :blank # => true
|
336
|
-
# person.errors.added? :name, "can
|
335
|
+
# person.errors.added? :name, "can’t be blank" # => true
|
337
336
|
#
|
338
337
|
# If the error requires options, then it returns +true+ with
|
339
338
|
# the correct options, or +false+ with incorrect or missing options.
|
340
339
|
#
|
341
|
-
# person.errors.add :name, :too_long,
|
340
|
+
# person.errors.add :name, :too_long, count: 25
|
342
341
|
# person.errors.added? :name, :too_long, count: 25 # => true
|
343
342
|
# person.errors.added? :name, "is too long (maximum is 25 characters)" # => true
|
344
343
|
# person.errors.added? :name, :too_long, count: 24 # => false
|
@@ -360,7 +359,7 @@ module ActiveModel
|
|
360
359
|
# present, or +false+ otherwise. +type+ is treated the same as for +add+.
|
361
360
|
#
|
362
361
|
# person.errors.add :age
|
363
|
-
# person.errors.add :name, :too_long,
|
362
|
+
# person.errors.add :name, :too_long, count: 25
|
364
363
|
# person.errors.of_kind? :age # => true
|
365
364
|
# person.errors.of_kind? :name # => false
|
366
365
|
# person.errors.of_kind? :name, :too_long # => true
|
@@ -386,7 +385,7 @@ module ActiveModel
|
|
386
385
|
#
|
387
386
|
# person = Person.create(address: '123 First St.')
|
388
387
|
# person.errors.full_messages
|
389
|
-
# # => ["Name is too short (minimum is 5 characters)", "Name can
|
388
|
+
# # => ["Name is too short (minimum is 5 characters)", "Name can’t be blank", "Email can’t be blank"]
|
390
389
|
def full_messages
|
391
390
|
@errors.map(&:full_message)
|
392
391
|
end
|
@@ -401,7 +400,7 @@ module ActiveModel
|
|
401
400
|
#
|
402
401
|
# person = Person.create()
|
403
402
|
# person.errors.full_messages_for(:name)
|
404
|
-
# # => ["Name is too short (minimum is 5 characters)", "Name can
|
403
|
+
# # => ["Name is too short (minimum is 5 characters)", "Name can’t be blank"]
|
405
404
|
def full_messages_for(attribute)
|
406
405
|
where(attribute).map(&:full_message).freeze
|
407
406
|
end
|
@@ -415,7 +414,7 @@ module ActiveModel
|
|
415
414
|
#
|
416
415
|
# person = Person.create()
|
417
416
|
# person.errors.messages_for(:name)
|
418
|
-
# # => ["is too short (minimum is 5 characters)", "can
|
417
|
+
# # => ["is too short (minimum is 5 characters)", "can’t be blank"]
|
419
418
|
def messages_for(attribute)
|
420
419
|
where(attribute).map(&:message)
|
421
420
|
end
|
@@ -472,6 +471,8 @@ module ActiveModel
|
|
472
471
|
end
|
473
472
|
end
|
474
473
|
|
474
|
+
# = Active \Model \StrictValidationFailed
|
475
|
+
#
|
475
476
|
# Raised when a validation cannot be corrected by end users and are considered
|
476
477
|
# exceptional.
|
477
478
|
#
|
@@ -486,14 +487,18 @@ module ActiveModel
|
|
486
487
|
# person = Person.new
|
487
488
|
# person.name = nil
|
488
489
|
# person.valid?
|
489
|
-
# # => ActiveModel::StrictValidationFailed: Name can
|
490
|
+
# # => ActiveModel::StrictValidationFailed: Name can’t be blank
|
490
491
|
class StrictValidationFailed < StandardError
|
491
492
|
end
|
492
493
|
|
494
|
+
# = Active \Model \RangeError
|
495
|
+
#
|
493
496
|
# Raised when attribute values are out of range.
|
494
497
|
class RangeError < ::RangeError
|
495
498
|
end
|
496
499
|
|
500
|
+
# = Active \Model \UnknownAttributeError
|
501
|
+
#
|
497
502
|
# Raised when unknown attributes are supplied via mass assignment.
|
498
503
|
#
|
499
504
|
# class Person
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveModel
|
4
|
-
# Returns the currently loaded version of \Active \Model as a
|
4
|
+
# Returns the currently loaded version of \Active \Model as a +Gem::Version+.
|
5
5
|
def self.gem_version
|
6
6
|
Gem::Version.new VERSION::STRING
|
7
7
|
end
|
8
8
|
|
9
9
|
module VERSION
|
10
10
|
MAJOR = 7
|
11
|
-
MINOR =
|
12
|
-
TINY =
|
13
|
-
PRE = "
|
11
|
+
MINOR = 1
|
12
|
+
TINY = 0
|
13
|
+
PRE = "beta1"
|
14
14
|
|
15
15
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
16
16
|
end
|
data/lib/active_model/lint.rb
CHANGED
@@ -5,7 +5,7 @@ module ActiveModel
|
|
5
5
|
# == Active \Model \Lint \Tests
|
6
6
|
#
|
7
7
|
# You can test whether an object is compliant with the Active \Model API by
|
8
|
-
# including
|
8
|
+
# including +ActiveModel::Lint::Tests+ in your TestCase. It will
|
9
9
|
# include tests that tell you whether your object is fully compliant,
|
10
10
|
# or if not, which aspects of the API are not implemented.
|
11
11
|
#
|
@@ -10,14 +10,15 @@ en:
|
|
10
10
|
inclusion: "is not included in the list"
|
11
11
|
exclusion: "is reserved"
|
12
12
|
invalid: "is invalid"
|
13
|
-
confirmation: "doesn
|
13
|
+
confirmation: "doesn’t match %{attribute}"
|
14
14
|
accepted: "must be accepted"
|
15
|
-
empty: "can
|
16
|
-
blank: "can
|
15
|
+
empty: "can’t be empty"
|
16
|
+
blank: "can’t be blank"
|
17
17
|
present: "must be blank"
|
18
18
|
too_long:
|
19
19
|
one: "is too long (maximum is 1 character)"
|
20
20
|
other: "is too long (maximum is %{count} characters)"
|
21
|
+
password_too_long: "is too long"
|
21
22
|
too_short:
|
22
23
|
one: "is too short (minimum is 1 character)"
|
23
24
|
other: "is too short (minimum is %{count} characters)"
|
data/lib/active_model/model.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveModel
|
4
|
-
#
|
4
|
+
# = Active \Model \Basic \Model
|
5
5
|
#
|
6
6
|
# Allows implementing models similar to ActiveRecord::Base.
|
7
7
|
# Includes ActiveModel::API for the required interface for an
|
@@ -37,10 +37,34 @@ module ActiveModel
|
|
37
37
|
# person.omg # => true
|
38
38
|
#
|
39
39
|
# For more detailed information on other functionalities available, please
|
40
|
-
# refer to the specific modules included in
|
40
|
+
# refer to the specific modules included in +ActiveModel::Model+
|
41
41
|
# (see below).
|
42
42
|
module Model
|
43
43
|
extend ActiveSupport::Concern
|
44
44
|
include ActiveModel::API
|
45
|
+
include ActiveModel::Access
|
46
|
+
|
47
|
+
##
|
48
|
+
# :method: slice
|
49
|
+
#
|
50
|
+
# :call-seq: slice(*methods)
|
51
|
+
#
|
52
|
+
# Returns a hash of the given methods with their names as keys and returned
|
53
|
+
# values as values.
|
54
|
+
#
|
55
|
+
#--
|
56
|
+
# Implemented by ActiveModel::Access#slice.
|
57
|
+
|
58
|
+
##
|
59
|
+
# :method: values_at
|
60
|
+
#
|
61
|
+
# :call-seq: values_at(*methods)
|
62
|
+
#
|
63
|
+
# Returns an array of the values returned by the given methods.
|
64
|
+
#
|
65
|
+
#--
|
66
|
+
# Implemented by ActiveModel::Access#values_at.
|
45
67
|
end
|
68
|
+
|
69
|
+
ActiveSupport.run_load_hooks(:active_model, Model)
|
46
70
|
end
|
data/lib/active_model/naming.rb
CHANGED
@@ -195,18 +195,15 @@ module ActiveModel
|
|
195
195
|
#
|
196
196
|
# Specify +options+ with additional translating options.
|
197
197
|
def human(options = {})
|
198
|
-
return @human
|
199
|
-
@klass.respond_to?(:i18n_scope)
|
200
|
-
|
201
|
-
defaults = @klass.lookup_ancestors.map do |klass|
|
202
|
-
klass.model_name.i18n_key
|
203
|
-
end
|
198
|
+
return @human if i18n_keys.empty? || i18n_scope.empty?
|
204
199
|
|
200
|
+
key, *defaults = i18n_keys
|
205
201
|
defaults << options[:default] if options[:default]
|
206
|
-
defaults <<
|
202
|
+
defaults << MISSING_TRANSLATION
|
207
203
|
|
208
|
-
|
209
|
-
|
204
|
+
translation = I18n.translate(key, scope: i18n_scope, count: 1, **options, default: defaults)
|
205
|
+
translation = @human if translation == MISSING_TRANSLATION
|
206
|
+
translation
|
210
207
|
end
|
211
208
|
|
212
209
|
def uncountable?
|
@@ -214,12 +211,26 @@ module ActiveModel
|
|
214
211
|
end
|
215
212
|
|
216
213
|
private
|
214
|
+
MISSING_TRANSLATION = -(2**60) # :nodoc:
|
215
|
+
|
217
216
|
def _singularize(string)
|
218
217
|
ActiveSupport::Inflector.underscore(string).tr("/", "_")
|
219
218
|
end
|
219
|
+
|
220
|
+
def i18n_keys
|
221
|
+
@i18n_keys ||= if @klass.respond_to?(:lookup_ancestors)
|
222
|
+
@klass.lookup_ancestors.map { |klass| klass.model_name.i18n_key }
|
223
|
+
else
|
224
|
+
[]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def i18n_scope
|
229
|
+
@i18n_scope ||= @klass.respond_to?(:i18n_scope) ? [@klass.i18n_scope, :models] : []
|
230
|
+
end
|
220
231
|
end
|
221
232
|
|
222
|
-
#
|
233
|
+
# = Active \Model \Naming
|
223
234
|
#
|
224
235
|
# Creates a +model_name+ method on your object.
|
225
236
|
#
|
@@ -336,5 +347,13 @@ module ActiveModel
|
|
336
347
|
end
|
337
348
|
end
|
338
349
|
private_class_method :model_name_from_record_or_class
|
350
|
+
|
351
|
+
private
|
352
|
+
def inherited(base)
|
353
|
+
super
|
354
|
+
base.class_eval do
|
355
|
+
@_model_name = nil
|
356
|
+
end
|
357
|
+
end
|
339
358
|
end
|
340
359
|
end
|
data/lib/active_model/railtie.rb
CHANGED
@@ -9,6 +9,10 @@ module ActiveModel
|
|
9
9
|
|
10
10
|
config.active_model = ActiveSupport::OrderedOptions.new
|
11
11
|
|
12
|
+
initializer "active_model.deprecator", before: :load_environment_config do |app|
|
13
|
+
app.deprecators[:active_model] = ActiveModel.deprecator
|
14
|
+
end
|
15
|
+
|
12
16
|
initializer "active_model.secure_password" do
|
13
17
|
ActiveModel::SecurePassword.min_cost = Rails.env.test?
|
14
18
|
end
|