README.rdoc 6.0 KB
Newer Older
M
Mislav Marohnić 已提交
1 2 3 4 5 6 7 8 9 10
= 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
R
R.T. Lechow 已提交
11
that did not exactly conform to the Active Record interface. This would result
J
José Valim 已提交
12 13 14
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.
M
Mislav Marohnić 已提交
15

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
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? # => false

It includes model name instrospection, conversions, translations and
validations, resulting in a class suitable to be used with ActionPack.
See +ActiveModel::Model+ for more examples.

J
José Valim 已提交
35 36
Active Model also provides the following functionality to have ORM-like
behavior out of the box:
M
Mislav Marohnić 已提交
37 38 39

* Add attribute magic to objects

40 41
    class Person
      include ActiveModel::AttributeMethods
42

43 44
      attribute_method_prefix 'clear_'
      define_attribute_methods [:name, :age]
45

46
      attr_accessor :name, :age
47

48 49 50 51
      def clear_attribute(attr)
        send("#{attr}=", nil)
      end
    end
52

M
Mislav Marohnić 已提交
53 54
    person.clear_name
    person.clear_age
55

56
  {Learn more}[link:classes/ActiveModel/AttributeMethods.html]
57

M
Mislav Marohnić 已提交
58
* Callbacks for certain operations
M
Mikel Lindsaar 已提交
59

60
    class Person
M
Mikel Lindsaar 已提交
61 62
      extend ActiveModel::Callbacks
      define_model_callbacks :create
63

M
Mikel Lindsaar 已提交
64
      def create
65
        run_callbacks :create do
M
Mikel Lindsaar 已提交
66 67 68 69
          # Your create action methods here
        end
      end
    end
70

M
Mislav Marohnić 已提交
71 72
  This generates +before_create+, +around_create+ and +after_create+
  class methods that wrap your create method.
73

74
  {Learn more}[link:classes/ActiveModel/CallBacks.html]
75

M
Mislav Marohnić 已提交
76
* Tracking value changes
77

M
Mislav Marohnić 已提交
78
  The ActiveModel::Dirty module allows for tracking attribute changes:
M
Mikel Lindsaar 已提交
79

80 81
    person = Person.new
    person.name # => nil
M
Mikel Lindsaar 已提交
82 83 84 85
    person.changed? # => false
    person.name = 'bob'
    person.changed? # => true
    person.changed # => ['name']
86
    person.changes # => { 'name' => [nil, 'bob'] }
M
Mikel Lindsaar 已提交
87 88 89
    person.name = 'robert'
    person.save
    person.previous_changes # => {'name' => ['bob, 'robert']}
90

91 92
  {Learn more}[link:classes/ActiveModel/Dirty.html]

M
Mislav Marohnić 已提交
93
* Adding +errors+ interface to objects
94

M
Mislav Marohnić 已提交
95 96
  Exposing error messages allows objects to interact with Action Pack
  helpers seamlessly.
97

98
    class Person
99

100 101 102
      def initialize
        @errors = ActiveModel::Errors.new(self)
      end
103

104 105
      attr_accessor :name
      attr_reader   :errors
106

107
      def validate!
V
Vijay Dev 已提交
108
        errors.add(:name, "can not be nil") if name.nil?
109
      end
110

C
Carlos Antonio da Silva 已提交
111
      def self.human_attribute_name(attr, options = {})
112 113 114
        "Name"
      end
    end
115

116
    person.errors.full_messages
V
Vijay Dev 已提交
117
    # => ["Name can not be nil"]
118

119
    person.errors.full_messages
V
Vijay Dev 已提交
120
    # => ["Name can not be nil"]
121 122

  {Learn more}[link:classes/ActiveModel/Errors.html]
123

M
Mislav Marohnić 已提交
124
* Model name introspection
125

126 127 128
    class NamedPerson
      extend ActiveModel::Naming
    end
129

P
Paco Guzman 已提交
130 131
    NamedPerson.model_name        # => "NamedPerson"
    NamedPerson.model_name.human  # => "Named person"
132 133 134

  {Learn more}[link:classes/ActiveModel/Naming.html]

M
Mislav Marohnić 已提交
135
* Observer support
136

M
Mislav Marohnić 已提交
137 138 139
  ActiveModel::Observers allows your object to implement the Observer
  pattern in a Rails App and take advantage of all the standard observer
  functions.
140

141
  {Learn more}[link:classes/ActiveModel/Observer.html]
142

M
Mislav Marohnić 已提交
143
* Making objects serializable
144

M
Mislav Marohnić 已提交
145 146
  ActiveModel::Serialization provides a standard interface for your object
  to provide +to_json+ or +to_xml+ serialization.
147

148 149 150 151
    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...
152

153
  {Learn more}[link:classes/ActiveModel/Serialization.html]
M
Mikel Lindsaar 已提交
154

M
Mislav Marohnić 已提交
155
* Internationalization (i18n) support
156 157 158 159

    class Person
      extend ActiveModel::Translation
    end
160

M
Mislav Marohnić 已提交
161
    Person.human_attribute_name('my_attribute')
P
Paco Guzman 已提交
162
    # => "My attribute"
163

164
  {Learn more}[link:classes/ActiveModel/Translation.html]
165

M
Mislav Marohnić 已提交
166
* Validation support
167 168 169 170 171 172 173 174 175 176 177

   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

178 179
   person = Person.new
   person.first_name = 'zoolander'
P
Paco Guzman 已提交
180
   person.valid?  # => false
181 182

  {Learn more}[link:classes/ActiveModel/Validations.html]
183

M
Mislav Marohnić 已提交
184
* Custom validators
185

C
Carlos Antonio da Silva 已提交
186
   class ValidatorPerson
187 188 189 190
     include ActiveModel::Validations
     validates_with HasNameValidator
     attr_accessor :name
   end
191

192 193
   class HasNameValidator < ActiveModel::Validator
     def validate(record)
C
Carlos Antonio da Silva 已提交
194
       record.errors[:name] = "must exist" if record.name.blank?
195 196
     end
   end
197

198
   p = ValidatorPerson.new
P
Paco Guzman 已提交
199 200
   p.valid?                  # =>  false
   p.errors.full_messages    # => ["Name must exist"]
201
   p.name = "Bob"
P
Paco Guzman 已提交
202
   p.valid?                  # =>  true
203 204

  {Learn more}[link:classes/ActiveModel/Validator.html]
J
José Valim 已提交
205

206 207 208

== Download and installation

W
Waynn Lue 已提交
209
The latest version of Active Model can be installed with RubyGems:
210 211 212 213 214

  % [sudo] gem install activemodel

Source code can be downloaded as part of the Rails project on GitHub

215
* https://github.com/rails/rails/tree/master/activemodel
216 217 218 219


== License

220 221 222
Active Model is released under the MIT license:

* http://www.opensource.org/licenses/MIT
223 224 225 226 227 228 229 230 231 232 233


== 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