activemodel 3.2.22.5 → 4.0.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 +85 -64
- data/MIT-LICENSE +1 -1
- data/README.rdoc +61 -24
- data/lib/active_model.rb +21 -11
- data/lib/active_model/attribute_methods.rb +150 -125
- data/lib/active_model/callbacks.rb +49 -34
- data/lib/active_model/conversion.rb +39 -19
- data/lib/active_model/deprecated_mass_assignment_security.rb +21 -0
- data/lib/active_model/dirty.rb +48 -32
- data/lib/active_model/errors.rb +176 -88
- data/lib/active_model/forbidden_attributes_protection.rb +27 -0
- data/lib/active_model/lint.rb +42 -55
- data/lib/active_model/locale/en.yml +3 -1
- data/lib/active_model/model.rb +97 -0
- data/lib/active_model/naming.rb +191 -51
- data/lib/active_model/railtie.rb +11 -1
- data/lib/active_model/secure_password.rb +55 -25
- data/lib/active_model/serialization.rb +51 -27
- data/lib/active_model/serializers/json.rb +83 -46
- data/lib/active_model/serializers/xml.rb +46 -12
- data/lib/active_model/test_case.rb +0 -12
- data/lib/active_model/translation.rb +9 -10
- data/lib/active_model/validations.rb +154 -52
- data/lib/active_model/validations/absence.rb +31 -0
- data/lib/active_model/validations/acceptance.rb +10 -22
- data/lib/active_model/validations/callbacks.rb +78 -25
- data/lib/active_model/validations/clusivity.rb +41 -0
- data/lib/active_model/validations/confirmation.rb +13 -23
- data/lib/active_model/validations/exclusion.rb +26 -55
- data/lib/active_model/validations/format.rb +44 -34
- data/lib/active_model/validations/inclusion.rb +22 -52
- data/lib/active_model/validations/length.rb +48 -49
- data/lib/active_model/validations/numericality.rb +30 -32
- data/lib/active_model/validations/presence.rb +12 -22
- data/lib/active_model/validations/validates.rb +68 -36
- data/lib/active_model/validations/with.rb +28 -23
- data/lib/active_model/validator.rb +22 -22
- data/lib/active_model/version.rb +4 -4
- metadata +23 -24
- data/lib/active_model/mass_assignment_security.rb +0 -237
- data/lib/active_model/mass_assignment_security/permission_set.rb +0 -40
- data/lib/active_model/mass_assignment_security/sanitizer.rb +0 -59
- data/lib/active_model/observer_array.rb +0 -147
- data/lib/active_model/observing.rb +0 -252
@@ -1,34 +1,40 @@
|
|
1
|
-
require '
|
2
|
-
require 'active_support/core_ext/class/attribute'
|
3
|
-
require 'active_support/deprecation'
|
1
|
+
require 'thread_safe'
|
4
2
|
|
5
3
|
module ActiveModel
|
4
|
+
# Raised when an attribute is not defined.
|
5
|
+
#
|
6
|
+
# class User < ActiveRecord::Base
|
7
|
+
# has_many :pets
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# user = User.first
|
11
|
+
# user.pets.select(:id).first.user_id
|
12
|
+
# # => ActiveModel::MissingAttributeError: missing attribute: user_id
|
6
13
|
class MissingAttributeError < NoMethodError
|
7
14
|
end
|
8
|
-
# == Active Model Attribute Methods
|
15
|
+
# == Active \Model Attribute Methods
|
9
16
|
#
|
10
|
-
# <tt>ActiveModel::AttributeMethods</tt> provides a way to add prefixes and
|
11
|
-
# to your methods as well as handling the creation of Active Record
|
12
|
-
# such as +table_name+.
|
17
|
+
# <tt>ActiveModel::AttributeMethods</tt> provides a way to add prefixes and
|
18
|
+
# suffixes to your methods as well as handling the creation of Active Record
|
19
|
+
# like class methods such as +table_name+.
|
13
20
|
#
|
14
21
|
# The requirements to implement ActiveModel::AttributeMethods are to:
|
15
22
|
#
|
16
|
-
# * <tt>include ActiveModel::AttributeMethods</tt> in your object
|
23
|
+
# * <tt>include ActiveModel::AttributeMethods</tt> in your object.
|
17
24
|
# * Call each Attribute Method module method you want to add, such as
|
18
|
-
# attribute_method_suffix or attribute_method_prefix
|
19
|
-
# * Call
|
20
|
-
#
|
21
|
-
# * Define the various generic +_attribute+ methods that you have declared
|
25
|
+
# +attribute_method_suffix+ or +attribute_method_prefix+.
|
26
|
+
# * Call +define_attribute_methods+ after the other methods are called.
|
27
|
+
# * Define the various generic +_attribute+ methods that you have declared.
|
22
28
|
#
|
23
29
|
# A minimal implementation could be:
|
24
30
|
#
|
25
31
|
# class Person
|
26
32
|
# include ActiveModel::AttributeMethods
|
27
33
|
#
|
28
|
-
# attribute_method_affix :
|
34
|
+
# attribute_method_affix prefix: 'reset_', suffix: '_to_default!'
|
29
35
|
# attribute_method_suffix '_contrived?'
|
30
36
|
# attribute_method_prefix 'clear_'
|
31
|
-
# define_attribute_methods
|
37
|
+
# define_attribute_methods :name
|
32
38
|
#
|
33
39
|
# attr_accessor :name
|
34
40
|
#
|
@@ -43,17 +49,16 @@ module ActiveModel
|
|
43
49
|
# end
|
44
50
|
#
|
45
51
|
# def reset_attribute_to_default!(attr)
|
46
|
-
# send("#{attr}=",
|
52
|
+
# send("#{attr}=", 'Default Name')
|
47
53
|
# end
|
48
54
|
# end
|
49
55
|
#
|
50
56
|
# Note that whenever you include ActiveModel::AttributeMethods in your class,
|
51
|
-
# it requires you to implement an
|
57
|
+
# it requires you to implement an +attributes+ method which returns a hash
|
52
58
|
# with each attribute name in your model as hash key and the attribute value as
|
53
59
|
# hash value.
|
54
60
|
#
|
55
61
|
# Hash keys must be strings.
|
56
|
-
#
|
57
62
|
module AttributeMethods
|
58
63
|
extend ActiveSupport::Concern
|
59
64
|
|
@@ -61,52 +66,12 @@ module ActiveModel
|
|
61
66
|
CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
|
62
67
|
|
63
68
|
included do
|
64
|
-
class_attribute :attribute_method_matchers, :
|
69
|
+
class_attribute :attribute_aliases, :attribute_method_matchers, instance_writer: false
|
70
|
+
self.attribute_aliases = {}
|
65
71
|
self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new]
|
66
72
|
end
|
67
73
|
|
68
74
|
module ClassMethods
|
69
|
-
def define_attr_method(name, value=nil, deprecation_warning = true, &block) #:nodoc:
|
70
|
-
# This deprecation_warning param is for internal use so that we can silence
|
71
|
-
# the warning from Active Record, because we are implementing more specific
|
72
|
-
# messages there instead.
|
73
|
-
#
|
74
|
-
# It doesn't apply to the original_#{name} method as we want to warn if
|
75
|
-
# people are calling that regardless.
|
76
|
-
if deprecation_warning
|
77
|
-
ActiveSupport::Deprecation.warn("define_attr_method is deprecated and will be removed without replacement.")
|
78
|
-
end
|
79
|
-
|
80
|
-
sing = singleton_class
|
81
|
-
sing.class_eval <<-eorb, __FILE__, __LINE__ + 1
|
82
|
-
remove_possible_method :'original_#{name}'
|
83
|
-
remove_possible_method :'_original_#{name}'
|
84
|
-
alias_method :'_original_#{name}', :'#{name}'
|
85
|
-
define_method :'original_#{name}' do
|
86
|
-
ActiveSupport::Deprecation.warn(
|
87
|
-
"This method is generated by ActiveModel::AttributeMethods::ClassMethods#define_attr_method, " \
|
88
|
-
"which is deprecated and will be removed."
|
89
|
-
)
|
90
|
-
send(:'_original_#{name}')
|
91
|
-
end
|
92
|
-
eorb
|
93
|
-
if block_given?
|
94
|
-
sing.send :define_method, name, &block
|
95
|
-
else
|
96
|
-
# If we can compile the method name, do it. Otherwise use define_method.
|
97
|
-
# This is an important *optimization*, please don't change it. define_method
|
98
|
-
# has slower dispatch and consumes more memory.
|
99
|
-
if name =~ NAME_COMPILABLE_REGEXP
|
100
|
-
sing.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
101
|
-
def #{name}; #{value.nil? ? 'nil' : value.to_s.inspect}; end
|
102
|
-
RUBY
|
103
|
-
else
|
104
|
-
value = value.to_s if value
|
105
|
-
sing.send(:define_method, name) { value }
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
75
|
# Declares a method available for all attributes with the given prefix.
|
111
76
|
# Uses +method_missing+ and <tt>respond_to?</tt> to rewrite the method.
|
112
77
|
#
|
@@ -119,14 +84,12 @@ module ActiveModel
|
|
119
84
|
# An instance method <tt>#{prefix}attribute</tt> must exist and accept
|
120
85
|
# at least the +attr+ argument.
|
121
86
|
#
|
122
|
-
# For example:
|
123
|
-
#
|
124
87
|
# class Person
|
125
|
-
#
|
126
88
|
# include ActiveModel::AttributeMethods
|
89
|
+
#
|
127
90
|
# attr_accessor :name
|
128
91
|
# attribute_method_prefix 'clear_'
|
129
|
-
# define_attribute_methods
|
92
|
+
# define_attribute_methods :name
|
130
93
|
#
|
131
94
|
# private
|
132
95
|
#
|
@@ -136,12 +99,12 @@ module ActiveModel
|
|
136
99
|
# end
|
137
100
|
#
|
138
101
|
# person = Person.new
|
139
|
-
# person.name =
|
102
|
+
# person.name = 'Bob'
|
140
103
|
# person.name # => "Bob"
|
141
104
|
# person.clear_name
|
142
105
|
# person.name # => nil
|
143
106
|
def attribute_method_prefix(*prefixes)
|
144
|
-
self.attribute_method_matchers += prefixes.map { |prefix| AttributeMethodMatcher.new :
|
107
|
+
self.attribute_method_matchers += prefixes.map! { |prefix| AttributeMethodMatcher.new prefix: prefix }
|
145
108
|
undefine_attribute_methods
|
146
109
|
end
|
147
110
|
|
@@ -154,17 +117,15 @@ module ActiveModel
|
|
154
117
|
#
|
155
118
|
# attribute#{suffix}(#{attr}, *args, &block)
|
156
119
|
#
|
157
|
-
# An <tt>attribute#{suffix}</tt> instance method must exist and accept at
|
158
|
-
# the +attr+ argument.
|
159
|
-
#
|
160
|
-
# For example:
|
120
|
+
# An <tt>attribute#{suffix}</tt> instance method must exist and accept at
|
121
|
+
# least the +attr+ argument.
|
161
122
|
#
|
162
123
|
# class Person
|
163
|
-
#
|
164
124
|
# include ActiveModel::AttributeMethods
|
125
|
+
#
|
165
126
|
# attr_accessor :name
|
166
127
|
# attribute_method_suffix '_short?'
|
167
|
-
# define_attribute_methods
|
128
|
+
# define_attribute_methods :name
|
168
129
|
#
|
169
130
|
# private
|
170
131
|
#
|
@@ -174,11 +135,11 @@ module ActiveModel
|
|
174
135
|
# end
|
175
136
|
#
|
176
137
|
# person = Person.new
|
177
|
-
# person.name =
|
138
|
+
# person.name = 'Bob'
|
178
139
|
# person.name # => "Bob"
|
179
140
|
# person.name_short? # => true
|
180
141
|
def attribute_method_suffix(*suffixes)
|
181
|
-
self.attribute_method_matchers += suffixes.map { |suffix| AttributeMethodMatcher.new :
|
142
|
+
self.attribute_method_matchers += suffixes.map! { |suffix| AttributeMethodMatcher.new suffix: suffix }
|
182
143
|
undefine_attribute_methods
|
183
144
|
end
|
184
145
|
|
@@ -195,14 +156,12 @@ module ActiveModel
|
|
195
156
|
# An <tt>#{prefix}attribute#{suffix}</tt> instance method must exist and
|
196
157
|
# accept at least the +attr+ argument.
|
197
158
|
#
|
198
|
-
# For example:
|
199
|
-
#
|
200
159
|
# class Person
|
201
|
-
#
|
202
160
|
# include ActiveModel::AttributeMethods
|
161
|
+
#
|
203
162
|
# attr_accessor :name
|
204
|
-
# attribute_method_affix :
|
205
|
-
# define_attribute_methods
|
163
|
+
# attribute_method_affix prefix: 'reset_', suffix: '_to_default!'
|
164
|
+
# define_attribute_methods :name
|
206
165
|
#
|
207
166
|
# private
|
208
167
|
#
|
@@ -216,35 +175,61 @@ module ActiveModel
|
|
216
175
|
# person.reset_name_to_default!
|
217
176
|
# person.name # => 'Gemma'
|
218
177
|
def attribute_method_affix(*affixes)
|
219
|
-
self.attribute_method_matchers += affixes.map { |affix| AttributeMethodMatcher.new :
|
178
|
+
self.attribute_method_matchers += affixes.map! { |affix| AttributeMethodMatcher.new prefix: affix[:prefix], suffix: affix[:suffix] }
|
220
179
|
undefine_attribute_methods
|
221
180
|
end
|
222
181
|
|
182
|
+
|
183
|
+
# Allows you to make aliases for attributes.
|
184
|
+
#
|
185
|
+
# class Person
|
186
|
+
# include ActiveModel::AttributeMethods
|
187
|
+
#
|
188
|
+
# attr_accessor :name
|
189
|
+
# attribute_method_suffix '_short?'
|
190
|
+
# define_attribute_methods :name
|
191
|
+
#
|
192
|
+
# alias_attribute :nickname, :name
|
193
|
+
#
|
194
|
+
# private
|
195
|
+
#
|
196
|
+
# def attribute_short?(attr)
|
197
|
+
# send(attr).length < 5
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# person = Person.new
|
202
|
+
# person.name = 'Bob'
|
203
|
+
# person.name # => "Bob"
|
204
|
+
# person.nickname # => "Bob"
|
205
|
+
# person.name_short? # => true
|
206
|
+
# person.nickname_short? # => true
|
223
207
|
def alias_attribute(new_name, old_name)
|
208
|
+
self.attribute_aliases = attribute_aliases.merge(new_name.to_s => old_name.to_s)
|
224
209
|
attribute_method_matchers.each do |matcher|
|
225
210
|
matcher_new = matcher.method_name(new_name).to_s
|
226
211
|
matcher_old = matcher.method_name(old_name).to_s
|
227
|
-
|
212
|
+
define_proxy_call false, self, matcher_new, matcher_old
|
228
213
|
end
|
229
214
|
end
|
230
215
|
|
231
216
|
# Declares the attributes that should be prefixed and suffixed by
|
232
217
|
# ActiveModel::AttributeMethods.
|
233
218
|
#
|
234
|
-
# To use, pass
|
235
|
-
#
|
236
|
-
#
|
219
|
+
# To use, pass attribute names (as strings or symbols), be sure to declare
|
220
|
+
# +define_attribute_methods+ after you define any prefix, suffix or affix
|
221
|
+
# methods, or they will not hook in.
|
237
222
|
#
|
238
223
|
# class Person
|
239
|
-
#
|
240
224
|
# include ActiveModel::AttributeMethods
|
225
|
+
#
|
241
226
|
# attr_accessor :name, :age, :address
|
242
227
|
# attribute_method_prefix 'clear_'
|
243
228
|
#
|
244
229
|
# # Call to define_attribute_methods must appear after the
|
245
230
|
# # attribute_method_prefix, attribute_method_suffix or
|
246
231
|
# # attribute_method_affix declares.
|
247
|
-
# define_attribute_methods
|
232
|
+
# define_attribute_methods :name, :age, :address
|
248
233
|
#
|
249
234
|
# private
|
250
235
|
#
|
@@ -252,10 +237,39 @@ module ActiveModel
|
|
252
237
|
# ...
|
253
238
|
# end
|
254
239
|
# end
|
255
|
-
def define_attribute_methods(attr_names)
|
256
|
-
attr_names.each { |attr_name| define_attribute_method(attr_name) }
|
240
|
+
def define_attribute_methods(*attr_names)
|
241
|
+
attr_names.flatten.each { |attr_name| define_attribute_method(attr_name) }
|
257
242
|
end
|
258
243
|
|
244
|
+
# Declares an attribute that should be prefixed and suffixed by
|
245
|
+
# ActiveModel::AttributeMethods.
|
246
|
+
#
|
247
|
+
# To use, pass an attribute name (as string or symbol), be sure to declare
|
248
|
+
# +define_attribute_method+ after you define any prefix, suffix or affix
|
249
|
+
# method, or they will not hook in.
|
250
|
+
#
|
251
|
+
# class Person
|
252
|
+
# include ActiveModel::AttributeMethods
|
253
|
+
#
|
254
|
+
# attr_accessor :name
|
255
|
+
# attribute_method_suffix '_short?'
|
256
|
+
#
|
257
|
+
# # Call to define_attribute_method must appear after the
|
258
|
+
# # attribute_method_prefix, attribute_method_suffix or
|
259
|
+
# # attribute_method_affix declares.
|
260
|
+
# define_attribute_method :name
|
261
|
+
#
|
262
|
+
# private
|
263
|
+
#
|
264
|
+
# def attribute_short?(attr)
|
265
|
+
# send(attr).length < 5
|
266
|
+
# end
|
267
|
+
# end
|
268
|
+
#
|
269
|
+
# person = Person.new
|
270
|
+
# person.name = 'Bob'
|
271
|
+
# person.name # => "Bob"
|
272
|
+
# person.name_short? # => true
|
259
273
|
def define_attribute_method(attr_name)
|
260
274
|
attribute_method_matchers.each do |matcher|
|
261
275
|
method_name = matcher.method_name(attr_name)
|
@@ -266,14 +280,36 @@ module ActiveModel
|
|
266
280
|
if respond_to?(generate_method, true)
|
267
281
|
send(generate_method, attr_name)
|
268
282
|
else
|
269
|
-
|
283
|
+
define_proxy_call true, generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s
|
270
284
|
end
|
271
285
|
end
|
272
286
|
end
|
273
287
|
attribute_method_matchers_cache.clear
|
274
288
|
end
|
275
289
|
|
276
|
-
# Removes all the previously dynamically defined methods from the class
|
290
|
+
# Removes all the previously dynamically defined methods from the class.
|
291
|
+
#
|
292
|
+
# class Person
|
293
|
+
# include ActiveModel::AttributeMethods
|
294
|
+
#
|
295
|
+
# attr_accessor :name
|
296
|
+
# attribute_method_suffix '_short?'
|
297
|
+
# define_attribute_method :name
|
298
|
+
#
|
299
|
+
# private
|
300
|
+
#
|
301
|
+
# def attribute_short?(attr)
|
302
|
+
# send(attr).length < 5
|
303
|
+
# end
|
304
|
+
# end
|
305
|
+
#
|
306
|
+
# person = Person.new
|
307
|
+
# person.name = 'Bob'
|
308
|
+
# person.name_short? # => true
|
309
|
+
#
|
310
|
+
# Person.undefine_attribute_methods
|
311
|
+
#
|
312
|
+
# person.name_short? # => NoMethodError
|
277
313
|
def undefine_attribute_methods
|
278
314
|
generated_attribute_methods.module_eval do
|
279
315
|
instance_methods.each { |m| undef_method(m) }
|
@@ -283,15 +319,11 @@ module ActiveModel
|
|
283
319
|
|
284
320
|
# Returns true if the attribute methods defined have been generated.
|
285
321
|
def generated_attribute_methods #:nodoc:
|
286
|
-
@generated_attribute_methods ||=
|
287
|
-
mod = Module.new
|
288
|
-
include mod
|
289
|
-
mod
|
290
|
-
end
|
322
|
+
@generated_attribute_methods ||= Module.new.tap { |mod| include mod }
|
291
323
|
end
|
292
324
|
|
293
325
|
protected
|
294
|
-
def instance_method_already_implemented?(method_name)
|
326
|
+
def instance_method_already_implemented?(method_name) #:nodoc:
|
295
327
|
generated_attribute_methods.method_defined?(method_name)
|
296
328
|
end
|
297
329
|
|
@@ -306,38 +338,36 @@ module ActiveModel
|
|
306
338
|
# significantly (in our case our test suite finishes 10% faster with
|
307
339
|
# this cache).
|
308
340
|
def attribute_method_matchers_cache #:nodoc:
|
309
|
-
@attribute_method_matchers_cache ||=
|
341
|
+
@attribute_method_matchers_cache ||= ThreadSafe::Cache.new(:initial_capacity => 4)
|
310
342
|
end
|
311
343
|
|
312
344
|
def attribute_method_matcher(method_name) #:nodoc:
|
313
|
-
|
314
|
-
attribute_method_matchers_cache[method_name]
|
315
|
-
else
|
345
|
+
attribute_method_matchers_cache.compute_if_absent(method_name) do
|
316
346
|
# Must try to match prefixes/suffixes first, or else the matcher with no prefix/suffix
|
317
347
|
# will match every time.
|
318
348
|
matchers = attribute_method_matchers.partition(&:plain?).reverse.flatten(1)
|
319
349
|
match = nil
|
320
350
|
matchers.detect { |method| match = method.match(method_name) }
|
321
|
-
|
351
|
+
match
|
322
352
|
end
|
323
353
|
end
|
324
354
|
|
325
355
|
# Define a method `name` in `mod` that dispatches to `send`
|
326
356
|
# using the given `extra` args. This fallbacks `define_method`
|
327
357
|
# and `send` if the given names cannot be compiled.
|
328
|
-
def
|
329
|
-
if name =~ NAME_COMPILABLE_REGEXP
|
330
|
-
|
358
|
+
def define_proxy_call(include_private, mod, name, send, *extra) #:nodoc:
|
359
|
+
defn = if name =~ NAME_COMPILABLE_REGEXP
|
360
|
+
"def #{name}(*args)"
|
331
361
|
else
|
332
|
-
|
362
|
+
"define_method(:'#{name}') do |*args|"
|
333
363
|
end
|
334
364
|
|
335
|
-
extra = (extra.map(&:inspect) << "*args").join(", ")
|
365
|
+
extra = (extra.map!(&:inspect) << "*args").join(", ")
|
336
366
|
|
337
|
-
if send =~ CALL_COMPILABLE_REGEXP
|
338
|
-
|
367
|
+
target = if send =~ CALL_COMPILABLE_REGEXP
|
368
|
+
"#{"self." unless include_private}#{send}(#{extra})"
|
339
369
|
else
|
340
|
-
|
370
|
+
"send(:'#{send}', #{extra})"
|
341
371
|
end
|
342
372
|
|
343
373
|
mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -347,34 +377,29 @@ module ActiveModel
|
|
347
377
|
RUBY
|
348
378
|
end
|
349
379
|
|
350
|
-
class AttributeMethodMatcher
|
380
|
+
class AttributeMethodMatcher #:nodoc:
|
351
381
|
attr_reader :prefix, :suffix, :method_missing_target
|
352
382
|
|
353
383
|
AttributeMethodMatch = Struct.new(:target, :attr_name, :method_name)
|
354
384
|
|
355
385
|
def initialize(options = {})
|
356
|
-
options.symbolize_keys!
|
357
|
-
|
358
386
|
if options[:prefix] == '' || options[:suffix] == ''
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
)
|
387
|
+
message = "Specifying an empty prefix/suffix for an attribute method is no longer " \
|
388
|
+
"necessary. If the un-prefixed/suffixed version of the method has not been " \
|
389
|
+
"defined when `define_attribute_methods` is called, it will be defined " \
|
390
|
+
"automatically."
|
391
|
+
ActiveSupport::Deprecation.warn message
|
365
392
|
end
|
366
393
|
|
367
|
-
@prefix, @suffix = options
|
368
|
-
@regex =
|
394
|
+
@prefix, @suffix = options.fetch(:prefix, ''), options.fetch(:suffix, '')
|
395
|
+
@regex = /^(?:#{Regexp.escape(@prefix)})(.*)(?:#{Regexp.escape(@suffix)})$/
|
369
396
|
@method_missing_target = "#{@prefix}attribute#{@suffix}"
|
370
397
|
@method_name = "#{prefix}%s#{suffix}"
|
371
398
|
end
|
372
399
|
|
373
400
|
def match(method_name)
|
374
401
|
if @regex =~ method_name
|
375
|
-
AttributeMethodMatch.new(method_missing_target, $
|
376
|
-
else
|
377
|
-
nil
|
402
|
+
AttributeMethodMatch.new(method_missing_target, $1, method_name)
|
378
403
|
end
|
379
404
|
end
|
380
405
|
|
@@ -411,7 +436,7 @@ module ActiveModel
|
|
411
436
|
# attribute_missing is like method_missing, but for attributes. When method_missing is
|
412
437
|
# called we check to see if there is a matching attribute method. If so, we call
|
413
438
|
# attribute_missing to dispatch the attribute. This method can be overloaded to
|
414
|
-
#
|
439
|
+
# customize the behavior.
|
415
440
|
def attribute_missing(match, *args, &block)
|
416
441
|
__send__(match.target, match.attr_name, *args, &block)
|
417
442
|
end
|
@@ -433,7 +458,7 @@ module ActiveModel
|
|
433
458
|
end
|
434
459
|
|
435
460
|
protected
|
436
|
-
def attribute_method?(attr_name)
|
461
|
+
def attribute_method?(attr_name) #:nodoc:
|
437
462
|
respond_to_without_attributes?(:attributes) && attributes.include?(attr_name)
|
438
463
|
end
|
439
464
|
|
@@ -442,7 +467,7 @@ module ActiveModel
|
|
442
467
|
# The struct's attributes are prefix, base and suffix.
|
443
468
|
def match_attribute_method?(method_name)
|
444
469
|
match = self.class.send(:attribute_method_matcher, method_name)
|
445
|
-
match && attribute_method?(match.attr_name)
|
470
|
+
match if match && attribute_method?(match.attr_name)
|
446
471
|
end
|
447
472
|
|
448
473
|
def missing_attribute(attr_name, stack)
|