activemodel 3.1.12 → 3.2.0.rc1
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.
- data/CHANGELOG.md +81 -36
- data/README.rdoc +1 -1
- data/lib/active_model/attribute_methods.rb +123 -104
- data/lib/active_model/callbacks.rb +2 -2
- data/lib/active_model/conversion.rb +26 -2
- data/lib/active_model/dirty.rb +3 -3
- data/lib/active_model/errors.rb +63 -51
- data/lib/active_model/lint.rb +12 -3
- data/lib/active_model/mass_assignment_security.rb +27 -8
- data/lib/active_model/mass_assignment_security/permission_set.rb +5 -5
- data/lib/active_model/mass_assignment_security/sanitizer.rb +42 -6
- data/lib/active_model/naming.rb +18 -10
- data/lib/active_model/observer_array.rb +3 -3
- data/lib/active_model/observing.rb +1 -2
- data/lib/active_model/secure_password.rb +2 -2
- data/lib/active_model/serialization.rb +61 -10
- data/lib/active_model/serializers/json.rb +20 -14
- data/lib/active_model/serializers/xml.rb +55 -31
- data/lib/active_model/translation.rb +15 -3
- data/lib/active_model/validations.rb +1 -1
- data/lib/active_model/validations/acceptance.rb +3 -1
- data/lib/active_model/validations/confirmation.rb +3 -1
- data/lib/active_model/validations/exclusion.rb +5 -3
- data/lib/active_model/validations/format.rb +4 -2
- data/lib/active_model/validations/inclusion.rb +5 -3
- data/lib/active_model/validations/length.rb +22 -10
- data/lib/active_model/validations/numericality.rb +4 -2
- data/lib/active_model/validations/presence.rb +5 -3
- data/lib/active_model/validations/validates.rb +15 -3
- data/lib/active_model/validations/with.rb +4 -2
- data/lib/active_model/version.rb +3 -3
- metadata +21 -28
- checksums.yaml +0 -7
data/CHANGELOG.md
CHANGED
@@ -1,71 +1,116 @@
|
|
1
|
-
## Rails 3.
|
1
|
+
## Rails 3.2.0 (unreleased) ##
|
2
2
|
|
3
|
-
*
|
4
|
-
|
3
|
+
* Deprecated `define_attr_method` in `ActiveModel::AttributeMethods`, because this only existed to
|
4
|
+
support methods like `set_table_name` in Active Record, which are themselves being deprecated.
|
5
5
|
|
6
|
-
*
|
6
|
+
*Jon Leighton*
|
7
7
|
|
8
|
-
|
8
|
+
* Add ActiveModel::Errors#added? to check if a specific error has been added *Martin Svalin*
|
9
9
|
|
10
|
-
*
|
10
|
+
* Add ability to define strict validation(with :strict => true option) that always raises exception when fails *Bogdan Gusiev*
|
11
|
+
|
12
|
+
* Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" *Grant Hutchins, Peter Jaros*
|
11
13
|
|
12
|
-
|
14
|
+
* Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior *Bogdan Gusiev*
|
15
|
+
|
16
|
+
## Rails 3.1.0 (August 30, 2011) ##
|
17
|
+
|
18
|
+
* Alternate I18n namespace lookup is no longer supported.
|
19
|
+
Instead of "activerecord.models.admins.post", do "activerecord.models.admins/post" instead *José Valim*
|
13
20
|
|
14
|
-
*
|
21
|
+
* attr_accessible and friends now accepts :as as option to specify a role *Josh Kalderimis*
|
22
|
+
|
23
|
+
* Add support for proc or lambda as an option for InclusionValidator,
|
24
|
+
ExclusionValidator, and FormatValidator *Prem Sichanugrist*
|
25
|
+
|
26
|
+
You can now supply Proc, lambda, or anything that respond to #call in those
|
27
|
+
validations, and it will be called with current record as an argument.
|
28
|
+
That given proc or lambda must returns an object which respond to #include? for
|
29
|
+
InclusionValidator and ExclusionValidator, and returns a regular expression
|
30
|
+
object for FormatValidator.
|
15
31
|
|
16
|
-
|
32
|
+
* Added ActiveModel::SecurePassword to encapsulate dead-simple password usage with BCrypt encryption and salting *DHH*
|
17
33
|
|
18
|
-
|
34
|
+
* ActiveModel::AttributeMethods allows attributes to be defined on demand *Alexander Uvarov*
|
19
35
|
|
20
|
-
|
36
|
+
* Add support for selectively enabling/disabling observers *Myron Marston*
|
21
37
|
|
22
|
-
*Carlos Antonio da Silva*
|
23
38
|
|
24
|
-
## Rails 3.
|
39
|
+
## Rails 3.0.7 (April 18, 2011) ##
|
25
40
|
|
26
41
|
* No changes.
|
27
42
|
|
28
|
-
|
43
|
+
|
44
|
+
* Rails 3.0.6 (April 5, 2011)
|
45
|
+
|
46
|
+
* Fix when database column name has some symbolic characters (e.g. Oracle CASE# VARCHAR2(20)) #5818 #6850 *Robert Pankowecki, Santiago Pastorino*
|
47
|
+
|
48
|
+
* Fix length validation for fixnums #6556 *Andriy Tyurnikov*
|
49
|
+
|
50
|
+
* Fix i18n key collision with namespaced models #6448 *yves.senn*
|
51
|
+
|
52
|
+
|
53
|
+
## Rails 3.0.5 (February 26, 2011) ##
|
29
54
|
|
30
55
|
* No changes.
|
31
56
|
|
32
|
-
|
57
|
+
|
58
|
+
## Rails 3.0.4 (February 8, 2011) ##
|
33
59
|
|
34
60
|
* No changes.
|
35
61
|
|
36
|
-
|
62
|
+
|
63
|
+
## Rails 3.0.3 (November 16, 2010) ##
|
37
64
|
|
38
65
|
* No changes.
|
39
66
|
|
40
|
-
## Rails 3.1.1 (October 7, 2011) ##
|
41
67
|
|
42
|
-
|
43
|
-
You must add the gem explicitly to your Gemfile if you want use ActiveModel::SecurePassword:
|
68
|
+
## Rails 3.0.2 (November 15, 2010) ##
|
44
69
|
|
45
|
-
|
70
|
+
* No changes
|
46
71
|
|
47
|
-
See GH #2687. *Guillermo Iguaran*
|
48
72
|
|
49
|
-
## Rails 3.1
|
73
|
+
## Rails 3.0.1 (October 15, 2010) ##
|
50
74
|
|
51
|
-
*
|
52
|
-
Instead of "activerecord.models.admins.post", do "activerecord.models.admins/post" instead *José Valim*
|
75
|
+
* No Changes, just a version bump.
|
53
76
|
|
54
|
-
* attr_accessible and friends now accepts :as as option to specify a role *Josh Kalderimis*
|
55
77
|
|
56
|
-
|
57
|
-
ExclusionValidator, and FormatValidator *Prem Sichanugrist*
|
78
|
+
## Rails 3.0.0 (August 29, 2010) ##
|
58
79
|
|
59
|
-
|
60
|
-
validations, and it will be called with current record as an argument.
|
61
|
-
That given proc or lambda must returns an object which respond to #include? for
|
62
|
-
InclusionValidator and ExclusionValidator, and returns a regular expression
|
63
|
-
object for FormatValidator.
|
80
|
+
* Added ActiveModel::MassAssignmentSecurity *Eric Chapweske, Josh Kalderimis*
|
64
81
|
|
65
|
-
*
|
82
|
+
* JSON supports a custom root option: to_json(:root => 'custom') #4515 *Jatinder Singh*
|
66
83
|
|
67
|
-
*
|
84
|
+
* #new_record? and #destroyed? were removed from ActiveModel::Lint. Use
|
85
|
+
persisted? instead. A model is persisted if it's not a new_record? and it was
|
86
|
+
not destroyed? *MG*
|
68
87
|
|
69
|
-
*
|
88
|
+
* Added validations reflection in ActiveModel::Validations *JV*
|
89
|
+
|
90
|
+
Model.validators
|
91
|
+
Model.validators_on(:field)
|
92
|
+
|
93
|
+
* #to_key was added to ActiveModel::Lint so we can generate DOM IDs for
|
94
|
+
AMo objects with composite keys *MG*
|
95
|
+
|
96
|
+
* ActiveModel::Observer#add_observer!
|
97
|
+
|
98
|
+
It has a custom hook to define after_find that should really be in a
|
99
|
+
ActiveRecord::Observer subclass:
|
100
|
+
|
101
|
+
def add_observer!(klass)
|
102
|
+
klass.add_observer(self)
|
103
|
+
klass.class_eval 'def after_find() end' unless klass.respond_to?(:after_find)
|
104
|
+
end
|
105
|
+
|
106
|
+
* Change the ActiveModel::Base.include_root_in_json default to true for Rails 3 *DHH*
|
107
|
+
|
108
|
+
* Add validates_format_of :without => /regexp/ option. #430 *Elliot Winkler, Peer Allan*
|
109
|
+
|
110
|
+
Example :
|
111
|
+
|
112
|
+
validates_format_of :subdomain, :without => /www|admin|mail/
|
113
|
+
|
114
|
+
* Introduce validates_with to encapsulate attribute validations in a class. #2630 *Jeff Dean*
|
70
115
|
|
71
|
-
|
116
|
+
* Extracted from Active Record and Active Resource.
|
data/README.rdoc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/hash/keys'
|
2
2
|
require 'active_support/core_ext/class/attribute'
|
3
|
+
require 'active_support/deprecation'
|
3
4
|
|
4
5
|
module ActiveModel
|
5
6
|
class MissingAttributeError < NoMethodError
|
@@ -56,54 +57,38 @@ module ActiveModel
|
|
56
57
|
module AttributeMethods
|
57
58
|
extend ActiveSupport::Concern
|
58
59
|
|
59
|
-
|
60
|
+
NAME_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?=]?\z/
|
61
|
+
CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
|
60
62
|
|
61
63
|
included do
|
62
64
|
class_attribute :attribute_method_matchers, :instance_writer => false
|
63
|
-
self.attribute_method_matchers = []
|
65
|
+
self.attribute_method_matchers = [ClassMethods::AttributeMethodMatcher.new]
|
64
66
|
end
|
65
67
|
|
66
68
|
module ClassMethods
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
#
|
79
|
-
# class Person
|
80
|
-
#
|
81
|
-
# include ActiveModel::AttributeMethods
|
82
|
-
#
|
83
|
-
# cattr_accessor :primary_key
|
84
|
-
# cattr_accessor :inheritance_column
|
85
|
-
#
|
86
|
-
# define_attr_method :primary_key, "sysid"
|
87
|
-
# define_attr_method( :inheritance_column ) do
|
88
|
-
# original_inheritance_column + "_id"
|
89
|
-
# end
|
90
|
-
#
|
91
|
-
# end
|
92
|
-
#
|
93
|
-
# Provides you with:
|
94
|
-
#
|
95
|
-
# Person.primary_key
|
96
|
-
# # => "sysid"
|
97
|
-
# Person.inheritance_column = 'address'
|
98
|
-
# Person.inheritance_column
|
99
|
-
# # => 'address_id'
|
100
|
-
def define_attr_method(name, value=nil, &block)
|
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
|
+
|
101
80
|
sing = singleton_class
|
102
81
|
sing.class_eval <<-eorb, __FILE__, __LINE__ + 1
|
103
|
-
|
104
|
-
|
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}')
|
105
91
|
end
|
106
|
-
alias_method :'original_#{name}', :'#{name}'
|
107
92
|
eorb
|
108
93
|
if block_given?
|
109
94
|
sing.send :define_method, name, &block
|
@@ -111,7 +96,7 @@ module ActiveModel
|
|
111
96
|
# If we can compile the method name, do it. Otherwise use define_method.
|
112
97
|
# This is an important *optimization*, please don't change it. define_method
|
113
98
|
# has slower dispatch and consumes more memory.
|
114
|
-
if name =~
|
99
|
+
if name =~ NAME_COMPILABLE_REGEXP
|
115
100
|
sing.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
116
101
|
def #{name}; #{value.nil? ? 'nil' : value.to_s.inspect}; end
|
117
102
|
RUBY
|
@@ -239,18 +224,7 @@ module ActiveModel
|
|
239
224
|
attribute_method_matchers.each do |matcher|
|
240
225
|
matcher_new = matcher.method_name(new_name).to_s
|
241
226
|
matcher_old = matcher.method_name(old_name).to_s
|
242
|
-
|
243
|
-
if matcher_new =~ COMPILABLE_REGEXP && matcher_old =~ COMPILABLE_REGEXP
|
244
|
-
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
245
|
-
def #{matcher_new}(*args)
|
246
|
-
send(:#{matcher_old}, *args)
|
247
|
-
end
|
248
|
-
RUBY
|
249
|
-
else
|
250
|
-
define_method(matcher_new) do |*args|
|
251
|
-
send(matcher_old, *args)
|
252
|
-
end
|
253
|
-
end
|
227
|
+
define_optimized_call self, matcher_new, matcher_old
|
254
228
|
end
|
255
229
|
end
|
256
230
|
|
@@ -284,36 +258,19 @@ module ActiveModel
|
|
284
258
|
|
285
259
|
def define_attribute_method(attr_name)
|
286
260
|
attribute_method_matchers.each do |matcher|
|
287
|
-
|
288
|
-
|
261
|
+
method_name = matcher.method_name(attr_name)
|
262
|
+
|
263
|
+
unless instance_method_already_implemented?(method_name)
|
264
|
+
generate_method = "define_method_#{matcher.method_missing_target}"
|
289
265
|
|
290
|
-
if respond_to?(generate_method
|
266
|
+
if respond_to?(generate_method)
|
291
267
|
send(generate_method, attr_name)
|
292
268
|
else
|
293
|
-
method_name
|
294
|
-
|
295
|
-
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
296
|
-
if method_defined?('#{method_name}')
|
297
|
-
undef :'#{method_name}'
|
298
|
-
end
|
299
|
-
RUBY
|
300
|
-
|
301
|
-
if method_name.to_s =~ COMPILABLE_REGEXP
|
302
|
-
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
303
|
-
def #{method_name}(*args)
|
304
|
-
send(:#{matcher.method_missing_target}, '#{attr_name}', *args)
|
305
|
-
end
|
306
|
-
RUBY
|
307
|
-
else
|
308
|
-
generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
309
|
-
define_method('#{method_name}') do |*args|
|
310
|
-
send('#{matcher.method_missing_target}', '#{attr_name}', *args)
|
311
|
-
end
|
312
|
-
RUBY
|
313
|
-
end
|
269
|
+
define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s
|
314
270
|
end
|
315
271
|
end
|
316
272
|
end
|
273
|
+
attribute_method_matchers_cache.clear
|
317
274
|
end
|
318
275
|
|
319
276
|
# Removes all the previously dynamically defined methods from the class
|
@@ -321,6 +278,7 @@ module ActiveModel
|
|
321
278
|
generated_attribute_methods.module_eval do
|
322
279
|
instance_methods.each { |m| undef_method(m) }
|
323
280
|
end
|
281
|
+
attribute_method_matchers_cache.clear
|
324
282
|
end
|
325
283
|
|
326
284
|
# Returns true if the attribute methods defined have been generated.
|
@@ -334,26 +292,87 @@ module ActiveModel
|
|
334
292
|
|
335
293
|
protected
|
336
294
|
def instance_method_already_implemented?(method_name)
|
337
|
-
method_defined?(method_name)
|
295
|
+
generated_attribute_methods.method_defined?(method_name)
|
338
296
|
end
|
339
297
|
|
340
298
|
private
|
299
|
+
# The methods +method_missing+ and +respond_to?+ of this module are
|
300
|
+
# invoked often in a typical rails, both of which invoke the method
|
301
|
+
# +match_attribute_method?+. The latter method iterates through an
|
302
|
+
# array doing regular expression matches, which results in a lot of
|
303
|
+
# object creations. Most of the times it returns a +nil+ match. As the
|
304
|
+
# match result is always the same given a +method_name+, this cache is
|
305
|
+
# used to alleviate the GC, which ultimately also speeds up the app
|
306
|
+
# significantly (in our case our test suite finishes 10% faster with
|
307
|
+
# this cache).
|
308
|
+
def attribute_method_matchers_cache #:nodoc:
|
309
|
+
@attribute_method_matchers_cache ||= {}
|
310
|
+
end
|
311
|
+
|
312
|
+
def attribute_method_matcher(method_name) #:nodoc:
|
313
|
+
if attribute_method_matchers_cache.key?(method_name)
|
314
|
+
attribute_method_matchers_cache[method_name]
|
315
|
+
else
|
316
|
+
# Must try to match prefixes/suffixes first, or else the matcher with no prefix/suffix
|
317
|
+
# will match every time.
|
318
|
+
matchers = attribute_method_matchers.partition(&:plain?).reverse.flatten(1)
|
319
|
+
match = nil
|
320
|
+
matchers.detect { |method| match = method.match(method_name) }
|
321
|
+
attribute_method_matchers_cache[method_name] = match
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Define a method `name` in `mod` that dispatches to `send`
|
326
|
+
# using the given `extra` args. This fallbacks `define_method`
|
327
|
+
# and `send` if the given names cannot be compiled.
|
328
|
+
def define_optimized_call(mod, name, send, *extra) #:nodoc:
|
329
|
+
if name =~ NAME_COMPILABLE_REGEXP
|
330
|
+
defn = "def #{name}(*args)"
|
331
|
+
else
|
332
|
+
defn = "define_method(:'#{name}') do |*args|"
|
333
|
+
end
|
334
|
+
|
335
|
+
extra = (extra.map(&:inspect) << "*args").join(", ")
|
336
|
+
|
337
|
+
if send =~ CALL_COMPILABLE_REGEXP
|
338
|
+
target = "#{send}(#{extra})"
|
339
|
+
else
|
340
|
+
target = "send(:'#{send}', #{extra})"
|
341
|
+
end
|
342
|
+
|
343
|
+
mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
344
|
+
#{defn}
|
345
|
+
#{target}
|
346
|
+
end
|
347
|
+
RUBY
|
348
|
+
end
|
349
|
+
|
341
350
|
class AttributeMethodMatcher
|
342
351
|
attr_reader :prefix, :suffix, :method_missing_target
|
343
352
|
|
344
|
-
AttributeMethodMatch = Struct.new(:target, :attr_name)
|
353
|
+
AttributeMethodMatch = Struct.new(:target, :attr_name, :method_name)
|
345
354
|
|
346
355
|
def initialize(options = {})
|
347
356
|
options.symbolize_keys!
|
357
|
+
|
358
|
+
if options[:prefix] == '' || options[:suffix] == ''
|
359
|
+
ActiveSupport::Deprecation.warn(
|
360
|
+
"Specifying an empty prefix/suffix for an attribute method is no longer " \
|
361
|
+
"necessary. If the un-prefixed/suffixed version of the method has not been " \
|
362
|
+
"defined when `define_attribute_methods` is called, it will be defined " \
|
363
|
+
"automatically."
|
364
|
+
)
|
365
|
+
end
|
366
|
+
|
348
367
|
@prefix, @suffix = options[:prefix] || '', options[:suffix] || ''
|
349
|
-
@regex =
|
368
|
+
@regex = /^(#{Regexp.escape(@prefix)})(.+?)(#{Regexp.escape(@suffix)})$/
|
350
369
|
@method_missing_target = "#{@prefix}attribute#{@suffix}"
|
351
370
|
@method_name = "#{prefix}%s#{suffix}"
|
352
371
|
end
|
353
372
|
|
354
373
|
def match(method_name)
|
355
374
|
if @regex =~ method_name
|
356
|
-
AttributeMethodMatch.new(method_missing_target, $2)
|
375
|
+
AttributeMethodMatch.new(method_missing_target, $2, method_name)
|
357
376
|
else
|
358
377
|
nil
|
359
378
|
end
|
@@ -362,6 +381,10 @@ module ActiveModel
|
|
362
381
|
def method_name(attr_name)
|
363
382
|
@method_name % attr_name
|
364
383
|
end
|
384
|
+
|
385
|
+
def plain?
|
386
|
+
prefix.empty? && suffix.empty?
|
387
|
+
end
|
365
388
|
end
|
366
389
|
end
|
367
390
|
|
@@ -376,13 +399,21 @@ module ActiveModel
|
|
376
399
|
# It's also possible to instantiate related objects, so a Client class
|
377
400
|
# belonging to the clients table with a +master_id+ foreign key can
|
378
401
|
# instantiate master through Client#master.
|
379
|
-
def method_missing(
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
402
|
+
def method_missing(method, *args, &block)
|
403
|
+
if respond_to_without_attributes?(method, true)
|
404
|
+
super
|
405
|
+
else
|
406
|
+
match = match_attribute_method?(method.to_s)
|
407
|
+
match ? attribute_missing(match, *args, &block) : super
|
384
408
|
end
|
385
|
-
|
409
|
+
end
|
410
|
+
|
411
|
+
# attribute_missing is like method_missing, but for attributes. When method_missing is
|
412
|
+
# called we check to see if there is a matching attribute method. If so, we call
|
413
|
+
# attribute_missing to dispatch the attribute. This method can be overloaded to
|
414
|
+
# customise the behaviour.
|
415
|
+
def attribute_missing(match, *args, &block)
|
416
|
+
__send__(match.target, match.attr_name, *args, &block)
|
386
417
|
end
|
387
418
|
|
388
419
|
# A Person object with a name attribute can ask <tt>person.respond_to?(:name)</tt>,
|
@@ -391,15 +422,14 @@ module ActiveModel
|
|
391
422
|
alias :respond_to_without_attributes? :respond_to?
|
392
423
|
def respond_to?(method, include_private_methods = false)
|
393
424
|
if super
|
394
|
-
|
425
|
+
true
|
395
426
|
elsif !include_private_methods && super(method, true)
|
396
427
|
# If we're here then we haven't found among non-private methods
|
397
428
|
# but found among all methods. Which means that the given method is private.
|
398
|
-
|
399
|
-
|
400
|
-
|
429
|
+
false
|
430
|
+
else
|
431
|
+
!match_attribute_method?(method.to_s).nil?
|
401
432
|
end
|
402
|
-
super
|
403
433
|
end
|
404
434
|
|
405
435
|
protected
|
@@ -411,19 +441,8 @@ module ActiveModel
|
|
411
441
|
# Returns a struct representing the matching attribute method.
|
412
442
|
# The struct's attributes are prefix, base and suffix.
|
413
443
|
def match_attribute_method?(method_name)
|
414
|
-
self.class.
|
415
|
-
|
416
|
-
return match
|
417
|
-
end
|
418
|
-
end
|
419
|
-
nil
|
420
|
-
end
|
421
|
-
|
422
|
-
# prevent method_missing from calling private methods with #send
|
423
|
-
def guard_private_attribute_method!(method_name, args)
|
424
|
-
if self.class.private_method_defined?(method_name)
|
425
|
-
raise NoMethodError.new("Attempt to call private method `#{method_name}'", method_name, args)
|
426
|
-
end
|
444
|
+
match = self.class.send(:attribute_method_matcher, method_name)
|
445
|
+
match && attribute_method?(match.attr_name) ? match : nil
|
427
446
|
end
|
428
447
|
|
429
448
|
def missing_attribute(attr_name, stack)
|