diff options
Diffstat (limited to 'activemodel/README.rdoc')
-rw-r--r-- | activemodel/README.rdoc | 206 |
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] |