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
Note that whenever you include ActiveModel::AttributeMethods in your
class, it requires you to implement an attributes
method 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 386 def method_missing(method_id, *args, &block) method_name = method_id.to_s if match = match_attribute_method?(method_name) guard_private_attribute_method!(method_name, args) return __send__(match.target, match.attr_name, *args, &block) end super end
# File lib/active_model/attribute_methods.rb, line 399 def respond_to?(method, include_private_methods = false) if super return true elsif !include_private_methods && super(method, true) # If we're here then we haven't found among non-private methods # but found among all methods. Which means that the given method is private. return false elsif match_attribute_method?(method.to_s) return true end super 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
.
# File lib/active_model/attribute_methods.rb, line 413 def attribute_method?(attr_name) attributes.include?(attr_name) end