= 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-ActiveRecord models, for example. Active Model also helps 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.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 The ActiveModel::Dirty module allows for tracking attribute changes: person = Person.new person.name # => nil person.changed? # => false person.name = 'bob' person.changed? # => true person.changed # => ['name'] person.changes # => { 'name' => [nil, 'bob'] } 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, "can not be nil") if name.nil? end def self.human_attribute_name(attr, options = {}) "Name" end end person.errors.full_messages # => ["Name can not be nil"] {Learn more}[link:classes/ActiveModel/Errors.html] * Model name introspection class NamedPerson extend ActiveModel::Naming end NamedPerson.model_name # => "NamedPerson" NamedPerson.model_name.human # => "Named person" {Learn more}[link:classes/ActiveModel/Naming.html] * Observer support ActiveModel::Observers allows your object to implement the Observer pattern in a Rails App and take advantage of all the standard observer functions. class PersonObserver < ActiveModel::Observer def after_create(person) person.logger.info("New person added!") end def after_destroy(person) person.logger.warn("Person with an id of #{person.id} was destroyed!") end end {Learn more}[link:classes/ActiveModel/Observer.html] * Making objects serializable ActiveModel::Serialization provides a standard interface for your object to provide +to_json+ or +to_xml+ serialization. s = SerialPerson.new s.serializable_hash # => {"name"=>nil} s.to_json # => "{\"name\":null}" 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 ValidatorPerson include ActiveModel::Validations validates_with HasNameValidator attr_accessor :name end class HasNameValidator < ActiveModel::Validator def validate(record) record.errors[:name] = "must exist" if record.name.blank? end 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 and feature requests can be filed with the rest for the Ruby on Rails project here: * https://github.com/rails/rails/issues