activemodel 3.0.pre → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +44 -1
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +184 -0
  4. data/lib/active_model.rb +29 -19
  5. data/lib/active_model/attribute_methods.rb +167 -46
  6. data/lib/active_model/callbacks.rb +134 -0
  7. data/lib/active_model/conversion.rb +41 -1
  8. data/lib/active_model/deprecated_error_methods.rb +1 -1
  9. data/lib/active_model/dirty.rb +56 -12
  10. data/lib/active_model/errors.rb +205 -46
  11. data/lib/active_model/lint.rb +53 -17
  12. data/lib/active_model/locale/en.yml +26 -23
  13. data/lib/active_model/mass_assignment_security.rb +160 -0
  14. data/lib/active_model/mass_assignment_security/permission_set.rb +40 -0
  15. data/lib/active_model/mass_assignment_security/sanitizer.rb +23 -0
  16. data/lib/active_model/naming.rb +70 -5
  17. data/lib/active_model/observing.rb +40 -16
  18. data/lib/active_model/railtie.rb +2 -0
  19. data/lib/active_model/serialization.rb +59 -0
  20. data/lib/active_model/serializers/json.rb +17 -11
  21. data/lib/active_model/serializers/xml.rb +66 -123
  22. data/lib/active_model/test_case.rb +0 -2
  23. data/lib/active_model/translation.rb +64 -0
  24. data/lib/active_model/validations.rb +150 -68
  25. data/lib/active_model/validations/acceptance.rb +53 -33
  26. data/lib/active_model/validations/callbacks.rb +57 -0
  27. data/lib/active_model/validations/confirmation.rb +41 -23
  28. data/lib/active_model/validations/exclusion.rb +18 -13
  29. data/lib/active_model/validations/format.rb +28 -24
  30. data/lib/active_model/validations/inclusion.rb +18 -13
  31. data/lib/active_model/validations/length.rb +67 -65
  32. data/lib/active_model/validations/numericality.rb +83 -58
  33. data/lib/active_model/validations/presence.rb +10 -8
  34. data/lib/active_model/validations/validates.rb +110 -0
  35. data/lib/active_model/validations/with.rb +90 -23
  36. data/lib/active_model/validator.rb +186 -0
  37. data/lib/active_model/version.rb +3 -2
  38. metadata +79 -20
  39. data/README +0 -21
  40. data/lib/active_model/state_machine.rb +0 -70
  41. data/lib/active_model/state_machine/event.rb +0 -62
  42. data/lib/active_model/state_machine/machine.rb +0 -75
  43. data/lib/active_model/state_machine/state.rb +0 -47
  44. data/lib/active_model/state_machine/state_transition.rb +0 -40
  45. data/lib/active_model/validations_repair_helper.rb +0 -35
data/CHANGELOG CHANGED
@@ -1,4 +1,47 @@
1
- *Edge*
1
+ *Rails 3.0.0 [release candidate] (July 26th, 2010)*
2
+
3
+ * Added ActiveModel::MassAssignmentSecurity [Eric Chapweske, Josh Kalderimis]
4
+
5
+
6
+ *Rails 3.0.0 [beta 4] (June 8th, 2010)*
7
+
8
+ * JSON supports a custom root option: to_json(:root => 'custom') #4515 [Jatinder Singh]
9
+
10
+
11
+ *Rails 3.0.0 [beta 3] (April 13th, 2010)*
12
+
13
+ * No changes
14
+
15
+
16
+ *Rails 3.0.0 [beta 2] (April 1st, 2010)*
17
+
18
+ * #new_record? and #destroyed? were removed from ActiveModel::Lint. Use
19
+ persisted? instead. A model is persisted if it's not a new_record? and it was
20
+ not destroyed? [MG]
21
+
22
+ * Added validations reflection in ActiveModel::Validations [JV]
23
+
24
+ Model.validators
25
+ Model.validators_on(:field)
26
+
27
+ * #to_key was added to ActiveModel::Lint so we can generate DOM IDs for
28
+ AMo objects with composite keys [MG]
29
+
30
+
31
+ *Rails 3.0.0 [beta 1] (February 4, 2010)*
32
+
33
+ * ActiveModel::Observer#add_observer!
34
+
35
+ It has a custom hook to define after_find that should really be in a
36
+ ActiveRecord::Observer subclass:
37
+
38
+ def add_observer!(klass)
39
+ klass.add_observer(self)
40
+ klass.class_eval 'def after_find() end' unless
41
+ klass.respond_to?(:after_find)
42
+ end
43
+
44
+ * Change the ActiveModel::Base.include_root_in_json default to true for Rails 3 [DHH]
2
45
 
