aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/README.rdoc
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel/README.rdoc')
-rw-r--r--activemodel/README.rdoc206
1 files changed, 206 insertions, 0 deletions
diff --git a/activemodel/README.rdoc b/activemodel/README.rdoc
new file mode 100644
index 0000000000..6f162ef408
--- /dev/null
+++ b/activemodel/README.rdoc
@@ -0,0 +1,206 @@
+= Active Model - defined interfaces for Rails
+
+Prior to Rails 3.0, if a plugin or gem developer wanted to be able 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 look like Active Record. This generated code
+duplication and fragile applications that broke on upgrades.
+
+Active Model is a solution for this problem.
+
+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
+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
+
+ class Person
+ extend ActiveModel::Callbacks
+ define_model_callbacks :create
+
+ def create
+ _run_create_callbacks do
+ # Your create action methods here
+ end
+ end
+ end
+
+ ...gives you before_create, around_create and after_create class methods that
+ wrap your create method.
+
+ {Learn more}[link:classes/ActiveModel/CallBacks.html]
+
+* For classes that already look like an Active Record object
+
+ class Person
+ include ActiveModel::Conversion
+ end
+
+ ...returns the class itself when sent :to_model
+
+ {Learn more}[link:classes/ActiveModel/Conversion.html]
+
+* Tracking changes in your object
+
+ Provides all the value tracking features implemented by ActiveRecord...
+
+ 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+ support to your object
+
+ Provides the error messages to allow your object 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 ErrorsPerson.human_attribute_name(attr, options = {})
+ "Name"
+ end
+
+ end
+
+ ... gives you...
+
+ person.errors.full_messages
+ # => ["Name Can not be nil"]
+ person.errors.full_messages
+ # => ["Name Can not be nil"]
+
+ {Learn more}[link:classes/ActiveModel/Errors.html]
+
+* Testing the compliance of your object
+
+ Use ActiveModel::Lint to test the compliance of your object to the
+ basic ActiveModel API...
+
+ {Learn more}[link:classes/ActiveModel/Lint/Tests.html]
+
+* Providing a human face to your object
+
+ ActiveModel::Naming provides your model with the model_name convention
+ and a human_name attribute...
+
+ class NamedPerson
+ extend ActiveModel::Naming
+ end
+
+ ...gives you...
+
+ NamedPerson.model_name #=> "NamedPerson"
+ NamedPerson.model_name.human #=> "Named person"
+
+ {Learn more}[link:classes/ActiveModel/Naming.html]
+
+* Adding observer support to your objects
+
+ ActiveModel::Observers allows your object to implement the Observer
+ pattern in a Rails App and take advantage of all the standard observer
+ functions.
+
+ {Learn more}[link:classes/ActiveModel/Observer.html]
+
+* Making your object 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 # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
+
+ {Learn more}[link:classes/ActiveModel/Serialization.html]
+
+* Integrating with Rail's internationalization (i18n) handling through
+ ActiveModel::Translations...
+
+ class Person
+ extend ActiveModel::Translation
+ end
+
+ {Learn more}[link:classes/ActiveModel/Translation.html]
+
+* Providing a full Validation stack for your objects...
+
+ 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]
+
+* Make custom validators
+
+ class Person
+ 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]