= Active Model -- model interfaces for Rails
Active Model provides a known set of interfaces for usage in model classes.
They allow for Action Pack helpers to interact with non-Active Record models,
for example. Active Model also helps with building custom ORMs for use outside of
the Rails framework.
Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
interact with Action Pack helpers, it was required to either copy chunks of
code from Rails, or monkey patch entire helpers to make them handle objects
that did not exactly conform to the Active Record interface. This would result
in code duplication and fragile applications that broke on upgrades. Active
Model solves this by defining an explicit API. You can read more about the
API in ActiveModel::Lint::Tests.
Active Model provides a default module that implements the basic API required
to integrate with Action Pack out of the box: ActiveModel::Model.
    class Person
      include ActiveModel::Model
      attr_accessor :name, :age
      validates_presence_of :name
    end
    person = Person.new(name: 'bob', age: '18')
    person.name   # => 'bob'
    person.age    # => '18'
    person.valid? # => true
It includes model name introspections, conversions, translations and
validations, resulting in a class suitable to be used with Action Pack.
See ActiveModel::Model for more examples.
Active Model also provides the following functionality to have ORM-like
behavior out of the box:
* Add attribute magic to objects
    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
  
    person = Person.new
    person.clear_name
    person.clear_age
  {Learn more}[link:classes/ActiveModel/AttributeMethods.html]
* Callbacks for certain operations
    class Person
      extend ActiveModel::Callbacks
      define_model_callbacks :create
      def create
        run_callbacks :create do
          # Your create action methods here
        end
      end
    end
  This generates +before_create+, +around_create+ and +after_create+
  class methods that wrap your create method.
  {Learn more}[link:classes/ActiveModel/Callbacks.html]
* Tracking value changes
    class Person
      include ActiveModel::Dirty
      define_attribute_methods :name
      def name
        @name
      end
      def name=(val)
        name_will_change! unless val == @name
        @name = val
      end
      def save
        # do persistence work
        changes_applied
      end
    end
    person = Person.new
    person.name             # => nil
    person.changed?         # => false
    person.name = 'bob'
    person.changed?         # => true
    person.changed          # => ['name']
    person.changes          # => { 'name' => [nil, 'bob'] }
    person.save
    person.name = 'robert'
    person.save
    person.previous_changes # => {'name' => ['bob, 'robert']}
  {Learn more}[link:classes/ActiveModel/Dirty.html]
* Adding +errors+ interface to objects
  Exposing error messages allows objects to interact with Action Pack
  helpers seamlessly.
    class Person
      def initialize
        @errors = ActiveModel::Errors.new(self)
      end
      attr_accessor :name
      attr_reader   :errors
      def validate!
        errors.add(:name, "cannot be nil") if name.nil?
      end
      def self.human_attribute_name(attr, options = {})
        "Name"
      end
    end
  
    person = Person.new
    person.name = nil
    person.validate!
    person.errors.full_messages
    # => ["Name cannot be nil"]
  {Learn more}[link:classes/ActiveModel/Errors.html]
* Model name introspection
    class NamedPerson
      extend ActiveModel::Naming
    end
    NamedPerson.model_name.name   # => "NamedPerson"
    NamedPerson.model_name.human  # => "Named person"
  {Learn more}[link:classes/ActiveModel/Naming.html]
* Making objects serializable
  ActiveModel::Serialization provides a standard interface for your object
  to provide +to_json+ or +to_xml+ serialization.
    class SerialPerson
      include ActiveModel::Serialization
      attr_accessor :name
      def attributes
        {'name' => name}
      end
    end
    s = SerialPerson.new
    s.serializable_hash   # => {"name"=>nil}
    class SerialPerson
      include ActiveModel::Serializers::JSON
    end
    s = SerialPerson.new
    s.to_json             # => "{\"name\":null}"
    class SerialPerson
      include ActiveModel::Serializers::Xml
    end
    s = SerialPerson.new
    s.to_xml              # => "\n "My attribute"
  {Learn more}[link:classes/ActiveModel/Translation.html]
* Validation support
    class Person
      include ActiveModel::Validations
      attr_accessor :first_name, :last_name
      validates_each :first_name, :last_name do |record, attr, value|
        record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
      end
    end
    person = Person.new
    person.first_name = 'zoolander'
    person.valid?  # => false
  {Learn more}[link:classes/ActiveModel/Validations.html]
* Custom validators
  
    class HasNameValidator < ActiveModel::Validator
      def validate(record)
        record.errors[:name] = "must exist" if record.name.blank?
      end
    end
    class ValidatorPerson
      include ActiveModel::Validations
      validates_with HasNameValidator
      attr_accessor :name
    end
    p = ValidatorPerson.new
    p.valid?                  # =>  false
    p.errors.full_messages    # => ["Name must exist"]
    p.name = "Bob"
    p.valid?                  # =>  true
  {Learn more}[link:classes/ActiveModel/Validator.html]
== Download and installation
The latest version of Active Model can be installed with RubyGems:
  % [sudo] gem install activemodel
Source code can be downloaded as part of the Rails project on GitHub
* https://github.com/rails/rails/tree/master/activemodel
== License
Active Model is released under the MIT license:
* http://www.opensource.org/licenses/MIT
== Support
API documentation is at
* http://api.rubyonrails.org
Bug reports can be filed for the Ruby on Rails project here:
* https://github.com/rails/rails/issues
Feature requests should be discussed on the rails-core mailing list here:
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core