activemodel 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activemodel might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +84 -93
- data/MIT-LICENSE +1 -1
- data/README.rdoc +8 -16
- data/lib/active_model.rb +3 -2
- data/lib/active_model/attribute_assignment.rb +52 -0
- data/lib/active_model/attribute_methods.rb +16 -16
- data/lib/active_model/callbacks.rb +3 -3
- data/lib/active_model/conversion.rb +3 -3
- data/lib/active_model/dirty.rb +34 -35
- data/lib/active_model/errors.rb +117 -63
- data/lib/active_model/forbidden_attributes_protection.rb +3 -2
- data/lib/active_model/gem_version.rb +5 -5
- data/lib/active_model/lint.rb +32 -28
- data/lib/active_model/locale/en.yml +2 -1
- data/lib/active_model/model.rb +3 -4
- data/lib/active_model/naming.rb +5 -4
- data/lib/active_model/secure_password.rb +2 -9
- data/lib/active_model/serialization.rb +36 -9
- data/lib/active_model/serializers/json.rb +1 -1
- data/lib/active_model/type.rb +59 -0
- data/lib/active_model/type/big_integer.rb +13 -0
- data/lib/active_model/type/binary.rb +50 -0
- data/lib/active_model/type/boolean.rb +21 -0
- data/lib/active_model/type/date.rb +50 -0
- data/lib/active_model/type/date_time.rb +44 -0
- data/lib/active_model/type/decimal.rb +52 -0
- data/lib/active_model/type/decimal_without_scale.rb +11 -0
- data/lib/active_model/type/float.rb +25 -0
- data/lib/active_model/type/helpers.rb +4 -0
- data/lib/active_model/type/helpers/accepts_multiparameter_time.rb +35 -0
- data/lib/active_model/type/helpers/mutable.rb +18 -0
- data/lib/active_model/type/helpers/numeric.rb +34 -0
- data/lib/active_model/type/helpers/time_value.rb +77 -0
- data/lib/active_model/type/immutable_string.rb +29 -0
- data/lib/active_model/type/integer.rb +66 -0
- data/lib/active_model/type/registry.rb +64 -0
- data/lib/active_model/type/string.rb +19 -0
- data/lib/active_model/type/text.rb +11 -0
- data/lib/active_model/type/time.rb +46 -0
- data/lib/active_model/type/unsigned_integer.rb +15 -0
- data/lib/active_model/type/value.rb +112 -0
- data/lib/active_model/validations.rb +35 -3
- data/lib/active_model/validations/absence.rb +1 -1
- data/lib/active_model/validations/acceptance.rb +61 -9
- data/lib/active_model/validations/callbacks.rb +3 -3
- data/lib/active_model/validations/confirmation.rb +16 -4
- data/lib/active_model/validations/exclusion.rb +3 -1
- data/lib/active_model/validations/format.rb +1 -1
- data/lib/active_model/validations/helper_methods.rb +13 -0
- data/lib/active_model/validations/inclusion.rb +3 -3
- data/lib/active_model/validations/length.rb +48 -17
- data/lib/active_model/validations/numericality.rb +12 -13
- data/lib/active_model/validations/validates.rb +1 -1
- data/lib/active_model/validations/with.rb +0 -10
- data/lib/active_model/validator.rb +6 -2
- data/lib/active_model/version.rb +1 -1
- metadata +34 -9
- data/lib/active_model/serializers/xml.rb +0 -238
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6ac74cf489726c9ec6fe5932520215ccffd304a8
|
4
|
+
data.tar.gz: 415b347104e566577357cd976b129a43cd2cf698
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9ecb240f9de03285920ca4fc1e3d687049afcfb73ed7108a4dd18068776d43ddd9d894cb9a66419df758e175475346f059cb0d932077214fe63830c1d28eda7
|
7
|
+
data.tar.gz: 243ad2ee7768e1773f0b31a3d8cc714e17c2c0aab54d1907e1db7d1136a3b718fb58fc0e5877bce2589d9d3de16d0011a046da9b1d68bf8bc970cdc4fbb36f7b
|
data/CHANGELOG.md
CHANGED
@@ -1,143 +1,134 @@
|
|
1
|
-
## Rails
|
1
|
+
## Rails 5.0.0.beta1 (December 18, 2015) ##
|
2
2
|
|
3
3
|
* No changes.
|
4
4
|
|
5
5
|
|
6
|
-
|
6
|
+
* Validate multiple contexts on `valid?` and `invalid?` at once.
|
7
7
|
|
8
|
-
|
8
|
+
Example:
|
9
9
|
|
10
|
+
class Person
|
11
|
+
include ActiveModel::Validations
|
10
12
|
|
11
|
-
|
13
|
+
attr_reader :name, :title
|
14
|
+
validates_presence_of :name, on: :create
|
15
|
+
validates_presence_of :title, on: :update
|
16
|
+
end
|
12
17
|
|
13
|
-
|
18
|
+
person = Person.new
|
19
|
+
person.valid?([:create, :update]) # => false
|
20
|
+
person.errors.messages # => {:name=>["can't be blank"], :title=>["can't be blank"]}
|
14
21
|
|
22
|
+
*Dmitry Polushkin*
|
15
23
|
|
16
|
-
|
24
|
+
* Add case_sensitive option for confirmation validator in models.
|
17
25
|
|
18
|
-
*
|
26
|
+
*Akshat Sharma*
|
19
27
|
|
28
|
+
* Ensure `method_missing` is called for methods passed to
|
29
|
+
`ActiveModel::Serialization#serializable_hash` that don't exist.
|
20
30
|
|
21
|
-
|
31
|
+
*Jay Elaraj*
|
22
32
|
|
23
|
-
*
|
33
|
+
* Remove `ActiveModel::Serializers::Xml` from core.
|
24
34
|
|
35
|
+
*Zachary Scott*
|
25
36
|
|
26
|
-
|
37
|
+
* Add `ActiveModel::Dirty#[attr_name]_previously_changed?` and
|
38
|
+
`ActiveModel::Dirty#[attr_name]_previous_change` to improve access
|
39
|
+
to recorded changes after the model has been saved.
|
27
40
|
|
28
|
-
|
41
|
+
It makes the dirty-attributes query methods consistent before and after
|
42
|
+
saving.
|
29
43
|
|
44
|
+
*Fernando Tapia Rico*
|
30
45
|
|
31
|
-
|
46
|
+
* Deprecate the `:tokenizer` option for `validates_length_of`, in favor of
|
47
|
+
plain Ruby.
|
32
48
|
|
33
|
-
*
|
49
|
+
*Sean Griffin*
|
34
50
|
|
51
|
+
* Deprecate `ActiveModel::Errors#add_on_empty` and `ActiveModel::Errors#add_on_blank`
|
52
|
+
with no replacement.
|
35
53
|
|
36
|
-
|
54
|
+
*Wojciech Wnętrzak*
|
37
55
|
|
38
|
-
*
|
56
|
+
* Deprecate `ActiveModel::Errors#get`, `ActiveModel::Errors#set` and
|
57
|
+
`ActiveModel::Errors#[]=` methods that have inconsistent behavior.
|
39
58
|
|
59
|
+
*Wojciech Wnętrzak*
|
40
60
|
|
41
|
-
|
61
|
+
* Allow symbol as values for `tokenize` of `LengthValidator`.
|
42
62
|
|
43
|
-
*
|
63
|
+
*Kensuke Naito*
|
44
64
|
|
65
|
+
* Assigning an unknown attribute key to an `ActiveModel` instance during initialization
|
66
|
+
will now raise `ActiveModel::AttributeAssignment::UnknownAttributeError` instead of
|
67
|
+
`NoMethodError`.
|
45
68
|
|
46
|
-
|
69
|
+
Example:
|
47
70
|
|
48
|
-
|
71
|
+
User.new(foo: 'some value')
|
72
|
+
# => ActiveModel::AttributeAssignment::UnknownAttributeError: unknown attribute 'foo' for User.
|
49
73
|
|
74
|
+
*Eugene Gilburg*
|
50
75
|
|
51
|
-
|
76
|
+
* Extracted `ActiveRecord::AttributeAssignment` to `ActiveModel::AttributeAssignment`
|
77
|
+
allowing to use it for any object as an includable module.
|
52
78
|
|
53
|
-
|
79
|
+
Example:
|
54
80
|
|
81
|
+
class Cat
|
82
|
+
include ActiveModel::AttributeAssignment
|
83
|
+
attr_accessor :name, :status
|
84
|
+
end
|
55
85
|
|
56
|
-
|
86
|
+
cat = Cat.new
|
87
|
+
cat.assign_attributes(name: "Gorby", status: "yawning")
|
88
|
+
cat.name # => 'Gorby'
|
89
|
+
cat.status # => 'yawning'
|
90
|
+
cat.assign_attributes(status: "sleeping")
|
91
|
+
cat.name # => 'Gorby'
|
92
|
+
cat.status # => 'sleeping'
|
57
93
|
|
58
|
-
*
|
94
|
+
*Bogdan Gusiev*
|
59
95
|
|
96
|
+
* Add `ActiveModel::Errors#details`
|
60
97
|
|
61
|
-
|
98
|
+
To be able to return type of used validator, one can now call `details`
|
99
|
+
on errors instance.
|
62
100
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
## Rails 4.2.3 (June 25, 2015) ##
|
67
|
-
|
68
|
-
* No Changes *
|
69
|
-
|
70
|
-
|
71
|
-
## Rails 4.2.2 (June 16, 2015) ##
|
72
|
-
|
73
|
-
* No Changes *
|
74
|
-
|
75
|
-
|
76
|
-
## Rails 4.2.1 (March 19, 2015) ##
|
77
|
-
|
78
|
-
* No changes.
|
101
|
+
Example:
|
79
102
|
|
103
|
+
class User < ActiveRecord::Base
|
104
|
+
validates :name, presence: true
|
105
|
+
end
|
80
106
|
|
81
|
-
|
107
|
+
user = User.new; user.valid?; user.errors.details
|
108
|
+
=> {name: [{error: :blank}]}
|
82
109
|
|
83
|
-
*
|
110
|
+
*Wojciech Wnętrzak*
|
84
111
|
|
85
|
-
|
112
|
+
* Change validates_acceptance_of to accept true by default.
|
86
113
|
|
87
|
-
|
114
|
+
The default for validates_acceptance_of is now "1" and true.
|
115
|
+
In the past, only "1" was the default and you were required to add
|
116
|
+
accept: true.
|
88
117
|
|
89
|
-
*
|
90
|
-
|
91
|
-
Preventing, in many cases, the simple mistake of using `validate` instead of `validates`.
|
92
|
-
|
93
|
-
*Sonny Michaud*
|
94
|
-
|
95
|
-
* Deprecate `reset_#{attribute}` in favor of `restore_#{attribute}`.
|
96
|
-
|
97
|
-
These methods may cause confusion with the `reset_changes`, which has
|
98
|
-
different behaviour.
|
99
|
-
|
100
|
-
*Rafael Mendonça França*
|
101
|
-
|
102
|
-
* Deprecate `ActiveModel::Dirty#reset_changes` in favor of `#clear_changes_information`.
|
103
|
-
|
104
|
-
Method's name is causing confusion with the `reset_#{attribute}` methods.
|
105
|
-
While `reset_name` sets the value of the name attribute to previous value
|
106
|
-
`reset_changes` only discards the changes.
|
118
|
+
* Remove deprecated `ActiveModel::Dirty#reset_#{attribute}` and
|
119
|
+
`ActiveModel::Dirty#reset_changes`.
|
107
120
|
|
108
121
|
*Rafael Mendonça França*
|
109
122
|
|
110
|
-
*
|
111
|
-
the value of changed attributes to previous value.
|
112
|
-
|
113
|
-
*Igor G.*
|
114
|
-
|
115
|
-
* Allow proc and symbol as values for `only_integer` of `NumericalityValidator`
|
116
|
-
|
117
|
-
*Robin Mehner*
|
118
|
-
|
119
|
-
* `has_secure_password` now verifies that the given password is less than 72
|
120
|
-
characters if validations are enabled.
|
121
|
-
|
122
|
-
Fixes #14591.
|
123
|
-
|
124
|
-
*Akshay Vishnoi*
|
125
|
-
|
126
|
-
* Remove deprecated `Validator#setup` without replacement.
|
127
|
-
|
128
|
-
See #10716.
|
129
|
-
|
130
|
-
*Kuldeep Aggarwal*
|
131
|
-
|
132
|
-
* Add plural and singular form for length validator's default messages.
|
133
|
-
|
134
|
-
*Abd ar-Rahman Hamid*
|
135
|
-
|
136
|
-
* Introduce `validate` as an alias for `valid?`.
|
123
|
+
* Change the way in which callback chains can be halted.
|
137
124
|
|
138
|
-
|
139
|
-
|
125
|
+
The preferred method to halt a callback chain from now on is to explicitly
|
126
|
+
`throw(:abort)`.
|
127
|
+
In the past, returning `false` in an Active Model `before_` callback had
|
128
|
+
the side effect of halting the callback chain.
|
129
|
+
This is not recommended anymore and, depending on the value of the
|
130
|
+
`ActiveSupport.halt_callback_chains_on_return_false` option, will
|
131
|
+
either not work at all or display a deprecation warning.
|
140
132
|
|
141
|
-
*Henrik Nyh*
|
142
133
|
|
143
|
-
Please check [4-
|
134
|
+
Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/activemodel/CHANGELOG.md) for previous changes.
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -49,7 +49,7 @@ behavior out of the box:
|
|
49
49
|
send("#{attr}=", nil)
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
person = Person.new
|
54
54
|
person.clear_name
|
55
55
|
person.clear_age
|
@@ -132,7 +132,7 @@ behavior out of the box:
|
|
132
132
|
"Name"
|
133
133
|
end
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
person = Person.new
|
137
137
|
person.name = nil
|
138
138
|
person.validate!
|
@@ -154,8 +154,8 @@ behavior out of the box:
|
|
154
154
|
|
155
155
|
* Making objects serializable
|
156
156
|
|
157
|
-
ActiveModel::Serialization provides a standard interface for your object
|
158
|
-
to provide +to_json+
|
157
|
+
<tt>ActiveModel::Serialization</tt> provides a standard interface for your object
|
158
|
+
to provide +to_json+ serialization.
|
159
159
|
|
160
160
|
class SerialPerson
|
161
161
|
include ActiveModel::Serialization
|
@@ -177,13 +177,6 @@ behavior out of the box:
|
|
177
177
|
s = SerialPerson.new
|
178
178
|
s.to_json # => "{\"name\":null}"
|
179
179
|
|
180
|
-
class SerialPerson
|
181
|
-
include ActiveModel::Serializers::Xml
|
182
|
-
end
|
183
|
-
|
184
|
-
s = SerialPerson.new
|
185
|
-
s.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
|
186
|
-
|
187
180
|
{Learn more}[link:classes/ActiveModel/Serialization.html]
|
188
181
|
|
189
182
|
* Internationalization (i18n) support
|
@@ -216,10 +209,10 @@ behavior out of the box:
|
|
216
209
|
{Learn more}[link:classes/ActiveModel/Validations.html]
|
217
210
|
|
218
211
|
* Custom validators
|
219
|
-
|
212
|
+
|
220
213
|
class HasNameValidator < ActiveModel::Validator
|
221
214
|
def validate(record)
|
222
|
-
record.errors
|
215
|
+
record.errors.add(:name, "must exist") if record.name.blank?
|
223
216
|
end
|
224
217
|
end
|
225
218
|
|
@@ -242,11 +235,11 @@ behavior out of the box:
|
|
242
235
|
|
243
236
|
The latest version of Active Model can be installed with RubyGems:
|
244
237
|
|
245
|
-
|
238
|
+
$ gem install activemodel
|
246
239
|
|
247
240
|
Source code can be downloaded as part of the Rails project on GitHub
|
248
241
|
|
249
|
-
* https://github.com/rails/rails/tree/
|
242
|
+
* https://github.com/rails/rails/tree/master/activemodel
|
250
243
|
|
251
244
|
|
252
245
|
== License
|
@@ -269,4 +262,3 @@ Bug reports can be filed for the Ruby on Rails project here:
|
|
269
262
|
Feature requests should be discussed on the rails-core mailing list here:
|
270
263
|
|
271
264
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|
272
|
-
|
data/lib/active_model.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2004-
|
2
|
+
# Copyright (c) 2004-2015 David Heinemeier Hansson
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -28,6 +28,7 @@ require 'active_model/version'
|
|
28
28
|
module ActiveModel
|
29
29
|
extend ActiveSupport::Autoload
|
30
30
|
|
31
|
+
autoload :AttributeAssignment
|
31
32
|
autoload :AttributeMethods
|
32
33
|
autoload :BlockValidator, 'active_model/validator'
|
33
34
|
autoload :Callbacks
|
@@ -49,6 +50,7 @@ module ActiveModel
|
|
49
50
|
eager_autoload do
|
50
51
|
autoload :Errors
|
51
52
|
autoload :StrictValidationFailed, 'active_model/errors'
|
53
|
+
autoload :UnknownAttributeError, 'active_model/errors'
|
52
54
|
end
|
53
55
|
|
54
56
|
module Serializers
|
@@ -56,7 +58,6 @@ module ActiveModel
|
|
56
58
|
|
57
59
|
eager_autoload do
|
58
60
|
autoload :JSON
|
59
|
-
autoload :Xml
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
|
3
|
+
module ActiveModel
|
4
|
+
module AttributeAssignment
|
5
|
+
include ActiveModel::ForbiddenAttributesProtection
|
6
|
+
|
7
|
+
# Allows you to set all the attributes by passing in a hash of attributes with
|
8
|
+
# keys matching the attribute names.
|
9
|
+
#
|
10
|
+
# If the passed hash responds to <tt>permitted?</tt> method and the return value
|
11
|
+
# of this method is +false+ an <tt>ActiveModel::ForbiddenAttributesError</tt>
|
12
|
+
# exception is raised.
|
13
|
+
#
|
14
|
+
# class Cat
|
15
|
+
# include ActiveModel::AttributeAssignment
|
16
|
+
# attr_accessor :name, :status
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# cat = Cat.new
|
20
|
+
# cat.assign_attributes(name: "Gorby", status: "yawning")
|
21
|
+
# cat.name # => 'Gorby'
|
22
|
+
# cat.status => 'yawning'
|
23
|
+
# cat.assign_attributes(status: "sleeping")
|
24
|
+
# cat.name # => 'Gorby'
|
25
|
+
# cat.status => 'sleeping'
|
26
|
+
def assign_attributes(new_attributes)
|
27
|
+
if !new_attributes.respond_to?(:stringify_keys)
|
28
|
+
raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
|
29
|
+
end
|
30
|
+
return if new_attributes.nil? || new_attributes.empty?
|
31
|
+
|
32
|
+
attributes = new_attributes.stringify_keys
|
33
|
+
_assign_attributes(sanitize_for_mass_assignment(attributes))
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def _assign_attributes(attributes)
|
39
|
+
attributes.each do |k, v|
|
40
|
+
_assign_attribute(k, v)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def _assign_attribute(k, v)
|
45
|
+
if respond_to?("#{k}=")
|
46
|
+
public_send("#{k}=", v)
|
47
|
+
else
|
48
|
+
raise UnknownAttributeError.new(self, k)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'concurrent/map'
|
2
2
|
require 'mutex_m'
|
3
3
|
|
4
4
|
module ActiveModel
|
@@ -23,7 +23,7 @@ module ActiveModel
|
|
23
23
|
# The requirements to implement <tt>ActiveModel::AttributeMethods</tt> are to:
|
24
24
|
#
|
25
25
|
# * <tt>include ActiveModel::AttributeMethods</tt> in your class.
|
26
|
-
# * Call each of its
|
26
|
+
# * Call each of its methods you want to add, such as +attribute_method_suffix+
|
27
27
|
# or +attribute_method_prefix+.
|
28
28
|
# * Call +define_attribute_methods+ after the other methods are called.
|
29
29
|
# * Define the various generic +_attribute+ methods that you have declared.
|
@@ -225,9 +225,9 @@ module ActiveModel
|
|
225
225
|
end
|
226
226
|
|
227
227
|
# Declares the attributes that should be prefixed and suffixed by
|
228
|
-
# ActiveModel::AttributeMethods
|
228
|
+
# <tt>ActiveModel::AttributeMethods</tt>.
|
229
229
|
#
|
230
|
-
# To use, pass attribute names (as strings or symbols)
|
230
|
+
# To use, pass attribute names (as strings or symbols). Be sure to declare
|
231
231
|
# +define_attribute_methods+ after you define any prefix, suffix or affix
|
232
232
|
# methods, or they will not hook in.
|
233
233
|
#
|
@@ -239,7 +239,7 @@ module ActiveModel
|
|
239
239
|
#
|
240
240
|
# # Call to define_attribute_methods must appear after the
|
241
241
|
# # attribute_method_prefix, attribute_method_suffix or
|
242
|
-
# # attribute_method_affix
|
242
|
+
# # attribute_method_affix declarations.
|
243
243
|
# define_attribute_methods :name, :age, :address
|
244
244
|
#
|
245
245
|
# private
|
@@ -253,9 +253,9 @@ module ActiveModel
|
|
253
253
|
end
|
254
254
|
|
255
255
|
# Declares an attribute that should be prefixed and suffixed by
|
256
|
-
# ActiveModel::AttributeMethods
|
256
|
+
# <tt>ActiveModel::AttributeMethods</tt>.
|
257
257
|
#
|
258
|
-
# To use, pass an attribute name (as string or symbol)
|
258
|
+
# To use, pass an attribute name (as string or symbol). Be sure to declare
|
259
259
|
# +define_attribute_method+ after you define any prefix, suffix or affix
|
260
260
|
# method, or they will not hook in.
|
261
261
|
#
|
@@ -267,7 +267,7 @@ module ActiveModel
|
|
267
267
|
#
|
268
268
|
# # Call to define_attribute_method must appear after the
|
269
269
|
# # attribute_method_prefix, attribute_method_suffix or
|
270
|
-
# # attribute_method_affix
|
270
|
+
# # attribute_method_affix declarations.
|
271
271
|
# define_attribute_method :name
|
272
272
|
#
|
273
273
|
# private
|
@@ -342,7 +342,7 @@ module ActiveModel
|
|
342
342
|
private
|
343
343
|
# The methods +method_missing+ and +respond_to?+ of this module are
|
344
344
|
# invoked often in a typical rails, both of which invoke the method
|
345
|
-
# +
|
345
|
+
# +matched_attribute_method+. The latter method iterates through an
|
346
346
|
# array doing regular expression matches, which results in a lot of
|
347
347
|
# object creations. Most of the time it returns a +nil+ match. As the
|
348
348
|
# match result is always the same given a +method_name+, this cache is
|
@@ -350,7 +350,7 @@ module ActiveModel
|
|
350
350
|
# significantly (in our case our test suite finishes 10% faster with
|
351
351
|
# this cache).
|
352
352
|
def attribute_method_matchers_cache #:nodoc:
|
353
|
-
@attribute_method_matchers_cache ||=
|
353
|
+
@attribute_method_matchers_cache ||= Concurrent::Map.new(initial_capacity: 4)
|
354
354
|
end
|
355
355
|
|
356
356
|
def attribute_method_matchers_matching(method_name) #:nodoc:
|
@@ -363,7 +363,7 @@ module ActiveModel
|
|
363
363
|
end
|
364
364
|
|
365
365
|
# Define a method `name` in `mod` that dispatches to `send`
|
366
|
-
# using the given `extra` args. This
|
366
|
+
# using the given `extra` args. This falls back on `define_method`
|
367
367
|
# and `send` if the given names cannot be compiled.
|
368
368
|
def define_proxy_call(include_private, mod, name, send, *extra) #:nodoc:
|
369
369
|
defn = if name =~ NAME_COMPILABLE_REGEXP
|
@@ -372,7 +372,7 @@ module ActiveModel
|
|
372
372
|
"define_method(:'#{name}') do |*args|"
|
373
373
|
end
|
374
374
|
|
375
|
-
extra = (extra.map!(&:inspect) << "*args").join(", ")
|
375
|
+
extra = (extra.map!(&:inspect) << "*args").join(", ".freeze)
|
376
376
|
|
377
377
|
target = if send =~ CALL_COMPILABLE_REGEXP
|
378
378
|
"#{"self." unless include_private}#{send}(#{extra})"
|
@@ -419,7 +419,7 @@ module ActiveModel
|
|
419
419
|
# returned by <tt>attributes</tt>, as though they were first-class
|
420
420
|
# methods. So a +Person+ class with a +name+ attribute can for example use
|
421
421
|
# <tt>Person#name</tt> and <tt>Person#name=</tt> and never directly use
|
422
|
-
# the attributes hash -- except for multiple
|
422
|
+
# the attributes hash -- except for multiple assignments with
|
423
423
|
# <tt>ActiveRecord::Base#attributes=</tt>.
|
424
424
|
#
|
425
425
|
# It's also possible to instantiate related objects, so a <tt>Client</tt>
|
@@ -429,7 +429,7 @@ module ActiveModel
|
|
429
429
|
if respond_to_without_attributes?(method, true)
|
430
430
|
super
|
431
431
|
else
|
432
|
-
match =
|
432
|
+
match = matched_attribute_method(method.to_s)
|
433
433
|
match ? attribute_missing(match, *args, &block) : super
|
434
434
|
end
|
435
435
|
end
|
@@ -454,7 +454,7 @@ module ActiveModel
|
|
454
454
|
# but found among all methods. Which means that the given method is private.
|
455
455
|
false
|
456
456
|
else
|
457
|
-
!
|
457
|
+
!matched_attribute_method(method.to_s).nil?
|
458
458
|
end
|
459
459
|
end
|
460
460
|
|
@@ -466,7 +466,7 @@ module ActiveModel
|
|
466
466
|
private
|
467
467
|
# Returns a struct representing the matching attribute method.
|
468
468
|
# The struct's attributes are prefix, base and suffix.
|
469
|
-
def
|
469
|
+
def matched_attribute_method(method_name)
|
470
470
|
matches = self.class.send(:attribute_method_matchers_matching, method_name)
|
471
471
|
matches.detect { |match| attribute_method?(match.attr_name) }
|
472
472
|
end
|