README.rdoc 6.2 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
Active Model provides a default module that implements the basic API required
17
to integrate with Action Pack out of the box: <tt>ActiveModel::Model</tt>.
18 19 20 21 22 23 24 25 26 27

    class Person
      include ActiveModel::Model

      attr_accessor :name, :age
      validates_presence_of :name
    end

    person = Person.new(:name => 'bob', :age => '18')
    person.name # => 'bob'
A
Alexey Vakhov 已提交
28
    person.age # => '18'
29
    person.valid? # => true
30

31 32
It includes model name introspections, conversions, translations and
validations, resulting in a class suitable to be used with Action Pack.
V
Vijay Dev 已提交
33
See <tt>ActiveModel::Model</tt> for more examples.
34

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

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
  {Learn more}[link:classes/ActiveModel/Dirty.html]
92

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
  {Learn more}[link:classes/ActiveModel/Errors.html]
120

M
Mislav Marohnić 已提交
121
* Model name introspection
122

123 124 125
    class NamedPerson
      extend ActiveModel::Naming
    end
126

P
Paco Guzman 已提交
127 128
    NamedPerson.model_name        # => "NamedPerson"
    NamedPerson.model_name.human  # => "Named person"
129

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

M
Mislav Marohnić 已提交
132
* Observer support
133

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

F
Francesco Rodriguez 已提交
138 139 140 141 142 143 144 145 146 147
    class PersonObserver < ActiveModel::Observer
      def after_create(person)
        person.logger.info("New person added!")
      end

      def after_destroy(person)
        person.logger.warn("Person with an id of #{person.id} was destroyed!")
      end
    end

148
  {Learn more}[link:classes/ActiveModel/Observer.html]
149

M
Mislav Marohnić 已提交
150
* Making objects serializable
151

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

155 156 157 158
    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...
159

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

M
Mislav Marohnić 已提交
162
* Internationalization (i18n) support
163 164 165 166

    class Person
      extend ActiveModel::Translation
    end
167

M
Mislav Marohnić 已提交
168
    Person.human_attribute_name('my_attribute')
P
Paco Guzman 已提交
169
    # => "My attribute"
170

171
  {Learn more}[link:classes/ActiveModel/Translation.html]
172

M
Mislav Marohnić 已提交
173
* Validation support
174 175 176 177 178 179 180 181 182 183 184

   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

185 186
   person = Person.new
   person.first_name = 'zoolander'
P
Paco Guzman 已提交
187
   person.valid?  # => false
188

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

M
Mislav Marohnić 已提交
191
* Custom validators
192

C
Carlos Antonio da Silva 已提交
193
   class ValidatorPerson
194 195 196 197
     include ActiveModel::Validations
     validates_with HasNameValidator
     attr_accessor :name
   end
198

199 200
   class HasNameValidator < ActiveModel::Validator
     def validate(record)
C
Carlos Antonio da Silva 已提交
201
       record.errors[:name] = "must exist" if record.name.blank?
202 203
     end
   end
204

205
   p = ValidatorPerson.new
P
Paco Guzman 已提交
206 207
   p.valid?                  # =>  false
   p.errors.full_messages    # => ["Name must exist"]
208
   p.name = "Bob"
P
Paco Guzman 已提交
209
   p.valid?                  # =>  true
210

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

213 214 215

== Download and installation

W
Waynn Lue 已提交
216
The latest version of Active Model can be installed with RubyGems:
217 218 219 220 221

  % [sudo] gem install activemodel

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

222
* https://github.com/rails/rails/tree/master/activemodel
223 224 225 226


== License

227 228 229
Active Model is released under the MIT license:

* http://www.opensource.org/licenses/MIT
230 231 232 233 234 235 236 237 238 239 240


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