aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/README
diff options
context:
space:
mode:
authorMikel Lindsaar <raasdnil@gmail.com>2010-02-01 10:08:20 +1100
committerMikel Lindsaar <raasdnil@gmail.com>2010-02-01 10:08:20 +1100
commita07d0f87863e01ef931c87bd35bd36c564c20cd3 (patch)
tree308f9e66ad1164cb4a8d3cd9ab9d6263a4828b0d /activemodel/README
parentc493370f332715dee0ef795a66e896d7f0471cbe (diff)
downloadrails-a07d0f87863e01ef931c87bd35bd36c564c20cd3.tar.gz
rails-a07d0f87863e01ef931c87bd35bd36c564c20cd3.tar.bz2
rails-a07d0f87863e01ef931c87bd35bd36c564c20cd3.zip
Full update on ActiveModel documentation
Diffstat (limited to 'activemodel/README')
-rw-r--r--activemodel/README211
1 files changed, 185 insertions, 26 deletions
diff --git a/activemodel/README b/activemodel/README
index 7c9c754a8e..0d6fd1f21c 100644
--- a/activemodel/README
+++ b/activemodel/README
@@ -1,45 +1,68 @@
= 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 callbacks to your class
-
- class MyClass
- 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.
+
+* 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 MyClass
+
+ 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
@@ -52,6 +75,142 @@ functionality from the following modules:
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]
+
+
+* Turning your object into a finite State Machine
+
+ ActiveModel::StateMachine provides a clean way to include all the methods
+ you need to transform your object into a finite State Machine...
+
+ light = TrafficLight.new
+ light.current_state #=> :red
+ light.change_color! #=> true
+ light.current_state #=> :green
+
+ {Learn more}[link:classes/ActiveModel/StateMachine.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(: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]