3
46
  * Add validates_format_of :without => /regexp/ option. #430 [Elliot Winkler, Peer Allan]
4
47
 
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2009 David Heinemeier Hansson
1
+ Copyright (c) 2004-2010 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc ADDED
@@ -0,0 +1,184 @@
1
+ = Active Model -- model interfaces for Rails
2
+
3
+ Active Model provides a known set of interfaces for usage in model classes.
4
+ They allow for Action Pack helpers to interact with non-ActiveRecord models,
5
+ for example. Active Model also helps building custom ORMs for use outside of
6
+ the Rails framework.
7
+
8
+ Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
9
+ interact with Action Pack helpers, it was required to either copy chunks of
10
+ code from Rails, or monkey patch entire helpers to make them handle objects
11
+ that did not exacly conform to the Active Record interface. This would result
12
+ in code duplication and fragile applications that broke on upgrades.
13
+
14
+ Active Model solves this. You can include functionality from the following
15
+ modules:
16
+
17
+ * Add attribute magic to objects
18
+
19
+ class Person
20
+ include ActiveModel::AttributeMethods
21
+
22
+ attribute_method_prefix 'clear_'
23
+ define_attribute_methods [:name, :age]
24
+
25
+ attr_accessor :name, :age
26
+
27
+ def clear_attribute(attr)
28
+ send("#{attr}=", nil)
29
+ end
30
+ end
31
+
32
+ person.clear_name
33
+ person.clear_age
34
+
35
+ {Learn more}[link:classes/ActiveModel/AttributeMethods.html]
36
+
37
+ * Callbacks for certain operations
38
+
39
+ class Person
40
+ extend ActiveModel::Callbacks
41
+ define_model_callbacks :create
42
+
43
+ def create
44
+ _run_create_callbacks do
45
+ # Your create action methods here
46
+ end
47
+ end
48
+ end
49
+
50
+ This generates +before_create+, +around_create+ and +after_create+
51
+ class methods that wrap your create method.
52
+
53
+ {Learn more}[link:classes/ActiveModel/CallBacks.html]
54
+
55
+ * Tracking value changes
56
+
57
+ The ActiveModel::Dirty module allows for tracking attribute changes:
58
+
59
+ person = Person.new
60
+ person.name # => nil
61
+ person.changed? # => false
62
+ person.name = 'bob'
63
+ person.changed? # => true
64
+ person.changed # => ['name']
65
+ person.changes # => { 'name' => [nil, 'bob'] }
66
+ person.name = 'robert'
67
+ person.save
68
+ person.previous_changes # => {'name' => ['bob, 'robert']}
69
+
70
+ {Learn more}[link:classes/ActiveModel/Dirty.html]
71
+
72
+ * Adding +errors+ interface to objects
73
+
74
+ Exposing error messages allows objects to interact with Action Pack
75
+ helpers seamlessly.
76
+
77
+ class Person
78
+
79
+ def initialize
80
+ @errors = ActiveModel::Errors.new(self)
81
+ end
82
+
83
+ attr_accessor :name
84
+ attr_reader :errors
85
+
86
+ def validate!
87
+ errors.add(:name, "can not be nil") if name == nil
88
+ end
89
+
90
+ def ErrorsPerson.human_attribute_name(attr, options = {})
91
+ "Name"
92
+ end
93
+
94
+ end
95
+
96
+ person.errors.full_messages
97
+ # => ["Name Can not be nil"]
98
+
99
+ person.errors.full_messages
100
+ # => ["Name Can not be nil"]
101
+
102
+ {Learn more}[link:classes/ActiveModel/Errors.html]
103
+
104
+ * Model name introspection
105
+
106
+ class NamedPerson
107
+ extend ActiveModel::Naming
108
+ end
109
+
110
+ NamedPerson.model_name #=> "NamedPerson"
111
+ NamedPerson.model_name.human #=> "Named person"
112
+
113
+ {Learn more}[link:classes/ActiveModel/Naming.html]
114
+
115
+ * Observer support
116
+
117
+ ActiveModel::Observers allows your object to implement the Observer
118
+ pattern in a Rails App and take advantage of all the standard observer
119
+ functions.
120
+
121
+ {Learn more}[link:classes/ActiveModel/Observer.html]
122
+
123
+ * Making objects serializable
124
+
125
+ ActiveModel::Serialization provides a standard interface for your object
126
+ to provide +to_json+ or +to_xml+ serialization.
127
+
128
+ s = SerialPerson.new
129
+ s.serializable_hash # => {"name"=>nil}
130
+ s.to_json # => "{\"name\":null}"
131
+ s.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
132
+
133
+ {Learn more}[link:classes/ActiveModel/Serialization.html]
134
+
135
+ * Internationalization (i18n) support
136
+
137
+ class Person
138
+ extend ActiveModel::Translation
139
+ end
140
+
141
+ Person.human_attribute_name('my_attribute')
142
+ #=> "My attribute"
143
+
144
+ {Learn more}[link:classes/ActiveModel/Translation.html]
145
+
146
+ * Validation support
147
+
148
+ class Person
149
+ include ActiveModel::Validations
150
+
151
+ attr_accessor :first_name, :last_name
152
+
153
+ validates_each :first_name, :last_name do |record, attr, value|
154
+ record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
155
+ end
156
+ end
157
+
158
+ person = Person.new
159
+ person.first_name = 'zoolander'
160
+ person.valid? #=> false
161
+
162
+ {Learn more}[link:classes/ActiveModel/Validations.html]
163
+
164
+ * Custom validators
165
+
166
+ class Person
167
+ include ActiveModel::Validations
168
+ validates_with HasNameValidator
169
+ attr_accessor :name
170
+ end
171
+
172
+ class HasNameValidator < ActiveModel::Validator
173
+ def validate(record)
174
+ record.errors[:name] = "must exist" if record.name.blank?
175
+ end
176
+ end
177
+
178
+ p = ValidatorPerson.new
179
+ p.valid? #=> false
180
+ p.errors.full_messages #=> ["Name must exist"]
181
+ p.name = "Bob"
182
+ p.valid? #=> true
183
+
184
+ {Learn more}[link:classes/ActiveModel/Validator.html]
data/lib/active_model.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2004-2009 David Heinemeier Hansson
2
+ # Copyright (c) 2004-2010 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
@@ -21,32 +21,42 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib"
25
- $:.unshift(activesupport_path) if File.directory?(activesupport_path)
24
+ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
25
+ $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
26
26
  require 'active_support'
