aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/lib')
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb127
-rw-r--r--activemodel/lib/active_model/callbacks.rb50
-rw-r--r--activemodel/lib/active_model/validations.rb17
3 files changed, 133 insertions, 61 deletions
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index 16fcf14009..f30d00b355 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -3,32 +3,32 @@ require 'active_support/core_ext/class/attribute'
require 'active_support/deprecation'
module ActiveModel
+ # Raised when an attribute is not defined.
class MissingAttributeError < NoMethodError
end
# == Active Model Attribute Methods
#
- # <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+.
+ # <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 to:
#
- # * <tt>include ActiveModel::AttributeMethods</tt> in your object
+ # * <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
+ # +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_affix prefix: 'reset_', suffix: '_to_default!'
# attribute_method_suffix '_contrived?'
# attribute_method_prefix 'clear_'
- # define_attribute_methods 'name'
+ # define_attribute_methods :name
#
# attr_accessor :name
#
@@ -43,17 +43,16 @@ module ActiveModel
# end
#
# def reset_attribute_to_default!(attr)
- # send("#{attr}=", "Default Name")
+ # send("#{attr}=", 'Default Name')
# end
# end
#
# Note that whenever you include ActiveModel::AttributeMethods in your class,
- # it requires you to implement an <tt>attributes</tt> method which returns a hash
+ # 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.
- #
module AttributeMethods
extend ActiveSupport::Concern
@@ -79,11 +78,9 @@ module ActiveModel
# An instance method <tt>#{prefix}attribute</tt> must exist and accept
# at least the +attr+ argument.
#
- # For example:
- #
# class Person
- #
# include ActiveModel::AttributeMethods
+ #
# attr_accessor :name
# attribute_method_prefix 'clear_'
# define_attribute_methods :name
@@ -96,7 +93,7 @@ module ActiveModel
# end
#
# person = Person.new
- # person.name = "Bob"
+ # person.name = 'Bob'
# person.name # => "Bob"
# person.clear_name
# person.name # => nil
@@ -114,14 +111,12 @@ module ActiveModel
#
# attribute#{suffix}(#{attr}, *args, &block)
#
- # An <tt>attribute#{suffix}</tt> instance method must exist and accept at least
- # the +attr+ argument.
- #
- # For example:
+ # An <tt>attribute#{suffix}</tt> instance method must exist and accept at
+ # least the +attr+ argument.
#
# class Person
- #
# include ActiveModel::AttributeMethods
+ #
# attr_accessor :name
# attribute_method_suffix '_short?'
# define_attribute_methods :name
@@ -134,7 +129,7 @@ module ActiveModel
# end
#
# person = Person.new
- # person.name = "Bob"
+ # person.name = 'Bob'
# person.name # => "Bob"
# person.name_short? # => true
def attribute_method_suffix(*suffixes)
@@ -155,13 +150,11 @@ module ActiveModel
# An <tt>#{prefix}attribute#{suffix}</tt> instance method must exist and
# accept at least the +attr+ argument.
#
- # For example:
- #
# 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
@@ -184,14 +177,27 @@ module ActiveModel
# Allows you to make aliases for attributes.
#
# class Person
+ # include ActiveModel::AttributeMethods
+ #
# attr_accessor :name
+ # attribute_method_suffix '_short?'
+ # define_attribute_methods :name
+ #
# alias_attribute :nickname, :name
+ #
+ # private
+ #
+ # def attribute_short?(attr)
+ # send(attr).length < 5
+ # end
# end
#
# person = Person.new
- # person.nickname = "Bob"
- # person.nickname # => "Bob"
- # person.name # => "Bob"
+ # person.name = 'Bob'
+ # person.name # => "Bob"
+ # person.nickname # => "Bob"
+ # person.name_short? # => true
+ # person.nickname_short? # => true
def alias_attribute(new_name, old_name)
self.attribute_aliases = attribute_aliases.merge(new_name.to_s => old_name.to_s)
attribute_method_matchers.each do |matcher|
@@ -204,13 +210,13 @@ module ActiveModel
# Declares 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.
+ # To use, pass 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_'
#
@@ -229,6 +235,35 @@ module ActiveModel
attr_names.flatten.each { |attr_name| define_attribute_method(attr_name) }
end
+ # Declares an attribute that should be prefixed and suffixed by
+ # ActiveModel::AttributeMethods.
+ #
+ # To use, pass an attribute name (as string or symbol), be sure to declare
+ # +define_attribute_method+ after you define any prefix, suffix or affix
+ # method, or they will not hook in.
+ #
+ # class Person
+ # include ActiveModel::AttributeMethods
+ #
+ # attr_accessor :name
+ # attribute_method_suffix '_short?'
+ #
+ # # Call to define_attribute_method must appear after the
+ # # attribute_method_prefix, attribute_method_suffix or
+ # # attribute_method_affix declares.
+ # define_attribute_method :name
+ #
+ # private
+ #
+ # def attribute_short?(attr)
+ # send(attr).length < 5
+ # end
+ # end
+ #
+ # person = Person.new
+ # person.name = 'Bob'
+ # person.name # => "Bob"
+ # person.name_short? # => true
def define_attribute_method(attr_name)
attribute_method_matchers.each do |matcher|
method_name = matcher.method_name(attr_name)
@@ -246,7 +281,29 @@ module ActiveModel
attribute_method_matchers_cache.clear
end
- # Removes all the previously dynamically defined methods from the class
+ # Removes all the previously dynamically defined methods from the class.
+ #
+ # class Person
+ # include ActiveModel::AttributeMethods
+ #
+ # attr_accessor :name
+ # attribute_method_suffix '_short?'
+ # define_attribute_method :name
+ #
+ # private
+ #
+ # def attribute_short?(attr)
+ # send(attr).length < 5
+ # end
+ # end
+ #
+ # person = Person.new
+ # person.name = 'Bob'
+ # person.name_short? # => true
+ #
+ # Person.undefine_attribute_methods
+ #
+ # person.name_short? # => NoMethodError
def undefine_attribute_methods
generated_attribute_methods.module_eval do
instance_methods.each { |m| undef_method(m) }
diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb
index ebb4b51aa3..b8ba1a0a52 100644
--- a/activemodel/lib/active_model/callbacks.rb
+++ b/activemodel/lib/active_model/callbacks.rb
@@ -6,7 +6,7 @@ module ActiveModel
# Provides an interface for any class to have Active Record like callbacks.
#
# Like the Active Record methods, the callback chain is aborted as soon as
- # one of the methods in the chain returns false.
+ # one of the methods in the chain returns +false+.
#
# First, extend ActiveModel::Callbacks from the class you are creating:
#
@@ -18,9 +18,10 @@ module ActiveModel
#
# define_model_callbacks :create, :update
#
- # This will provide all three standard callbacks (before, around and after) for
- # both the :create and :update methods. To implement, you need to wrap the methods
- # you want callbacks on in a block so that the callbacks get a chance to fire:
+ # This will provide all three standard callbacks (before, around and after)
+ # for both the <tt>:create</tt> and <tt>:update</tt> methods. To implement,
+ # you need to wrap the methods you want callbacks on in a block so that the
+ # callbacks get a chance to fire:
#
# def create
# run_callbacks :create do
@@ -28,8 +29,8 @@ module ActiveModel
# end
# end
#
- # Then in your class, you can use the +before_create+, +after_create+ and +around_create+
- # methods, just as you would in an Active Record module.
+ # Then in your class, you can use the +before_create+, +after_create+ and
+ # +around_create+ methods, just as you would in an Active Record module.
#
# before_create :action_before_create
#
@@ -38,12 +39,12 @@ module ActiveModel
# end
#
# You can choose not to have all three callbacks by passing a hash to the
- # define_model_callbacks method.
+ # +define_model_callbacks+ method.
#
- # define_model_callbacks :create, :only => [:after, :before]
+ # define_model_callbacks :create, only: [:after, :before]
#
- # Would only create the after_create and before_create callback methods in your
- # class.
+ # Would only create the +after_create+ and +before_create+ callback methods in
+ # your class.
module Callbacks
def self.extended(base)
base.class_eval do
@@ -51,25 +52,27 @@ module ActiveModel
end
end
- # define_model_callbacks accepts the same options define_callbacks does, in case
- # you want to overwrite a default. Besides that, it also accepts an :only option,
- # where you can choose if you want all types (before, around or after) or just some.
+ # define_model_callbacks accepts the same options +define_callbacks+ does,
+ # in case you want to overwrite a default. Besides that, it also accepts an
+ # <tt>:only</tt> option, where you can choose if you want all types (before,
+ # around or after) or just some.
#
- # define_model_callbacks :initializer, :only => :after
+ # define_model_callbacks :initializer, only: :after
#
- # Note, the <tt>:only => <type></tt> hash will apply to all callbacks defined on
- # that method call. To get around this you can call the define_model_callbacks
+ # Note, the <tt>only: <type></tt> hash will apply to all callbacks defined
+ # on that method call. To get around this you can call the define_model_callbacks
# method as many times as you need.
#
- # define_model_callbacks :create, :only => :after
- # define_model_callbacks :update, :only => :before
- # define_model_callbacks :destroy, :only => :around
+ # define_model_callbacks :create, only: :after
+ # define_model_callbacks :update, only: :before
+ # define_model_callbacks :destroy, only: :around
#
- # Would create +after_create+, +before_update+ and +around_destroy+ methods only.
+ # Would create +after_create+, +before_update+ and +around_destroy+ methods
+ # only.
#
- # You can pass in a class to before_<type>, after_<type> and around_<type>, in which
- # case the callback will call that class's <action>_<type> method passing the object
- # that the callback is being called on.
+ # You can pass in a class to before_<type>, after_<type> and around_<type>,
+ # in which case the callback will call that class's <action>_<type> method
+ # passing the object that the callback is being called on.
#
# class MyModel
# extend ActiveModel::Callbacks
@@ -83,7 +86,6 @@ module ActiveModel
# # obj is the MyModel instance that the callback is being called on
# end
# end
- #
def define_model_callbacks(*callbacks)
options = callbacks.extract_options!
options = {
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 06eebf79d9..cd596e37d2 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -38,7 +38,6 @@ module ActiveModel
# Note that <tt>ActiveModel::Validations</tt> automatically adds an +errors+ method
# to your instances initialized with a new <tt>ActiveModel::Errors</tt> object, so
# there is no need for you to do this manually.
- #
module Validations
extend ActiveSupport::Concern
@@ -153,6 +152,21 @@ module ActiveModel
# List all validators that are being used to validate the model using
# +validates_with+ method.
+ #
+ # class Person
+ # include ActiveModel::Validations
+ #
+ # validates_with MyValidator
+ # validates_with OtherValidator, on: :create
+ # validates_with StrictValidator, strict: true
+ # end
+ #
+ # Person.validators
+ # # => [
+ # # #<MyValidator:0x007fbff403e808 @options={}>,
+ # # #<OtherValidator:0x007fbff403d930 @options={:on=>:create}>,
+ # # #<StrictValidator:0x007fbff3204a30 @options={:strict=>true}>
+ # # ]
def validators
_validators.values.flatten.uniq
end
@@ -221,7 +235,6 @@ module ActiveModel
# @data[key]
# end
# end
- #
alias :read_attribute_for_validation :send
protected