Active Model Attribute Methods
ActiveModel::AttributeMethods provides a way to add prefixes
and suffixes to your methods as well as handling the creation of
ActiveRecord::Base-like class methods such as
table_name.
The requirements to implement ActiveModel::AttributeMethods
are to:
-
include ActiveModel::AttributeMethodsin your class. -
Call each of its method you want to add, such as
attribute_method_suffixorattribute_method_prefix. -
Call
define_attribute_methodsafter the other methods are called. -
Define the various generic
_attributemethods that you have declared. -
Define an
attributesmethod, see below.
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 def attributes {'name' => @name} end 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.
| NAME_COMPILABLE_REGEXP | = | /\A[a-zA-Z_]\w*[!?=]?\z/ |
| CALL_COMPILABLE_REGEXP | = | /\A[a-zA-Z_]\w*[!?]?\z/ |
attribute_missing is like method_missing, but for
attributes. When method_missing is called we check to see if
there is a matching attribute method. If so, we tell
attribute_missing to dispatch the attribute. This method can
be overloaded to customize the behavior.
Allows access to the object attributes, which are held in the hash returned
by attributes, as though they were first-class methods. So a
Person class with a name attribute can for
example use Person#name and Person#name= and
never directly use the attributes hash – except for multiple assigns with
ActiveRecord::Base#attributes=.
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 activemodel/lib/active_model/attribute_methods.rb, line 431 def method_missing(method, *args, &block) if respond_to_without_attributes?(method, true) super else match = match_attribute_method?(method.to_s) match ? attribute_missing(match, *args, &block) : super end end
# File activemodel/lib/active_model/attribute_methods.rb, line 452 def respond_to?(method, include_private_methods = false) if super 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. false else !match_attribute_method?(method.to_s).nil? end end
A Person instance with a name attribute can ask
person.respond_to?(:name),
person.respond_to?(:name=), and
person.respond_to?(:name?) which will all return
true.