27
27
 
28
+
28
29
  module ActiveModel
29
- autoload :AttributeMethods, 'active_model/attribute_methods'
30
- autoload :Conversion, 'active_model/conversion'
31
- autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
32
- autoload :Dirty, 'active_model/dirty'
33
- autoload :Errors, 'active_model/errors'
34
- autoload :Lint, 'active_model/lint'
30
+ extend ActiveSupport::Autoload
31
+
32
+ autoload :AttributeMethods
33
+ autoload :BlockValidator, 'active_model/validator'
34
+ autoload :Callbacks
35
+ autoload :Conversion
36
+ autoload :DeprecatedErrorMethods
37
+ autoload :Dirty
38
+ autoload :EachValidator, 'active_model/validator'
39
+ autoload :Errors
40
+ autoload :Lint
41
+ autoload :MassAssignmentSecurity
35
42
  autoload :Name, 'active_model/naming'
36
- autoload :Naming, 'active_model/naming'
43
+ autoload :Naming
37
44
  autoload :Observer, 'active_model/observing'
38
- autoload :Observing, 'active_model/observing'
39
- autoload :Serialization, 'active_model/serialization'
40
- autoload :StateMachine, 'active_model/state_machine'
41
- autoload :TestCase, 'active_model/test_case'
42
- autoload :Validations, 'active_model/validations'
43
- autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
44
- autoload :VERSION, 'active_model/version'
45
+ autoload :Observing
46
+ autoload :Serialization
47
+ autoload :TestCase
48
+ autoload :Translation
49
+ autoload :VERSION
50
+ autoload :Validations
51
+ autoload :Validator
45
52
 
46
53
  module Serializers
47
- autoload :JSON, 'active_model/serializers/json'
48
- autoload :Xml, 'active_model/serializers/xml'
54
+ extend ActiveSupport::Autoload
55
+
56
+ autoload :JSON
57
+ autoload :Xml
49
58
  end
50
59
  end
51
60
 
61
+ require 'active_support/i18n'
52
62
  I18n.load_path << File.dirname(__FILE__) + '/active_model/locale/en.yml'
@@ -4,39 +4,108 @@ require 'active_support/core_ext/class/inheritable_attributes'
4
4
  module ActiveModel
