mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Adding ActiveModel::AttributeMethods documentation
This commit is contained in:
parent
e1c15d9fa1
commit
8834b2612b
2 changed files with 143 additions and 23 deletions
|
@ -12,9 +12,30 @@ Active Model provides a known set of interfaces that your objects can implement
|
||||||
to then present a common interface to the Action Pack helpers. You can include
|
to then present a common interface to the Action Pack helpers. You can include
|
||||||
functionality from the following modules:
|
functionality from the following modules:
|
||||||
|
|
||||||
|
* Adding attribute magic to your objects
|
||||||
|
|
||||||
|
Add prefixes and suffixes to defined attribute methods...
|
||||||
|
|
||||||
|
class Person
|
||||||
|
include ActiveModel::AttributeMethods
|
||||||
|
|
||||||
|
attribute_method_prefix 'clear_'
|
||||||
|
define_attribute_methods [:name, :age]
|
||||||
|
|
||||||
|
attr_accessor :name, :age
|
||||||
|
|
||||||
|
def clear_attribute(attr)
|
||||||
|
send("#{attr}=", nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
...gives you clear_name, clear_age.
|
||||||
|
|
||||||
|
{Learn more}[link:classes/ActiveModel/AttributeMethods.html]
|
||||||
|
|
||||||
* Adding callbacks to your objects
|
* Adding callbacks to your objects
|
||||||
|
|
||||||
class MyClass
|
class Person
|
||||||
extend ActiveModel::Callbacks
|
extend ActiveModel::Callbacks
|
||||||
define_model_callbacks :create
|
define_model_callbacks :create
|
||||||
|
|
||||||
|
@ -32,7 +53,7 @@ functionality from the following modules:
|
||||||
|
|
||||||
* For classes that already look like an Active Record object
|
* For classes that already look like an Active Record object
|
||||||
|
|
||||||
class MyClass
|
class Person
|
||||||
include ActiveModel::Conversion
|
include ActiveModel::Conversion
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,51 @@ module ActiveModel
|
||||||
class MissingAttributeError < NoMethodError
|
class MissingAttributeError < NoMethodError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# <tt>ActiveModel::AttributeMethods</tt> 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:
|
||||||
|
#
|
||||||
|
# * <tt>include ActiveModel::AttributeMethods</tt> in your object
|
||||||
|
# * Call each Attribute Method module method you want to add, such as
|
||||||
|
# attribute_method_suffix or attribute_method_prefix
|
||||||
|
# * Call <tt>define_attribute_methods</tt> 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
|
||||||
|
#
|
||||||
module AttributeMethods
|
module AttributeMethods
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
# Declare and check for suffixed attribute methods.
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
# Defines an "attribute" method (like +inheritance_column+ or
|
# Defines an "attribute" method (like +inheritance_column+ or
|
||||||
# +table_name+). A new (class) method will be created with the
|
# +table_name+). A new (class) method will be created with the
|
||||||
|
@ -22,12 +63,27 @@ module ActiveModel
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
#
|
#
|
||||||
# class A < ActiveRecord::Base
|
# class Person
|
||||||
|
#
|
||||||
|
# include ActiveModel::AttributeMethods
|
||||||
|
#
|
||||||
|
# cattr_accessor :primary_key
|
||||||
|
# cattr_accessor :inheritance_column
|
||||||
|
#
|
||||||
# define_attr_method :primary_key, "sysid"
|
# define_attr_method :primary_key, "sysid"
|
||||||
# define_attr_method( :inheritance_column ) do
|
# define_attr_method( :inheritance_column ) do
|
||||||
# original_inheritance_column + "_id"
|
# original_inheritance_column + "_id"
|
||||||
# end
|
# end
|
||||||
|
#
|
||||||
# end
|
# end
|
||||||
|
#
|
||||||
|
# Provivdes you with:
|
||||||
|
#
|
||||||
|
# AttributePerson.primary_key
|
||||||
|
# # => "sysid"
|
||||||
|
# AttributePerson.inheritance_column = 'address'
|
||||||
|
# AttributePerson.inheritance_column
|
||||||
|
# # => 'address_id'
|
||||||
def define_attr_method(name, value=nil, &block)
|
def define_attr_method(name, value=nil, &block)
|
||||||
sing = metaclass
|
sing = metaclass
|
||||||
sing.send :alias_method, "original_#{name}", name
|
sing.send :alias_method, "original_#{name}", name
|
||||||
|
@ -54,19 +110,25 @@ module ActiveModel
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
#
|
#
|
||||||
# class Person < ActiveRecord::Base
|
# class Person
|
||||||
|
#
|
||||||
|
# include ActiveModel::AttributeMethods
|
||||||
|
# attr_accessor :name
|
||||||
# attribute_method_prefix 'clear_'
|
# attribute_method_prefix 'clear_'
|
||||||
|
# define_attribute_methods [:name]
|
||||||
#
|
#
|
||||||
# private
|
# private
|
||||||
# def clear_attribute(attr)
|
#
|
||||||
# ...
|
# def clear_attribute(attr)
|
||||||
# end
|
# send("#{attr}=", nil)
|
||||||
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# person = Person.find(1)
|
# person = Person.new
|
||||||
# person.name # => 'Gem'
|
# person.name = "Bob"
|
||||||
|
# person.name # => "Bob"
|
||||||
# person.clear_name
|
# person.clear_name
|
||||||
# person.name # => ''
|
# person.name # => nil
|
||||||
def attribute_method_prefix(*prefixes)
|
def attribute_method_prefix(*prefixes)
|
||||||
attribute_method_matchers.concat(prefixes.map { |prefix| AttributeMethodMatcher.new :prefix => prefix })
|
attribute_method_matchers.concat(prefixes.map { |prefix| AttributeMethodMatcher.new :prefix => prefix })
|
||||||
undefine_attribute_methods
|
undefine_attribute_methods
|
||||||
|
@ -86,18 +148,24 @@ module ActiveModel
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
#
|
#
|
||||||
# class Person < ActiveRecord::Base
|
# class Person
|
||||||
|
#
|
||||||
|
# include ActiveModel::AttributeMethods
|
||||||
|
# attr_accessor :name
|
||||||
# attribute_method_suffix '_short?'
|
# attribute_method_suffix '_short?'
|
||||||
|
# define_attribute_methods [:name]
|
||||||
#
|
#
|
||||||
# private
|
# private
|
||||||
# def attribute_short?(attr)
|
#
|
||||||
# ...
|
# def attribute_short?(attr)
|
||||||
# end
|
# send(attr).length < 5
|
||||||
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# person = Person.find(1)
|
# person = Person.new
|
||||||
# person.name # => 'Gem'
|
# person.name = "Bob"
|
||||||
# person.name_short? # => true
|
# person.name # => "Bob"
|
||||||
|
# person.name_short? # => true
|
||||||
def attribute_method_suffix(*suffixes)
|
def attribute_method_suffix(*suffixes)
|
||||||
attribute_method_matchers.concat(suffixes.map { |suffix| AttributeMethodMatcher.new :suffix => suffix })
|
attribute_method_matchers.concat(suffixes.map { |suffix| AttributeMethodMatcher.new :suffix => suffix })
|
||||||
undefine_attribute_methods
|
undefine_attribute_methods
|
||||||
|
@ -118,16 +186,21 @@ module ActiveModel
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
#
|
#
|
||||||
# class Person < ActiveRecord::Base
|
# class Person
|
||||||
|
#
|
||||||
|
# include ActiveModel::AttributeMethods
|
||||||
|
# attr_accessor :name
|
||||||
# attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
|
# attribute_method_affix :prefix => 'reset_', :suffix => '_to_default!'
|
||||||
|
# define_attribute_methods [:name]
|
||||||
#
|
#
|
||||||
# private
|
# private
|
||||||
# def reset_attribute_to_default!(attr)
|
#
|
||||||
# ...
|
# def reset_attribute_to_default!(attr)
|
||||||
# end
|
# ...
|
||||||
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# person = Person.find(1)
|
# person = Person.new
|
||||||
# person.name # => 'Gem'
|
# person.name # => 'Gem'
|
||||||
# person.reset_name_to_default!
|
# person.reset_name_to_default!
|
||||||
# person.name # => 'Gemma'
|
# person.name # => 'Gemma'
|
||||||
|
@ -146,6 +219,30 @@ module ActiveModel
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Declares a the attributes that should be prefixed and suffixed by
|
||||||
|
# ActiveModel::AttributeMethods.
|
||||||
|
#
|
||||||
|
# To use, pass in an array of attribute names (as strings or symbols),
|
||||||
|
# be sure to declare +define_attribute_methods+ after you define any
|
||||||
|
# prefix, suffix or affix methods, or they will not hook in.
|
||||||
|
#
|
||||||
|
# class Person
|
||||||
|
#
|
||||||
|
# include ActiveModel::AttributeMethods
|
||||||
|
# attr_accessor :name, :age, :address
|
||||||
|
# attribute_method_prefix 'clear_'
|
||||||
|
#
|
||||||
|
# # Call to define_attribute_methods must appear after the
|
||||||
|
# # attribute_method_prefix, attribute_method_suffix or
|
||||||
|
# # attribute_method_affix declares.
|
||||||
|
# define_attribute_methods [:name, :age, :address]
|
||||||
|
#
|
||||||
|
# private
|
||||||
|
#
|
||||||
|
# def clear_attribute(attr)
|
||||||
|
# ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
def define_attribute_methods(attr_names)
|
def define_attribute_methods(attr_names)
|
||||||
return if attribute_methods_generated?
|
return if attribute_methods_generated?
|
||||||
attr_names.each do |attr_name|
|
attr_names.each do |attr_name|
|
||||||
|
@ -168,6 +265,7 @@ module ActiveModel
|
||||||
@attribute_methods_generated = true
|
@attribute_methods_generated = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Removes all the preiously dynamically defined methods from the class
|
||||||
def undefine_attribute_methods
|
def undefine_attribute_methods
|
||||||
generated_attribute_methods.module_eval do
|
generated_attribute_methods.module_eval do
|
||||||
instance_methods.each { |m| undef_method(m) }
|
instance_methods.each { |m| undef_method(m) }
|
||||||
|
@ -183,6 +281,7 @@ module ActiveModel
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if the attribute methods defined have been generated.
|
||||||
def attribute_methods_generated?
|
def attribute_methods_generated?
|
||||||
@attribute_methods_generated ||= nil
|
@attribute_methods_generated ||= nil
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue