rails 4.0.0 → 4.2.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +30 -23
  3. data/guides/CHANGELOG.md +108 -6
  4. data/guides/Rakefile +21 -6
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/edge_badge.png +0 -0
  7. data/guides/assets/images/feature_tile.gif +0 -0
  8. data/guides/assets/images/footer_tile.gif +0 -0
  9. data/guides/assets/images/fxn.png +0 -0
  10. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  11. data/guides/assets/images/getting_started/challenge.png +0 -0
  12. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  13. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  14. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  15. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  16. data/guides/assets/images/getting_started/new_article.png +0 -0
  17. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  18. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  19. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  20. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  21. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  22. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  23. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  24. data/guides/assets/images/header_tile.gif +0 -0
  25. data/guides/assets/images/icons/README +1 -1
  26. data/guides/assets/images/icons/callouts/11.png +0 -0
  27. data/guides/assets/images/icons/callouts/12.png +0 -0
  28. data/guides/assets/images/icons/callouts/13.png +0 -0
  29. data/guides/assets/images/icons/callouts/15.png +0 -0
  30. data/guides/assets/images/icons/caution.png +0 -0
  31. data/guides/assets/images/icons/example.png +0 -0
  32. data/guides/assets/images/radar.png +0 -0
  33. data/guides/assets/images/rails4_features.png +0 -0
  34. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  35. data/guides/assets/images/vijaydev.jpg +0 -0
  36. data/guides/assets/javascripts/guides.js +36 -34
  37. data/guides/assets/stylesheets/main.css +6 -2
  38. data/guides/assets/stylesheets/print.css +1 -1
  39. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  40. data/guides/bug_report_templates/action_controller_master.rb +54 -0
  41. data/guides/bug_report_templates/active_record_gem.rb +5 -2
  42. data/guides/bug_report_templates/active_record_master.rb +3 -2
  43. data/guides/bug_report_templates/generic_gem.rb +15 -0
  44. data/guides/bug_report_templates/generic_master.rb +26 -0
  45. data/guides/rails_guides.rb +23 -4
  46. data/guides/rails_guides/generator.rb +1 -1
  47. data/guides/rails_guides/helpers.rb +4 -2
  48. data/guides/rails_guides/levenshtein.rb +27 -21
  49. data/guides/rails_guides/markdown.rb +11 -7
  50. data/guides/rails_guides/markdown/renderer.rb +1 -1
  51. data/guides/source/2_2_release_notes.md +3 -3
  52. data/guides/source/2_3_release_notes.md +12 -12
  53. data/guides/source/3_0_release_notes.md +10 -13
  54. data/guides/source/3_1_release_notes.md +7 -4
  55. data/guides/source/3_2_release_notes.md +17 -14
  56. data/guides/source/4_0_release_notes.md +110 -54
  57. data/guides/source/4_1_release_notes.md +730 -0
  58. data/guides/source/4_2_release_notes.md +877 -0
  59. data/guides/source/_license.html.erb +1 -1
  60. data/guides/source/_welcome.html.erb +6 -2
  61. data/guides/source/action_controller_overview.md +223 -57
  62. data/guides/source/action_mailer_basics.md +129 -76
  63. data/guides/source/action_view_overview.md +247 -246
  64. data/guides/source/active_job_basics.md +339 -0
  65. data/guides/source/active_model_basics.md +374 -20
  66. data/guides/source/active_record_basics.md +46 -45
  67. data/guides/source/active_record_callbacks.md +83 -28
  68. data/guides/source/{migrations.md → active_record_migrations.md} +191 -275
  69. data/guides/source/active_record_postgresql.md +433 -0
  70. data/guides/source/active_record_querying.md +382 -300
  71. data/guides/source/active_record_validations.md +64 -55
  72. data/guides/source/active_support_core_extensions.md +229 -187
  73. data/guides/source/active_support_instrumentation.md +23 -22
  74. data/guides/source/api_documentation_guidelines.md +167 -15
  75. data/guides/source/asset_pipeline.md +768 -294
  76. data/guides/source/association_basics.md +188 -96
  77. data/guides/source/autoloading_and_reloading_constants.md +1311 -0
  78. data/guides/source/caching_with_rails.md +45 -11
  79. data/guides/source/command_line.md +96 -65
  80. data/guides/source/configuring.md +404 -70
  81. data/guides/source/contributing_to_ruby_on_rails.md +270 -130
  82. data/guides/source/credits.html.erb +7 -3
  83. data/guides/source/debugging_rails_applications.md +471 -284
  84. data/guides/source/development_dependencies_install.md +115 -21
  85. data/guides/source/documents.yaml +31 -9
  86. data/guides/source/engines.md +737 -291
  87. data/guides/source/form_helpers.md +137 -89
  88. data/guides/source/generators.md +60 -28
  89. data/guides/source/getting_started.md +1007 -596
  90. data/guides/source/i18n.md +178 -96
  91. data/guides/source/index.html.erb +2 -1
  92. data/guides/source/initialization.md +248 -104
  93. data/guides/source/kindle/toc.html.erb +1 -1
  94. data/guides/source/layout.html.erb +14 -22
  95. data/guides/source/layouts_and_rendering.md +78 -46
  96. data/guides/source/maintenance_policy.md +78 -0
  97. data/guides/source/nested_model_forms.md +10 -7
  98. data/guides/source/plugins.md +66 -57
  99. data/guides/source/rails_application_templates.md +49 -12
  100. data/guides/source/rails_on_rack.md +50 -60
  101. data/guides/source/routing.md +190 -139
  102. data/guides/source/ruby_on_rails_guides_guidelines.md +12 -13
  103. data/guides/source/security.md +134 -83
  104. data/guides/source/testing.md +322 -200
  105. data/guides/source/upgrading_ruby_on_rails.md +834 -37
  106. data/guides/source/working_with_javascript_in_rails.md +36 -26
  107. data/guides/w3c_validator.rb +2 -0
  108. metadata +93 -116
  109. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  110. data/guides/assets/images/getting_started/new_post.png +0 -0
  111. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  112. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  113. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  114. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  115. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  116. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  117. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  118. data/guides/code/getting_started/Gemfile +0 -43
  119. data/guides/code/getting_started/Gemfile.lock +0 -150
  120. data/guides/code/getting_started/README.rdoc +0 -28
  121. data/guides/code/getting_started/Rakefile +0 -6
  122. data/guides/code/getting_started/app/assets/javascripts/application.js +0 -16
  123. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
  124. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
  125. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
  126. data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
  127. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
  128. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
  129. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
  130. data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
  131. data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -17
  132. data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -47
  133. data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
  134. data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
  135. data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
  136. data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
  137. data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
  138. data/guides/code/getting_started/app/models/comment.rb +0 -3
  139. data/guides/code/getting_started/app/models/post.rb +0 -7
  140. data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
  141. data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
  142. data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
  143. data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
  144. data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
  145. data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
  146. data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
  147. data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
  148. data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -3
  149. data/guides/code/getting_started/bin/bundle +0 -4
  150. data/guides/code/getting_started/bin/rails +0 -4
  151. data/guides/code/getting_started/bin/rake +0 -4
  152. data/guides/code/getting_started/config.ru +0 -4
  153. data/guides/code/getting_started/config/application.rb +0 -18
  154. data/guides/code/getting_started/config/boot.rb +0 -4
  155. data/guides/code/getting_started/config/database.yml +0 -25
  156. data/guides/code/getting_started/config/environment.rb +0 -5
  157. data/guides/code/getting_started/config/environments/development.rb +0 -30
  158. data/guides/code/getting_started/config/environments/production.rb +0 -80
  159. data/guides/code/getting_started/config/environments/test.rb +0 -36
  160. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
  161. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
  162. data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
  163. data/guides/code/getting_started/config/initializers/locale.rb +0 -9
  164. data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
  165. data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
  166. data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
  167. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
  168. data/guides/code/getting_started/config/locales/en.yml +0 -23
  169. data/guides/code/getting_started/config/routes.rb +0 -7
  170. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
  171. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
  172. data/guides/code/getting_started/db/schema.rb +0 -33
  173. data/guides/code/getting_started/db/seeds.rb +0 -7
  174. data/guides/code/getting_started/public/404.html +0 -58
  175. data/guides/code/getting_started/public/422.html +0 -58
  176. data/guides/code/getting_started/public/500.html +0 -57
  177. data/guides/code/getting_started/public/favicon.ico +0 -0
  178. data/guides/code/getting_started/public/robots.txt +0 -5
  179. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
  180. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
  181. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
  182. data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
  183. data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
  184. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
  185. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
  186. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
  187. data/guides/code/getting_started/test/models/comment_test.rb +0 -7
  188. data/guides/code/getting_started/test/models/post_test.rb +0 -7
  189. data/guides/code/getting_started/test/test_helper.rb +0 -15
  190. data/guides/source/kindle/KINDLE.md +0 -26
@@ -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 is part of the object will educate users of that
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
@@ -48,10 +48,10 @@ overall database access code.
48
48
  Active Record gives us several mechanisms, the most important being the ability
49
49
  to:
50
50
 
51
- * Represent models and their data
52
- * Represent associations between these models
53
- * Represent inheritance hierarchies through related models
54
- * Validate models before they get persisted to the database
51
+ * Represent models and their data.
52
+ * Represent associations between these models.
53
+ * Represent inheritance hierarchies through related models.
54
+ * Validate models before they get persisted to the database.
55
55
  * Perform database operations in an object-oriented fashion.
56
56
 
57
57
  Convention over Configuration in Active Record
@@ -62,9 +62,9 @@ may be necessary to write a lot of configuration code. This is particularly true
62
62
  for ORM frameworks in general. However, if you follow the conventions adopted by
63
63
  Rails, you'll need to write very little configuration (in some case no
64
64
  configuration at all) when creating Active Record models. The idea is that if
65
- you configure your applications in the very same way most of the times then this
66
- should be the default way. In this cases, explicit configuration would be needed
67
- only in those cases where you can't follow the conventions for any reason.
65
+ you configure your applications in the very same way most of the time then this
66
+ should be the default way. Thus, explicit configuration would be needed
67
+ only in those cases where you can't follow the standard convention.
68
68
 
69
69
  ### Naming Conventions
70
70
 
@@ -78,17 +78,17 @@ of two or more words, the model class name should follow the Ruby conventions,
78
78
  using the CamelCase form, while the table name must contain the words separated
79
79
  by underscores. Examples:
80
80
 
81
- * Database Table - Plural with underscores separating words (e.g., `book_clubs`)
81
+ * Database Table - Plural with underscores separating words (e.g., `book_clubs`).
82
82
  * Model Class - Singular with the first letter of each word capitalized (e.g.,
83
- `BookClub`)
83
+ `BookClub`).
84
84
 
85
- | Model / Class | Table / Schema |
86
- | ------------- | -------------- |
87
- | `Post` | `posts` |
88
- | `LineItem` | `line_items` |
89
- | `Deer` | `deer` |
90
- | `Mouse` | `mice` |
91
- | `Person` | `people` |
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
@@ -101,11 +101,11 @@ depending on the purpose of these columns.
101
101
  fields that Active Record will look for when you create associations between
102
102
  your models.
103
103
  * **Primary keys** - By default, Active Record will use an integer column named
104
- `id` as the table's primary key. When using [Rails
104
+ `id` as the table's primary key. When using [Active Record
105
105
  Migrations](migrations.html) to create your tables, this column will be
106
106
  automatically created.
107
107
 
108
- There are also some optional column names that will create additional features
108
+ There are also some optional column names that will add additional features
109
109
  to Active Record instances:
110
110
 
111
111
  * `created_at` - Automatically gets set to the current date and time when the
@@ -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)
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 `Post` class that
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 post.
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
 
@@ -171,28 +171,28 @@ name that should be used:
171
171
 
172
172
  ```ruby
173
173
  class Product < ActiveRecord::Base
174
- self.table_name = "PRODUCT"
174
+ self.table_name = "my_products"
175
175
  end
176
176
  ```
177
177
 
178
178
  If you do so, you will have to define manually the class name that is hosting
179
- the fixtures (class_name.yml) using the `set_fixture_class` method in your test
179
+ the fixtures (my_products.yml) using the `set_fixture_class` method in your test
180
180
  definition:
181
181
 
182
182
  ```ruby
183
- class FunnyJoke < ActiveSupport::TestCase
184
- set_fixture_class funny_jokes: 'Joke'
185
- fixtures :funny_jokes
183
+ class ProductTest < ActiveSupport::TestCase
184
+ set_fixture_class my_products: Product
185
+ fixtures :my_products
186
186
  ...
187
187
  end
188
188
  ```
189
189
 
190
190
  It's also possible to override the column that should be used as the table's
191
- primary key using the `ActiveRecord::Base.set_primary_key` method:
191
+ primary key using the `ActiveRecord::Base.primary_key=` method:
192
192
 
193
193
  ```ruby
194
194
  class Product < ActiveRecord::Base
195
- set_primary_key "product_id"
195
+ self.primary_key = "product_id"
196
196
  end
197
197
  ```
198
198
 
@@ -253,12 +253,12 @@ user = User.first
253
253
 
254
254
  ```ruby
255
255
  # return the first user named David
256
- david = User.find_by_name('David')
256
+ david = User.find_by(name: 'David')
257
257
  ```
258
258
 
259
259
  ```ruby
260
260
  # find all users named David who are Code Artists and sort by created_at in reverse chronological order
261
- users = User.where(name: 'David', occupation: 'Code Artist').order('created_at DESC')
261
+ users = User.where(name: 'David', occupation: 'Code Artist').order(created_at: :desc)
262
262
  ```
263
263
 
264
264
  You can learn more about querying an Active Record model in the [Active Record
@@ -270,7 +270,7 @@ Once an Active Record object has been retrieved, its attributes can be modified
270
270
  and it can be saved to the database.
271
271
 
272
272
  ```ruby
273
- user = User.find_by_name('David')
273
+ user = User.find_by(name: 'David')
274
274
  user.name = 'Dave'
275
275
  user.save
276
276
  ```
@@ -279,7 +279,7 @@ A shorthand for this is to use a hash mapping attribute names to the desired
279
279
  value, like so:
280
280
 
281
281
  ```ruby
282
- user = User.find_by_name('David')
282
+ user = User.find_by(name: 'David')
283
283
  user.update(name: 'Dave')
284
284
  ```
285
285
 
@@ -297,7 +297,7 @@ Likewise, once retrieved an Active Record object can be destroyed which removes
297
297
  it from the database.
298
298
 
299
299
  ```ruby
300
- user = User.find_by_name('David')
300
+ user = User.find_by(name: 'David')
301
301
  user.destroy
302
302
  ```
303
303
 
@@ -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 `create`, `save` and `update` take it into account when
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, `create!`, `save!` and `update!`), which are stricter in that
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.create # => false
326
- User.create! # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
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
@@ -343,7 +344,7 @@ Migrations
343
344
 
344
345
  Rails provides a domain-specific language for managing a database schema called
345
346
  migrations. Migrations are stored in files which are executed against any
346
- database that Active Record support using `rake`. Here's a migration that
347
+ database that Active Record supports using `rake`. Here's a migration that
347
348
  creates a table:
348
349
 
349
350
  ```ruby
@@ -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
@@ -368,6 +369,6 @@ Rails keeps track of which files have been committed to the database and
368
369
  provides rollback features. To actually create the table, you'd run `rake db:migrate`
369
370
  and to roll it back, `rake db:rollback`.
370
371
 
371
- Note that the above code is database-agnostic: it will run in MySQL, postgresql,
372
- Oracle and others. You can learn more about migrations in the [Active Record
373
- Migrations guide](migrations.html)
372
+ Note that the above code is database-agnostic: it will run in MySQL,
373
+ PostgreSQL, Oracle and others. You can learn more about migrations in the
374
+ [Active Record Migrations guide](migrations.html).
@@ -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 <em>object life cycle</em> so that you can control your application and its data.
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
 
@@ -35,11 +35,11 @@ class User < ActiveRecord::Base
35
35
  before_validation :ensure_login_has_a_value
36
36
 
37
37
  protected
38
- def ensure_login_has_a_value
39
- if login.nil?
40
- self.login = email unless email.blank?
38
+ def ensure_login_has_a_value
39
+ if login.nil?
40
+ self.login = email unless email.blank?
41
+ end
41
42
  end
42
- end
43
43
  end
44
44
  ```
45
45
 
@@ -49,13 +49,13 @@ The macro-style class methods can also receive a block. Consider using this styl
49
49
  class User < ActiveRecord::Base
50
50
  validates :login, :email, presence: true
51
51
 
52
- before_create do |user|
53
- user.name = user.login.capitalize if user.name.blank?
52
+ before_create do
53
+ self.name = login.capitalize if name.blank?
54
54
  end
55
55
  end
56
56
  ```
57
57
 
58
- Callbacks can also be registered to only fire on certain lifecycle events:
58
+ Callbacks can also be registered to only fire on certain life cycle events:
59
59
 
60
60
  ```ruby
61
61
  class User < ActiveRecord::Base
@@ -65,13 +65,13 @@ class User < ActiveRecord::Base
65
65
  after_validation :set_location, on: [ :create, :update ]
66
66
 
67
67
  protected
68
- def normalize_name
69
- self.name = self.name.downcase.titleize
70
- end
68
+ def normalize_name
69
+ self.name = self.name.downcase.titleize
70
+ end
71
71
 
72
- def set_location
73
- self.location = LocationService.query(self)
74
- end
72
+ def set_location
73
+ self.location = LocationService.query(self)
74
+ end
75
75
  end
76
76
  ```
77
77
 
@@ -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
 
@@ -141,6 +144,55 @@ You have initialized an object!
141
144
  => #<User id: 1>
142
145
  ```
143
146
 
147
+ ### `after_touch`
148
+
149
+ The `after_touch` callback will be called whenever an Active Record object is touched.
150
+
151
+ ```ruby
152
+ class User < ActiveRecord::Base
153
+ after_touch do |user|
154
+ puts "You have touched an object"
155
+ end
156
+ end
157
+
158
+ >> u = User.create(name: 'Kuldeep')
159
+ => #<User id: 1, name: "Kuldeep", created_at: "2013-11-25 12:17:49", updated_at: "2013-11-25 12:17:49">
160
+
161
+ >> u.touch
162
+ You have touched an object
163
+ => true
164
+ ```
165
+
166
+ It can be used along with `belongs_to`:
167
+
168
+ ```ruby
169
+ class Employee < ActiveRecord::Base
170
+ belongs_to :company, touch: true
171
+ after_touch do
172
+ puts 'An Employee was touched'
173
+ end
174
+ end
175
+
176
+ class Company < ActiveRecord::Base
177
+ has_many :employees
178
+ after_touch :log_when_employees_or_company_touched
179
+
180
+ private
181
+ def log_when_employees_or_company_touched
182
+ puts 'Employee/Company was touched'
183
+ end
184
+ end
185
+
186
+ >> @employee = Employee.last
187
+ => #<Employee id: 1, company_id: 1, created_at: "2013-11-25 17:04:22", updated_at: "2013-11-25 17:05:05">
188
+
189
+ # triggers @employee.company.touch
190
+ >> @employee.touch
191
+ Employee/Company was touched
192
+ An Employee was touched
193
+ => true
194
+ ```
195
+
144
196
  Running Callbacks
145
197
  -----------------
146
198
 
@@ -167,6 +219,7 @@ Additionally, the `after_find` callback is triggered by the following finder met
167
219
  * `all`
168
220
  * `first`
169
221
  * `find`
222
+ * `find_by`
170
223
  * `find_by_*`
171
224
  * `find_by_*!`
172
225
  * `find_by_sql`
@@ -179,7 +232,7 @@ NOTE: The `find_by_*` and `find_by_*!` methods are dynamic finders generated aut
179
232
  Skipping Callbacks
180
233
  ------------------
181
234
 
182
- Just as with validations, it is also possible to skip callbacks. These methods should be used with caution, however, because important business rules and application logic may be kept in callbacks. Bypassing them without understanding the potential implications may lead to invalid data.
235
+ Just as with validations, it is also possible to skip callbacks by using the following methods:
183
236
 
184
237
  * `decrement`
185
238
  * `decrement_counter`
@@ -194,6 +247,8 @@ Just as with validations, it is also possible to skip callbacks. These methods s
194
247
  * `update_all`
195
248
  * `update_counters`
196
249
 
250
+ These methods should be used with caution, however, because important business rules and application logic may be kept in callbacks. Bypassing them without understanding the potential implications may lead to invalid data.
251
+
197
252
  Halting Execution
198
253
  -----------------
199
254
 
@@ -201,32 +256,32 @@ As you start registering new callbacks for your models, they will be queued for
201
256
 
202
257
  The whole callback chain is wrapped in a transaction. If any _before_ callback method returns exactly `false` or raises an exception, the execution chain gets halted and a ROLLBACK is issued; _after_ callbacks can only accomplish that by raising an exception.
203
258
 