5
5
  class MissingAttributeError < NoMethodError
6
6
  end
7
-
7
+ # == Active Model Attribute Methods
8
+ #
9
+ # <tt>ActiveModel::AttributeMethods</tt> provides a way to add prefixes and suffixes
10
+ # to your methods as well as handling the creation of Active Record like class methods
11
+ # such as +table_name+.
12
+ #
13
+ # The requirements to implement ActiveModel::AttributeMethods are to:
14
+ #
15
+ # * <tt>include ActiveModel::AttributeMethods</tt> in your object
16
+ # * Call each Attribute Method module method you want to add, such as
17
+ # attribute_method_suffix or attribute_method_prefix
18
+ # * Call <tt>define_attribute_methods</tt> after the other methods are
19
+ # called.
20
+ # * Define the various generic +_attribute+ methods that you have declared
21
+ #
22
+ # A minimal implementation could be:
23
+ #
24
+ # class Person
25
+ # include ActiveModel::AttributeMethods
26
+ #
27
+ # attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
28
+ # attribute_method_suffix '_contrived?'
29
+ # attribute_method_prefix 'clear_'
30
+ # define_attribute_methods ['name']
31
+ #
32
+ # attr_accessor :name
33
+ #
34
+ # private
35
+ #
36
+ # def attribute_contrived?(attr)
37
+ # true
38
+ # end
39
+ #
40
+ # def clear_attribute(attr)
41
+ # send("#{attr}=", nil)
42
+ # end
43
+ #
44
+ # def reset_attribute_to_default!(attr)
45
+ # send("#{attr}=", "Default Name")
46
+ # end
47
+ # end
48
+ #
49
+ # Notice that whenever you include ActiveModel::AttributeMethods in your class,
50
+ # it requires you to implement a <tt>attributes</tt> methods which returns a hash
51
+ # with each attribute name in your model as hash key and the attribute value as
52
+ # hash value.
53
+ #
54
+ # Hash keys must be strings.
55
+ #
8
56
  module AttributeMethods
9
57
  extend ActiveSupport::Concern
10
58
 
11
- # Declare and check for suffixed attribute methods.
12
59
  module ClassMethods
13
- # Defines an "attribute" method (like +inheritance_column+ or
14
- # +table_name+). A new (class) method will be created with the
15
- # given name. If a value is specified, the new method will
16
- # return that value (as a string). Otherwise, the given block
17
- # will be used to compute the value of the method.
60
+ # Defines an "attribute" method (like +inheritance_column+ or +table_name+).
61
+ # A new (class) method will be created with the given name. If a value is
62
+ # specified, the new method will return that value (as a string).
63
+ # Otherwise, the given block will be used to compute the value of the
64
+ # method.
18
65
  #
19
- # The original method will be aliased, with the new name being
20
- # prefixed with "original_". This allows the new method to
21
- # access the original value.
66
+ # The original method will be aliased, with the new name being prefixed
67
+ # with "original_". This allows the new method to access the original
68
+ # value.
22
69
  #
23
70
  # Example:
24
71
  #
25
- # class A < ActiveRecord::Base
72
+ # class Person
73
+ #
74
+ # include ActiveModel::AttributeMethods
75
+ #
76
+ # cattr_accessor :primary_key
77
+ # cattr_accessor :inheritance_column
78
+ #
26
79
  # define_attr_method :primary_key, "sysid"
27
80
  # define_attr_method( :inheritance_column ) do
28
81
  # original_inheritance_column + "_id"
29
82
  # end
83
+ #
30
84
  # end
85
+ #
86
+ # Provides you with:
87
+ #
88
+ # AttributePerson.primary_key
89
+ # # => "sysid"
90
+ # AttributePerson.inheritance_column = 'address'
91
+ # AttributePerson.inheritance_column
92
+ # # => 'address_id'
31
93
  def define_attr_method(name, value=nil, &block)
