rails 4.1.4 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -10
- data/guides/CHANGELOG.md +15 -25
- data/guides/Rakefile +5 -3
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_gem.rb +2 -2
- data/guides/bug_report_templates/action_controller_master.rb +3 -2
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +29 -21
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides.rb +2 -2
- data/guides/source/2_2_release_notes.md +1 -1
- data/guides/source/2_3_release_notes.md +4 -4
- data/guides/source/3_0_release_notes.md +8 -8
- data/guides/source/3_1_release_notes.md +5 -2
- data/guides/source/3_2_release_notes.md +6 -3
- data/guides/source/4_0_release_notes.md +6 -3
- data/guides/source/4_1_release_notes.md +10 -11
- data/guides/source/4_2_release_notes.md +850 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +2 -8
- data/guides/source/action_controller_overview.md +84 -10
- data/guides/source/action_mailer_basics.md +91 -28
- data/guides/source/action_view_overview.md +140 -130
- data/guides/source/active_job_basics.md +318 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +19 -18
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +135 -226
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +269 -259
- data/guides/source/active_record_validations.md +21 -12
- data/guides/source/active_support_core_extensions.md +113 -73
- data/guides/source/active_support_instrumentation.md +10 -7
- data/guides/source/api_documentation_guidelines.md +62 -16
- data/guides/source/asset_pipeline.md +264 -67
- data/guides/source/association_basics.md +81 -74
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +132 -29
- data/guides/source/constant_autoloading_and_reloading.md +1297 -0
- data/guides/source/contributing_to_ruby_on_rails.md +192 -112
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +448 -294
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +210 -189
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +339 -201
- data/guides/source/i18n.md +111 -68
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +109 -62
- data/guides/source/layout.html.erb +1 -4
- data/guides/source/layouts_and_rendering.md +18 -17
- data/guides/source/maintenance_policy.md +26 -4
- data/guides/source/nested_model_forms.md +7 -4
- data/guides/source/plugins.md +27 -27
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +12 -9
- data/guides/source/routing.md +100 -74
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +40 -34
- data/guides/source/testing.md +188 -117
- data/guides/source/upgrading_ruby_on_rails.md +284 -29
- data/guides/source/working_with_javascript_in_rails.md +18 -16
- data/guides/w3c_validator.rb +2 -0
- metadata +40 -94
- data/guides/code/getting_started/Gemfile +0 -40
- data/guides/code/getting_started/Gemfile.lock +0 -125
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -60
- data/guides/code/getting_started/public/422.html +0 -60
- data/guides/code/getting_started/public/500.html +0 -59
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -12
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
Active Model Basics
|
|
2
2
|
===================
|
|
3
3
|
|
|
4
|
-
This guide should provide you with all you need to get started using model
|
|
4
|
+
This guide should provide you with all you need to get started using model
|
|
5
|
+
classes. Active Model allows for Action Pack helpers to interact with
|
|
6
|
+
plain Ruby objects. Active Model also helps build custom ORMs for use
|
|
7
|
+
outside of the Rails framework.
|
|
5
8
|
|
|
6
|
-
After reading this guide, you will
|
|
9
|
+
After reading this guide, you will be able to add to plain Ruby objects:
|
|
10
|
+
|
|
11
|
+
* The ability to behave like an Active Record model.
|
|
12
|
+
* Callbacks and validations like Active Record.
|
|
13
|
+
* Serializers.
|
|
14
|
+
* Integration with the Rails internationalization (i18n) framework.
|
|
7
15
|
|
|
8
16
|
--------------------------------------------------------------------------------
|
|
9
17
|
|
|
10
18
|
Introduction
|
|
11
19
|
------------
|
|
12
20
|
|
|
13
|
-
Active Model is a library containing various modules used in developing
|
|
21
|
+
Active Model is a library containing various modules used in developing
|
|
22
|
+
classes that need some features present on Active Record.
|
|
23
|
+
Some of these modules are explained below.
|
|
14
24
|
|
|
15
|
-
###
|
|
25
|
+
### Attribute Methods
|
|
16
26
|
|
|
17
|
-
The AttributeMethods module can add custom prefixes and suffixes
|
|
27
|
+
The `ActiveModel::AttributeMethods` module can add custom prefixes and suffixes
|
|
28
|
+
on methods of a class. It is used by defining the prefixes and suffixes and
|
|
29
|
+
which methods on the object will use them.
|
|
18
30
|
|
|
19
31
|
```ruby
|
|
20
32
|
class Person
|
|
@@ -38,14 +50,17 @@ end
|
|
|
38
50
|
|
|
39
51
|
person = Person.new
|
|
40
52
|
person.age = 110
|
|
41
|
-
person.age_highest? # true
|
|
42
|
-
person.reset_age # 0
|
|
43
|
-
person.age_highest? # false
|
|
53
|
+
person.age_highest? # => true
|
|
54
|
+
person.reset_age # => 0
|
|
55
|
+
person.age_highest? # => false
|
|
44
56
|
```
|
|
45
57
|
|
|
46
58
|
### Callbacks
|
|
47
59
|
|
|
48
|
-
Callbacks gives Active Record style callbacks. This provides an
|
|
60
|
+
`ActiveModel::Callbacks` gives Active Record style callbacks. This provides an
|
|
61
|
+
ability to define callbacks which run at appropriate times.
|
|
62
|
+
After defining callbacks, you can wrap them with before, after and around
|
|
63
|
+
custom methods.
|
|
49
64
|
|
|
50
65
|
```ruby
|
|
51
66
|
class Person
|
|
@@ -69,7 +84,9 @@ end
|
|
|
69
84
|
|
|
70
85
|
### Conversion
|
|
71
86
|
|
|
72
|
-
If a class defines `persisted?` and `id` methods, then you can include the
|
|
87
|
+
If a class defines `persisted?` and `id` methods, then you can include the
|
|
88
|
+
`ActiveModel::Conversion` module in that class and call the Rails conversion
|
|
89
|
+
methods on objects of that class.
|
|
73
90
|
|
|
74
91
|
```ruby
|
|
75
92
|
class Person
|
|
@@ -92,11 +109,13 @@ person.to_param # => nil
|
|
|
92
109
|
|
|
93
110
|
### Dirty
|
|
94
111
|
|
|
95
|
-
An object becomes dirty when it has gone through one or more changes to its
|
|
112
|
+
An object becomes dirty when it has gone through one or more changes to its
|
|
113
|
+
attributes and has not been saved. `ActiveModel::Dirty` gives the ability to
|
|
114
|
+
check whether an object has been changed or not. It also has attribute based
|
|
115
|
+
accessor methods. Let's consider a Person class with attributes `first_name`
|
|
116
|
+
and `last_name`:
|
|
96
117
|
|
|
97
118
|
```ruby
|
|
98
|
-
require 'active_model'
|
|
99
|
-
|
|
100
119
|
class Person
|
|
101
120
|
include ActiveModel::Dirty
|
|
102
121
|
define_attribute_methods :first_name, :last_name
|
|
@@ -162,10 +181,11 @@ Track what was the previous value of the attribute.
|
|
|
162
181
|
|
|
163
182
|
```ruby
|
|
164
183
|
# attr_name_was accessor
|
|
165
|
-
person.first_name_was # =>
|
|
184
|
+
person.first_name_was # => nil
|
|
166
185
|
```
|
|
167
186
|
|
|
168
|
-
Track both previous and current value of the changed attribute. Returns an array
|
|
187
|
+
Track both previous and current value of the changed attribute. Returns an array
|
|
188
|
+
if changed, else returns nil.
|
|
169
189
|
|
|
170
190
|
```ruby
|
|
171
191
|
# attr_name_change
|
|
@@ -175,7 +195,8 @@ person.last_name_change # => nil
|
|
|
175
195
|
|
|
176
196
|
### Validations
|
|
177
197
|
|
|
178
|
-
Validations module adds the ability to class objects
|
|
198
|
+
`ActiveModel::Validations` module adds the ability to validate class objects
|
|
199
|
+
like in Active Record.
|
|
179
200
|
|
|
180
201
|
```ruby
|
|
181
202
|
class Person
|
|
@@ -188,7 +209,8 @@ class Person
|
|
|
188
209
|
validates! :token, presence: true
|
|
189
210
|
end
|
|
190
211
|
|
|
191
|
-
person = Person.new
|
|
212
|
+
person = Person.new
|
|
213
|
+
person.token = "2b1f325"
|
|
192
214
|
person.valid? # => false
|
|
193
215
|
person.name = 'vishnu'
|
|
194
216
|
person.email = 'me'
|
|
@@ -198,3 +220,335 @@ person.valid? # => true
|
|
|
198
220
|
person.token = nil
|
|
199
221
|
person.valid? # => raises ActiveModel::StrictValidationFailed
|
|
200
222
|
```
|
|
223
|
+
|
|
224
|
+
### Naming
|
|
225
|
+
|
|
226
|
+
`ActiveModel::Naming` adds a number of class methods which make the naming and routing
|
|
227
|
+
easier to manage. The module defines the `model_name` class method which
|
|
228
|
+
will define a number of accessors using some `ActiveSupport::Inflector` methods.
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
class Person
|
|
232
|
+
extend ActiveModel::Naming
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
Person.model_name.name # => "Person"
|
|
236
|
+
Person.model_name.singular # => "person"
|
|
237
|
+
Person.model_name.plural # => "people"
|
|
238
|
+
Person.model_name.element # => "person"
|
|
239
|
+
Person.model_name.human # => "Person"
|
|
240
|
+
Person.model_name.collection # => "people"
|
|
241
|
+
Person.model_name.param_key # => "person"
|
|
242
|
+
Person.model_name.i18n_key # => :person
|
|
243
|
+
Person.model_name.route_key # => "people"
|
|
244
|
+
Person.model_name.singular_route_key # => "person"
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Model
|
|
248
|
+
|
|
249
|
+
`ActiveModel::Model` adds the ability to a class to work with Action Pack and
|
|
250
|
+
Action View right out of the box.
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
class EmailContact
|
|
254
|
+
include ActiveModel::Model
|
|
255
|
+
|
|
256
|
+
attr_accessor :name, :email, :message
|
|
257
|
+
validates :name, :email, :message, presence: true
|
|
258
|
+
|
|
259
|
+
def deliver
|
|
260
|
+
if valid?
|
|
261
|
+
# deliver email
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
When including `ActiveModel::Model` you get some features like:
|
|
268
|
+
|
|
269
|
+
- model name introspection
|
|
270
|
+
- conversions
|
|
271
|
+
- translations
|
|
272
|
+
- validations
|
|
273
|
+
|
|
274
|
+
It also gives you the ability to initialize an object with a hash of attributes,
|
|
275
|
+
much like any Active Record object.
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
email_contact = EmailContact.new(name: 'David',
|
|
279
|
+
email: 'david@example.com',
|
|
280
|
+
message: 'Hello World')
|
|
281
|
+
email_contact.name # => 'David'
|
|
282
|
+
email_contact.email # => 'david@example.com'
|
|
283
|
+
email_contact.valid? # => true
|
|
284
|
+
email_contact.persisted? # => false
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Any class that includes `ActiveModel::Model` can be used with `form_for`,
|
|
288
|
+
`render` and any other Action View helper methods, just like Active Record
|
|
289
|
+
objects.
|
|
290
|
+
|
|
291
|
+
### Serialization
|
|
292
|
+
|
|
293
|
+
`ActiveModel::Serialization` provides a basic serialization for your object.
|
|
294
|
+
You need to declare an attributes hash which contains the attributes you want to
|
|
295
|
+
serialize. Attributes must be strings, not symbols.
|
|
296
|
+
|
|
297
|
+
```ruby
|
|
298
|
+
class Person
|
|
299
|
+
include ActiveModel::Serialization
|
|
300
|
+
|
|
301
|
+
attr_accessor :name
|
|
302
|
+
|
|
303
|
+
def attributes
|
|
304
|
+
{'name' => nil}
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Now you can access a serialized hash of your object using the `serializable_hash`.
|
|
310
|
+
|
|
311
|
+
```ruby
|
|
312
|
+
person = Person.new
|
|
313
|
+
person.serializable_hash # => {"name"=>nil}
|
|
314
|
+
person.name = "Bob"
|
|
315
|
+
person.serializable_hash # => {"name"=>"Bob"}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### ActiveModel::Serializers
|
|
319
|
+
|
|
320
|
+
Rails provides two serializers `ActiveModel::Serializers::JSON` and
|
|
321
|
+
`ActiveModel::Serializers::Xml`. Both of these modules automatically include
|
|
322
|
+
the `ActiveModel::Serialization`.
|
|
323
|
+
|
|
324
|
+
##### ActiveModel::Serializers::JSON
|
|
325
|
+
|
|
326
|
+
To use the `ActiveModel::Serializers::JSON` you only need to change from
|
|
327
|
+
`ActiveModel::Serialization` to `ActiveModel::Serializers::JSON`.
|
|
328
|
+
|
|
329
|
+
```ruby
|
|
330
|
+
class Person
|
|
331
|
+
include ActiveModel::Serializers::JSON
|
|
332
|
+
|
|
333
|
+
attr_accessor :name
|
|
334
|
+
|
|
335
|
+
def attributes
|
|
336
|
+
{'name' => nil}
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
With the `as_json` you have a hash representing the model.
|
|
342
|
+
|
|
343
|
+
```ruby
|
|
344
|
+
person = Person.new
|
|
345
|
+
person.as_json # => {"name"=>nil}
|
|
346
|
+
person.name = "Bob"
|
|
347
|
+
person.as_json # => {"name"=>"Bob"}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
From a JSON string you define the attributes of the model.
|
|
351
|
+
You need to have the `attributes=` method defined on your class:
|
|
352
|
+
|
|
353
|
+
```ruby
|
|
354
|
+
class Person
|
|
355
|
+
include ActiveModel::Serializers::JSON
|
|
356
|
+
|
|
357
|
+
attr_accessor :name
|
|
358
|
+
|
|
359
|
+
def attributes=(hash)
|
|
360
|
+
hash.each do |key, value|
|
|
361
|
+
send("#{key}=", value)
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def attributes
|
|
366
|
+
{'name' => nil}
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Now it is possible to create an instance of person and set the attributes using `from_json`.
|
|
372
|
+
|
|
373
|
+
```ruby
|
|
374
|
+
json = { name: 'Bob' }.to_json
|
|
375
|
+
person = Person.new
|
|
376
|
+
person.from_json(json) # => #<Person:0x00000100c773f0 @name="Bob">
|
|
377
|
+
person.name # => "Bob"
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
##### ActiveModel::Serializers::Xml
|
|
381
|
+
|
|
382
|
+
To use the `ActiveModel::Serializers::Xml` you only need to change from
|
|
383
|
+
`ActiveModel::Serialization` to `ActiveModel::Serializers::Xml`.
|
|
384
|
+
|
|
385
|
+
```ruby
|
|
386
|
+
class Person
|
|
387
|
+
include ActiveModel::Serializers::Xml
|
|
388
|
+
|
|
389
|
+
attr_accessor :name
|
|
390
|
+
|
|
391
|
+
def attributes
|
|
392
|
+
{'name' => nil}
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
With the `to_xml` you have a XML representing the model.
|
|
398
|
+
|
|
399
|
+
```ruby
|
|
400
|
+
person = Person.new
|
|
401
|
+
person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name nil=\"true\"/>\n</person>\n"
|
|
402
|
+
person.name = "Bob"
|
|
403
|
+
person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<person>\n <name>Bob</name>\n</person>\n"
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
From a XML string you define the attributes of the model.
|
|
407
|
+
You need to have the `attributes=` method defined on your class:
|
|
408
|
+
|
|
409
|
+
```ruby
|
|
410
|
+
class Person
|
|
411
|
+
include ActiveModel::Serializers::Xml
|
|
412
|
+
|
|
413
|
+
attr_accessor :name
|
|
414
|
+
|
|
415
|
+
def attributes=(hash)
|
|
416
|
+
hash.each do |key, value|
|
|
417
|
+
send("#{key}=", value)
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def attributes
|
|
422
|
+
{'name' => nil}
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Now it is possible to create an instance of person and set the attributes using `from_xml`.
|
|
428
|
+
|
|
429
|
+
```ruby
|
|
430
|
+
xml = { name: 'Bob' }.to_xml
|
|
431
|
+
person = Person.new
|
|
432
|
+
person.from_xml(xml) # => #<Person:0x00000100c773f0 @name="Bob">
|
|
433
|
+
person.name # => "Bob"
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Translation
|
|
437
|
+
|
|
438
|
+
`ActiveModel::Translation` provides integration between your object and the Rails
|
|
439
|
+
internationalization (i18n) framework.
|
|
440
|
+
|
|
441
|
+
```ruby
|
|
442
|
+
class Person
|
|
443
|
+
extend ActiveModel::Translation
|
|
444
|
+
end
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
With the `human_attribute_name` you can transform attribute names into a more
|
|
448
|
+
human format. The human format is defined in your locale file.
|
|
449
|
+
|
|
450
|
+
* config/locales/app.pt-BR.yml
|
|
451
|
+
|
|
452
|
+
```yml
|
|
453
|
+
pt-BR:
|
|
454
|
+
activemodel:
|
|
455
|
+
attributes:
|
|
456
|
+
person:
|
|
457
|
+
name: 'Nome'
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
```ruby
|
|
461
|
+
Person.human_attribute_name('name') # => "Nome"
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Lint Tests
|
|
465
|
+
|
|
466
|
+
`ActiveModel::Lint::Tests` allow you to test whether an object is compliant with
|
|
467
|
+
the Active Model API.
|
|
468
|
+
|
|
469
|
+
* app/models/person.rb
|
|
470
|
+
|
|
471
|
+
```ruby
|
|
472
|
+
class Person
|
|
473
|
+
include ActiveModel::Model
|
|
474
|
+
|
|
475
|
+
end
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
* test/models/person_test.rb
|
|
479
|
+
|
|
480
|
+
```ruby
|
|
481
|
+
require 'test_helper'
|
|
482
|
+
|
|
483
|
+
class PersonTest < ActiveSupport::TestCase
|
|
484
|
+
include ActiveModel::Lint::Tests
|
|
485
|
+
|
|
486
|
+
def setup
|
|
487
|
+
@model = Person.new
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
$ rake test
|
|
494
|
+
|
|
495
|
+
Run options: --seed 14596
|
|
496
|
+
|
|
497
|
+
# Running:
|
|
498
|
+
|
|
499
|
+
......
|
|
500
|
+
|
|
501
|
+
Finished in 0.024899s, 240.9735 runs/s, 1204.8677 assertions/s.
|
|
502
|
+
|
|
503
|
+
6 runs, 30 assertions, 0 failures, 0 errors, 0 skips
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
An object is not required to implement all APIs in order to work with
|
|
507
|
+
Action Pack. This module only intends to provide guidance in case you want all
|
|
508
|
+
features out of the box.
|
|
509
|
+
|
|
510
|
+
### SecurePassword
|
|
511
|
+
|
|
512
|
+
`ActiveModel::SecurePassword` provides a way to securely store any
|
|
513
|
+
password in an encrypted form. On including this module, a
|
|
514
|
+
`has_secure_password` class method is provided which defines
|
|
515
|
+
an accessor named `password` with certain validations on it.
|
|
516
|
+
|
|
517
|
+
#### Requirements
|
|
518
|
+
|
|
519
|
+
`ActiveModel::SecurePassword` depends on the [`bcrypt`](https://github.com/codahale/bcrypt-ruby 'BCrypt'),
|
|
520
|
+
so include this gem in your Gemfile to use `ActiveModel::SecurePassword` correctly.
|
|
521
|
+
In order to make this work, the model must have an accessor named `password_digest`.
|
|
522
|
+
The `has_secure_password` will add the following validations on the `password` accessor:
|
|
523
|
+
|
|
524
|
+
1. Password should be present.
|
|
525
|
+
2. Password should be equal to its confirmation.
|
|
526
|
+
3. This maximum length of a password is 72 (required by `bcrypt` on which ActiveModel::SecurePassword depends)
|
|
527
|
+
|
|
528
|
+
#### Examples
|
|
529
|
+
|
|
530
|
+
```ruby
|
|
531
|
+
class Person
|
|
532
|
+
include ActiveModel::SecurePassword
|
|
533
|
+
has_secure_password
|
|
534
|
+
attr_accessor :password_digest
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
person = Person.new
|
|
538
|
+
|
|
539
|
+
# When password is blank.
|
|
540
|
+
person.valid? # => false
|
|
541
|
+
|
|
542
|
+
# When the confirmation doesn't match the password.
|
|
543
|
+
person.password = 'aditya'
|
|
544
|
+
person.password_confirmation = 'nomatch'
|
|
545
|
+
person.valid? # => false
|
|
546
|
+
|
|
547
|
+
# When the length of password, exceeds 72.
|
|
548
|
+
person.password = person.password_confirmation = 'a' * 100
|
|
549
|
+
person.valid? # => false
|
|
550
|
+
|
|
551
|
+
# When all validations are passed.
|
|
552
|
+
person.password = person.password_confirmation = 'aditya'
|
|
553
|
+
person.valid? # => true
|
|
554
|
+
```
|
|
@@ -31,7 +31,7 @@ Object Relational Mapping system.
|
|
|
31
31
|
in his book _Patterns of Enterprise Application Architecture_. In
|
|
32
32
|
Active Record, objects carry both persistent data and behavior which
|
|
33
33
|
operates on that data. Active Record takes the opinion that ensuring
|
|
34
|
-
data access logic
|
|
34
|
+
data access logic as part of the object will educate users of that
|
|
35
35
|
object on how to write to and read from the database.
|
|
36
36
|
|
|
37
37
|
### Object Relational Mapping
|
|
@@ -82,13 +82,13 @@ by underscores. Examples:
|
|
|
82
82
|
* Model Class - Singular with the first letter of each word capitalized (e.g.,
|
|
83
83
|
`BookClub`).
|
|
84
84
|
|
|
85
|
-
| Model / Class
|
|
86
|
-
|
|
|
87
|
-
| `
|
|
88
|
-
| `LineItem`
|
|
89
|
-
| `Deer`
|
|
90
|
-
| `Mouse`
|
|
91
|
-
| `Person`
|
|
85
|
+
| Model / Class | Table / Schema |
|
|
86
|
+
| ---------------- | -------------- |
|
|
87
|
+
| `Article` | `articles` |
|
|
88
|
+
| `LineItem` | `line_items` |
|
|
89
|
+
| `Deer` | `deers` |
|
|
90
|
+
| `Mouse` | `mice` |
|
|
91
|
+
| `Person` | `people` |
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
### Schema Conventions
|
|
@@ -116,13 +116,13 @@ to Active Record instances:
|
|
|
116
116
|
locking](http://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to
|
|
117
117
|
a model.
|
|
118
118
|
* `type` - Specifies that the model uses [Single Table
|
|
119
|
-
Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Single+table+inheritance).
|
|
119
|
+
Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Single+table+inheritance).
|
|
120
120
|
* `(association_name)_type` - Stores the type for
|
|
121
121
|
[polymorphic associations](association_basics.html#polymorphic-associations).
|
|
122
122
|
* `(table_name)_count` - Used to cache the number of belonging objects on
|
|
123
|
-
associations. For example, a `comments_count` column in a `
|
|
123
|
+
associations. For example, a `comments_count` column in a `Articles` class that
|
|
124
124
|
has many instances of `Comment` will cache the number of existent comments
|
|
125
|
-
for each
|
|
125
|
+
for each article.
|
|
126
126
|
|
|
127
127
|
NOTE: While these column names are optional, they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, `type` is a reserved keyword used to designate a table using Single Table Inheritance (STI). If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
|
|
128
128
|
|
|
@@ -309,11 +309,11 @@ into the database. There are several methods that you can use to check your
|
|
|
309
309
|
models and validate that an attribute value is not empty, is unique and not
|
|
310
310
|
already in the database, follows a specific format and many more.
|
|
311
311
|
|
|
312
|
-
Validation is a very important issue to consider when persisting to database, so
|
|
313
|
-
the methods `
|
|
312
|
+
Validation is a very important issue to consider when persisting to the database, so
|
|
313
|
+
the methods `save` and `update` take it into account when
|
|
314
314
|
running: they return `false` when validation fails and they didn't actually
|
|
315
|
-
perform any operation on database. All of these have a bang counterpart (that
|
|
316
|
-
is, `
|
|
315
|
+
perform any operation on the database. All of these have a bang counterpart (that
|
|
316
|
+
is, `save!` and `update!`), which are stricter in that
|
|
317
317
|
they raise the exception `ActiveRecord::RecordInvalid` if validation fails.
|
|
318
318
|
A quick example to illustrate:
|
|
319
319
|
|
|
@@ -322,8 +322,9 @@ class User < ActiveRecord::Base
|
|
|
322
322
|
validates :name, presence: true
|
|
323
323
|
end
|
|
324
324
|
|
|
325
|
-
User.
|
|
326
|
-
|
|
325
|
+
user = User.new
|
|
326
|
+
user.save # => false
|
|
327
|
+
user.save! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
|
|
327
328
|
```
|
|
328
329
|
|
|
329
330
|
You can learn more about validations in the [Active Record Validations
|
|
@@ -357,7 +358,7 @@ class CreatePublications < ActiveRecord::Migration
|
|
|
357
358
|
t.string :publisher_type
|
|
358
359
|
t.boolean :single_issue
|
|
359
360
|
|
|
360
|
-
t.timestamps
|
|
361
|
+
t.timestamps null: false
|
|
361
362
|
end
|
|
362
363
|
add_index :publications, :publication_type_id
|
|
363
364
|
end
|
|
@@ -15,7 +15,7 @@ After reading this guide, you will know:
|
|
|
15
15
|
The Object Life Cycle
|
|
16
16
|
---------------------
|
|
17
17
|
|
|
18
|
-
During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this
|
|
18
|
+
During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks into this *object life cycle* so that you can control your application and its data.
|
|
19
19
|
|
|
20
20
|
Callbacks allow you to trigger logic before or after an alteration of an object's state.
|
|
21
21
|
|
|
@@ -92,6 +92,7 @@ Here is a list with all the available Active Record callbacks, listed in the sam
|
|
|
92
92
|
* `around_create`
|
|
93
93
|
* `after_create`
|
|
94
94
|
* `after_save`
|
|
95
|
+
* `after_commit/after_rollback`
|
|
95
96
|
|
|
96
97
|
### Updating an Object
|
|
97
98
|
|
|
@@ -103,12 +104,14 @@ Here is a list with all the available Active Record callbacks, listed in the sam
|
|
|
103
104
|
* `around_update`
|
|
104
105
|
* `after_update`
|
|
105
106
|
* `after_save`
|
|
107
|
+
* `after_commit/after_rollback`
|
|
106
108
|
|
|
107
109
|
### Destroying an Object
|
|
108
110
|
|
|
109
111
|
* `before_destroy`
|
|
110
112
|
* `around_destroy`
|
|
111
113
|
* `after_destroy`
|
|
114
|
+
* `after_commit/after_rollback`
|
|
112
115
|
|
|
113
116
|
WARNING. `after_save` runs both on create and update, but always _after_ the more specific callbacks `after_create` and `after_update`, no matter the order in which the macro calls were executed.
|
|
114
117
|
|
|
@@ -258,27 +261,27 @@ WARNING. Any exception that is not `ActiveRecord::Rollback` will be re-raised by
|
|
|
258
261
|
Relational Callbacks
|
|
259
262
|
--------------------
|
|
260
263
|
|
|
261
|
-
Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many
|
|
264
|
+
Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many articles. A user's articles should be destroyed if the user is destroyed. Let's add an `after_destroy` callback to the `User` model by way of its relationship to the `Article` model:
|
|
262
265
|
|
|
263
266
|
```ruby
|
|
264
267
|
class User < ActiveRecord::Base
|
|
265
|
-
has_many :
|
|
268
|
+
has_many :articles, dependent: :destroy
|
|
266
269
|
end
|
|
267
270
|
|
|
268
|
-
class
|
|
271
|
+
class Article < ActiveRecord::Base
|
|
269
272
|
after_destroy :log_destroy_action
|
|
270
273
|
|
|
271
274
|
def log_destroy_action
|
|
272
|
-
puts '
|
|
275
|
+
puts 'Article destroyed'
|
|
273
276
|
end
|
|
274
277
|
end
|
|
275
278
|
|
|
276
279
|
>> user = User.first
|
|
277
280
|
=> #<User id: 1>
|
|
278
|
-
>> user.
|
|
279
|
-
=> #<
|
|
281
|
+
>> user.articles.create!
|
|
282
|
+
=> #<Article id: 1, user_id: 1>
|
|
280
283
|
>> user.destroy
|
|
281
|
-
|
|
284
|
+
Article destroyed
|
|
282
285
|
=> #<User id: 1>
|
|
283
286
|
```
|
|
284
287
|
|
|
@@ -325,7 +328,7 @@ When writing conditional callbacks, it is possible to mix both `:if` and `:unles
|
|
|
325
328
|
```ruby
|
|
326
329
|
class Comment < ActiveRecord::Base
|
|
327
330
|
after_create :send_email_to_author, if: :author_wants_emails?,
|
|
328
|
-
unless: Proc.new { |comment| comment.
|
|
331
|
+
unless: Proc.new { |comment| comment.article.ignore_comments? }
|
|
329
332
|
end
|
|
330
333
|
```
|
|
331
334
|
|