ActiveModel::AttributeMethods provides a way to add prefixes and suffixes to your methods as well as handling the creation of Active Record like class methods such as table_name.
The requirements to implement ActiveModel::AttributeMethods are to:
include ActiveModel::AttributeMethods in your object
Call each Attribute Method module method you want to add, such as attribute_method_suffix or attribute_method_prefix
Call define_attribute_methods after the other methods are called.
Define the various generic _attribute methods that you have declared
A minimal implementation could be:
class Person
include ActiveModel::AttributeMethods
attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
attribute_method_suffix '_contrived?'
attribute_method_prefix 'clear_'
define_attribute_methods ['name']
attr_accessor :name
private
def attribute_contrived?(attr)
true
end
def clear_attribute(attr)
send("#{attr}=", nil)
end
def reset_attribute_to_default!(attr)
send("#{attr}=", "Default Name")
end
end
Notice that whenever you include ActiveModel::AttributeMethods in your class, it requires you to implement a attributes methods which returns a hash with each attribute name in your model as hash key and the attribute value as hash value.
Hash keys must be strings.
Allows access to the object attributes, which are held in the @attributes hash, as though they were first-class methods. So a Person class with a name attribute can use Person#name and Person#name= and never directly use the attributes hash — except for multiple assigns with ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that the completed attribute is not nil or 0.
It’s also possible to instantiate related objects, so a Client class belonging to the clients table with a master_id foreign key can instantiate master through Client#master.
# File lib/active_model/attribute_methods.rb, line 358
358: def method_missing(method_id, *args, &block)
359: method_name = method_id.to_s
360: if match = match_attribute_method?(method_name)
361: guard_private_attribute_method!(method_name, args)
362: return __send__(match.target, match.attr_name, *args, &block)
363: end
364: super
365: end
# File lib/active_model/attribute_methods.rb, line 371
371: def respond_to?(method, include_private_methods = false)
372: if super
373: return true
374: elsif !include_private_methods && super(method, true)
375: # If we're here then we haven't found among non-private methods
376: # but found among all methods. Which means that the given method is private.
377: return false
378: elsif match_attribute_method?(method.to_s)
379: return true
380: end
381: super
382: end
A Person object with a name attribute can ask person.respond_to?(:name), person.respond_to?(:name=), and person.respond_to?(:name?) which will all return true.
prevent method_missing from calling private methods with #
# File lib/active_model/attribute_methods.rb, line 402
402: def guard_private_attribute_method!(method_name, args)
403: if self.class.private_method_defined?(method_name)
404: raise NoMethodError.new("Attempt to call private method", method_name, args)
405: end
406: end
Returns a struct representing the matching attribute method. The struct’s attributes are prefix, base and suffix.
# File lib/active_model/attribute_methods.rb, line 392
392: def match_attribute_method?(method_name)
393: self.class.send(:attribute_method_matchers).each do |method|
394: if (match = method.match(method_name)) && attribute_method?(match.attr_name)
395: return match
396: end
397: end
398: nil
399: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.