204
- WARNING. Raising an arbitrary exception may break code that expects `save` and its friends not to fail like that. The `ActiveRecord::Rollback` exception is thought precisely to tell Active Record a rollback is going on. That one is internally captured but not reraised.
259
+ WARNING. Any exception that is not `ActiveRecord::Rollback` will be re-raised by Rails after the callback chain is halted. Raising an exception other than `ActiveRecord::Rollback` may break code that does not expect methods like `save` and `update_attributes` (which normally try to return `true` or `false`) to raise an exception.
205
260
 
206
261
  Relational Callbacks
207
262
  --------------------
208
263
 
209
- Callbacks work through model relationships, and can even be defined by them. Suppose an example where a user has many posts. A user's posts 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 `Post` model:
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:
210
265
 
211
266
  ```ruby
212
267
  class User < ActiveRecord::Base
213
- has_many :posts, dependent: :destroy
268
+ has_many :articles, dependent: :destroy
214
269
  end
215
270
 
216
- class Post < ActiveRecord::Base
271
+ class Article < ActiveRecord::Base
217
272
  after_destroy :log_destroy_action
218
273
 
219
274
  def log_destroy_action
220
- puts 'Post destroyed'
275
+ puts 'Article destroyed'
221
276
  end
222
277
  end
223
278
 
224
279
  >> user = User.first
225
280
  => #<User id: 1>
226
- >> user.posts.create!
227
- => #<Post id: 1, user_id: 1>
281
+ >> user.articles.create!
282
+ => #<Article id: 1, user_id: 1>
228
283
  >> user.destroy
229
- Post destroyed
284
+ Article destroyed
230
285
  => #<User id: 1>
231
286
  ```
232
287
 
@@ -273,7 +328,7 @@ When writing conditional callbacks, it is possible to mix both `:if` and `:unles
273
328
  ```ruby
274
329
  class Comment < ActiveRecord::Base
275
330
  after_create :send_email_to_author, if: :author_wants_emails?,
276
- unless: Proc.new { |comment| comment.post.ignore_comments? }
331
+ unless: Proc.new { |comment| comment.article.ignore_comments? }
277
332
  end
278
333
  ```
279
334
 
@@ -287,7 +342,7 @@ Here's an example where we create a class with an `after_destroy` callback for a
287
342
  ```ruby
288
343
  class PictureFileCallbacks
289
344
  def after_destroy(picture_file)
290
- if File.exists?(picture_file.filepath)
345
+ if File.exist?(picture_file.filepath)
291
346
  File.delete(picture_file.filepath)
292
347
  end
293
348
  end
@@ -307,7 +362,7 @@ Note that we needed to instantiate a new `PictureFileCallbacks` object, since we
307
362
  ```ruby
308
363
  class PictureFileCallbacks
309
364
  def self.after_destroy(picture_file)
310
- if File.exists?(picture_file.filepath)
365
+ if File.exist?(picture_file.filepath)
311
366
  File.delete(picture_file.filepath)
312
367
  end
313
368
  end
@@ -342,7 +397,7 @@ By using the `after_commit` callback we can account for this case.
342
397
 
343
398
  ```ruby
344
399
  class PictureFile < ActiveRecord::Base
345
- after_commit :delete_picture_file_from_disk, :on => [:destroy]
400
+ after_commit :delete_picture_file_from_disk, on: [:destroy]
346
401
 
347
402
  def delete_picture_file_from_disk
348
403
  if File.exist?(filepath)
@@ -355,4 +410,4 @@ end
355
410
  NOTE: the `:on` option specifies when a callback will be fired. If you
356
411
  don't supply the `:on` option the callback will fire for every action.
357
412
 
358
- The `after_commit` and `after_rollback` callbacks are guaranteed to be called for all models created, updated, or destroyed within a transaction block. If any exceptions are raised within one of these callbacks, they will be ignored so that they don't interfere with the other callbacks. As such, if your callback code could raise an exception, you'll need to rescue it and handle it appropriately within the callback.
413
+ WARNING. The `after_commit` and `after_rollback` callbacks are guaranteed to be called for all models created, updated, or destroyed within a transaction block. If any exceptions are raised within one of these callbacks, they will be ignored so that they don't interfere with the other callbacks. As such, if your callback code could raise an exception, you'll need to rescue it and handle it appropriately within the callback.