README.rdoc 6.1 KB
Newer Older
M
Mislav Marohnić 已提交
1 2 3
= Active Model -- model interfaces for Rails

Active Model provides a known set of interfaces for usage in model classes.
4
They allow for Action Pack helpers to interact with non-Active Record models,
W
Waynn Lue 已提交
5
for example. Active Model also helps with building custom ORMs for use outside of
M
Mislav Marohnić 已提交
6 7 8 9 10
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
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
14
API in <tt>ActiveModel::Lint::Tests</tt>.
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

    class Person
      include ActiveModel::Model

      attr_accessor :name, :age
      validates_presence_of :name
    end

26
    person = Person.new(name: 'bob', age: '18')
27
    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
      attribute_method_prefix 'clear_'
44
      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 79 80 81 82
    class Person
      include ActiveModel::Dirty

      attr_accessor :name
    end
M
Mikel Lindsaar 已提交
83

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

95
  {Learn more}[link:classes/ActiveModel/Dirty.html]
96

M
Mislav Marohnić 已提交
97
* Adding +errors+ interface to objects
98

M
Mislav Marohnić 已提交
99 100
  Exposing error messages allows objects to interact with Action Pack
  helpers seamlessly.
101

102
    class Person
103

104 105 106
      def initialize
        @errors = ActiveModel::Errors.new(self)
      end
107

108 109
      attr_accessor :name
      attr_reader   :errors
110

111
      def validate!
V
Vijay Dev 已提交
112
        errors.add(:name, "can not be nil") if name.nil?
113
      end
114

C
Carlos Antonio da Silva 已提交
115
      def self.human_attribute_name(attr, options = {})
116 117 118
        "Name"
      end
    end
119

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

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

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

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

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

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

M
Mislav Marohnić 已提交
136
* Making objects serializable
137

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

141 142 143 144 145 146 147 148 149 150
    class SerialPerson
      include ActiveModel::Serialization

      attr_accessor :name

      def attributes
        {'name' => name}
      end
    end

151 152
    s = SerialPerson.new
    s.serializable_hash   # => {"name"=>nil}
153 154 155 156 157 158

    class SerialPerson
      include ActiveModel::Serializers::JSON
    end

    s = SerialPerson.new
159
    s.to_json             # => "{\"name\":null}"
160 161 162 163 164 165

    class SerialPerson
      include ActiveModel::Serializers::Xml
    end

    s = SerialPerson.new
166
    s.to_xml              # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
167

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

M
Mislav Marohnić 已提交
170
* Internationalization (i18n) support
171 172 173 174

    class Person
      extend ActiveModel::Translation
    end
175

M
Mislav Marohnić 已提交
176
    Person.human_attribute_name('my_attribute')
P
Paco Guzman 已提交
177
    # => "My attribute"
178

179
  {Learn more}[link:classes/ActiveModel/Translation.html]
180

M
Mislav Marohnić 已提交
181
* Validation support
182 183 184 185 186 187 188 189 190 191 192

   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

193 194
   person = Person.new
   person.first_name = 'zoolander'
P
Paco Guzman 已提交
195
   person.valid?  # => false
196

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

M
Mislav Marohnić 已提交
199
* Custom validators
200

C
Carlos Antonio da Silva 已提交
201
   class ValidatorPerson
202 203 204 205
     include ActiveModel::Validations
     validates_with HasNameValidator
     attr_accessor :name
   end
206

207 208
   class HasNameValidator < ActiveModel::Validator
     def validate(record)
C
Carlos Antonio da Silva 已提交
209
       record.errors[:name] = "must exist" if record.name.blank?
210 211
     end
   end
212

213
   p = ValidatorPerson.new
P
Paco Guzman 已提交
214 215
   p.valid?                  # =>  false
   p.errors.full_messages    # => ["Name must exist"]
216
   p.name = "Bob"
P
Paco Guzman 已提交
217
   p.valid?                  # =>  true
218

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

221 222 223

== Download and installation

W
Waynn Lue 已提交
224
The latest version of Active Model can be installed with RubyGems:
225 226 227 228 229

  % [sudo] gem install activemodel

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

230
* https://github.com/rails/rails/tree/master/activemodel
231 232 233 234


== License

235 236 237
Active Model is released under the MIT license:

* http://www.opensource.org/licenses/MIT
238 239 240 241 242 243 244 245 246 247 248


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