README in activemodel-3.0.0.beta4 vs README in activemodel-3.0.pre
- old
+ new
@@ -1,205 +1,21 @@
-= 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:
+Active Model
+==============
-* Adding attribute magic to your objects
+Totally experimental library that aims to extract common model mixins from
+ActiveRecord for use in ActiveResource (and other similar libraries).
+This is in a very rough state (no autotest or spec rake tasks set up yet),
+so please excuse the mess.
- 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
+Here's what I plan to extract:
+ * ActiveModel::Observing
+ * ActiveModel::Callbacks
+ * ActiveModel::Validations
- 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 ActiveResource params and ActiveRecord options
+ * ActiveModel::Scoping
-* For classes that already look like an Active Record object
+ # to_json, to_xml, etc
+ * ActiveModel::Serialization
- 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(: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]
+I'm trying to keep ActiveRecord compatibility where possible, but I'm
+annotating the spots where I'm diverging a bit.
\ No newline at end of file