32
- sing = metaclass
33
- sing.send :alias_method, "original_#{name}", name
94
+ sing = singleton_class
95
+ sing.class_eval <<-eorb, __FILE__, __LINE__ + 1
96
+ if method_defined?(:original_#{name})
97
+ undef :original_#{name}
98
+ end
99
+ alias_method :original_#{name}, :#{name}
100
+ eorb
34
101
  if block_given?
35
102
  sing.send :define_method, name, &block
36
103
  else
37
104
  # use eval instead of a block to work around a memory leak in dev
38
105
  # mode in fcgi
39
- sing.class_eval "def #{name}; #{value.to_s.inspect}; end"
106
+ sing.class_eval <<-eorb, __FILE__, __LINE__ + 1
107
+ def #{name}; #{value.to_s.inspect}; end
108
+ eorb
40
109
  end
41
110
  end
42
111
 
@@ -49,24 +118,30 @@ module ActiveModel
49
118
  #
50
119
  # #{prefix}attribute(#{attr}, *args, &block)
51
120
  #
52
- # An <tt>#{prefix}attribute</tt> instance method must exist and accept at least
53
- # the +attr+ argument.
121
+ # An instance method <tt>#{prefix}attribute</tt> must exist and accept
122
+ # at least the +attr+ argument.
54
123
  #
55
124
  # For example:
56
125
  #
57
- # class Person < ActiveRecord::Base
126
+ # class Person
127
+ #
128
+ # include ActiveModel::AttributeMethods
129
+ # attr_accessor :name
58
130
  # attribute_method_prefix 'clear_'
131
+ # define_attribute_methods [:name]
59
132
  #
60
133
  # private
61
- # def clear_attribute(attr)
62
- # ...
63
- # end
134
+ #
135
+ # def clear_attribute(attr)
136
+ # send("#{attr}=", nil)
137
+ # end
64
138
  # end
65
139
  #
66
- # person = Person.find(1)
67
- # person.name # => 'Gem'
140
+ # person = Person.new
141
+ # person.name = "Bob"
142
+ # person.name # => "Bob"
68
143
  # person.clear_name
69
- # person.name # => ''
144
+ # person.name # => nil
70
145
  def attribute_method_prefix(*prefixes)
71
146
  attribute_method_matchers.concat(prefixes.map { |prefix| AttributeMethodMatcher.new :prefix => prefix })
72
147
  undefine_attribute_methods
@@ -86,18 +161,24 @@ module ActiveModel
86
161
  #
87
162
  # For example:
88
163
  #
89
- # class Person < ActiveRecord::Base
164
+ # class Person
165
+ #
166
+ # include ActiveModel::AttributeMethods
167
+ # attr_accessor :name
90
168
  # attribute_method_suffix '_short?'
169
+ # define_attribute_methods [:name]
91
170
  #
92
171
  # private
93
- # def attribute_short?(attr)
94
- # ...
95
- # end
172
+ #
173
+ # def attribute_short?(attr)
174
+ # send(attr).length < 5
175
+ # end
96
176
  # end
97
177
  #
98
- # person = Person.find(1)
99
- # person.name # => 'Gem'
100
- # person.name_short? # => true
178
+ # person = Person.new
179
+ # person.name = "Bob"
180
+ # person.name # => "Bob"
181
+ # person.name_short? # => true
101
182
  def attribute_method_suffix(*suffixes)
102
183
  attribute_method_matchers.concat(suffixes.map { |suffix| AttributeMethodMatcher.new :suffix => suffix })
103
184
  undefine_attribute_methods
@@ -118,16 +199,21 @@ module ActiveModel
118
199
  #
119
200
  # For example:
120
201
  #
121
- # class Person < ActiveRecord::Base
202
+ # class Person
203
+ #
204
+ # include ActiveModel::AttributeMethods
205
+ # attr_accessor :name
122
206
  # attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
207
+ # define_attribute_methods [:name]
123
208
  #
124
209
  # private
125
- # def reset_attribute_to_default!(attr)
126
- # ...
127
- # end
210
+ #
211
+ # def reset_attribute_to_default!(attr)
212
+ # ...
213
+ # end
128
214
  # end
129
215
  #
130
- # person = Person.find(1)
216
+ # person = Person.new
131
217
  # person.name # => 'Gem'
132
218
  # person.reset_name_to_default!
133
219
  # person.name # => 'Gemma'
@@ -138,7 +224,7 @@ module ActiveModel
138
224
 
139
225
  def alias_attribute(new_name, old_name)
140
226
  attribute_method_matchers.each do |matcher|
141
- module_eval <<-STR, __FILE__, __LINE__+1
227
+ module_eval <<-STR, __FILE__, __LINE__ + 1
142
228
  def #{matcher.method_name(new_name)}(*args)
143
229
  send(:#{matcher.method_name(old_name)}, *args)
144
230
  end
@@ -146,6 +232,30 @@ module ActiveModel
146
232
  end
147
233
  end
148
234
 
235
+ # Declares a the attributes that should be prefixed and suffixed by
236
+ # ActiveModel::AttributeMethods.
237
+ #
238
+ # To use, pass in an array of attribute names (as strings or symbols),
239
+ # be sure to declare +define_attribute_methods+ after you define any
240
+ # prefix, suffix or affix methods, or they will not hook in.
241
+ #
242
+ # class Person
243
+ #
244
+ # include ActiveModel::AttributeMethods
245
+ # attr_accessor :name, :age, :address
246
+ # attribute_method_prefix 'clear_'
247
+ #
248
+ # # Call to define_attribute_methods must appear after the
249
+ # # attribute_method_prefix, attribute_method_suffix or
250
+ # # attribute_method_affix declares.
251
+ # define_attribute_methods [:name, :age, :address]
252
+ #
253
+ # private
254
+ #
255
+ # def clear_attribute(attr)
256
+ # ...
257
+ # end
258
+ # end
149
259
  def define_attribute_methods(attr_names)
150
260
  return if attribute_methods_generated?
151
261
  attr_names.each do |attr_name|
@@ -156,8 +266,13 @@ module ActiveModel
156
266
  if respond_to?(generate_method)
157
267
  send(generate_method, attr_name)
158
268
  else
159
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__+1
160
- def #{matcher.method_name(attr_name)}(*args)
269
+ method_name = matcher.method_name(attr_name)
270
+
271
+ generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
272
+ if method_defined?(:#{method_name})
273
+ undef :#{method_name}
274
+ end
275
+ def #{method_name}(*args)
161
276
  send(:#{matcher.method_missing_target}, '#{attr_name}', *args)
162
277
  end
163
278
  STR
@@ -168,6 +283,7 @@ module ActiveModel
168
283
  @attribute_methods_generated = true
169
284
  end
170
285
 
286
+ # Removes all the preiously dynamically defined methods from the class
171
287
  def undefine_attribute_methods
172
288
  generated_attribute_methods.module_eval do
173
289
  instance_methods.each { |m| undef_method(m) }
@@ -175,6 +291,7 @@ module ActiveModel
175
291
  @attribute_methods_generated = nil
176
292
  end
177
293
 
294
+ # Returns true if the attribute methods defined have been generated.
178
295
  def generated_attribute_methods #:nodoc:
179
296
  @generated_attribute_methods ||= begin
180
297
  mod = Module.new
@@ -183,6 +300,7 @@ module ActiveModel
183
300
  end
184
301
  end
185
302
 
303
+ # Returns true if the attribute methods defined have been generated.
186
304
  def attribute_methods_generated?
187
305
  @attribute_methods_generated ||= nil
188
306
  end
@@ -226,14 +344,17 @@ module ActiveModel
226
344
  end
227
345
  end
228
346
 
229
- # Allows access to the object attributes, which are held in the <tt>@attributes</tt> hash, as though they
230
- # were first-class methods. So a Person class with a name attribute can use Person#name and
231
- # Person#name= and never directly use the attributes hash -- except for multiple assigns with
232
- # ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that
233
- # the completed attribute is not +nil+ or 0.
347
+ # Allows access to the object attributes, which are held in the
348
+ # <tt>@attributes</tt> hash, as though they were first-class methods. So a
349
+ # Person class with a name attribute can use Person#name and Person#name=
350
+ # and never directly use the attributes hash -- except for multiple assigns
351
+ # with ActiveRecord#attributes=. A Milestone class can also ask
352
+ # Milestone#completed? to test that the completed attribute is not +nil+
353
+ # or 0.
234
354
  #
235
- # It's also possible to instantiate related objects, so a Client class belonging to the clients
236
- # table with a +master_id+ foreign key can instantiate master through Client#master.
355
+ # It's also possible to instantiate related objects, so a Client class
356
+ # belonging to the clients table with a +master_id+ foreign key can
357
+ # instantiate master through Client#master.
237
358
  def method_missing(method_id, *args, &block)
238
359
  method_name = method_id.to_s
239
360
  if match = match_attribute_method?(method_name)
@@ -252,7 +373,7 @@ module ActiveModel
252
373
  return true
253
374
  elsif !include_private_methods && super(method, true)
254
375
  # If we're here then we haven't found among non-private methods
255
- # but found among all methods. Which means that given method is private.
376
+ # but found among all methods. Which means that the given method is private.
256
377
  return false
257
378
  elsif match_attribute_method?(method.to_s)
258
379
  return true