rails 4.1.16 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -10
  3. data/guides/CHANGELOG.md +15 -100
  4. data/guides/Rakefile +5 -3
  5. data/guides/assets/javascripts/guides.js +6 -0
  6. data/guides/assets/stylesheets/main.css +4 -1
  7. data/guides/bug_report_templates/action_controller_master.rb +1 -0
  8. data/guides/rails_guides/helpers.rb +1 -1
  9. data/guides/rails_guides/levenshtein.rb +29 -21
  10. data/guides/rails_guides/markdown/renderer.rb +1 -1
  11. data/guides/rails_guides/markdown.rb +11 -7
  12. data/guides/rails_guides.rb +2 -2
  13. data/guides/source/2_2_release_notes.md +1 -1
  14. data/guides/source/2_3_release_notes.md +4 -4
  15. data/guides/source/3_0_release_notes.md +8 -8
  16. data/guides/source/3_1_release_notes.md +6 -3
  17. data/guides/source/3_2_release_notes.md +6 -3
  18. data/guides/source/4_0_release_notes.md +6 -3
  19. data/guides/source/4_1_release_notes.md +5 -6
  20. data/guides/source/4_2_release_notes.md +850 -0
  21. data/guides/source/_license.html.erb +1 -1
  22. data/guides/source/_welcome.html.erb +2 -8
  23. data/guides/source/action_controller_overview.md +81 -7
  24. data/guides/source/action_mailer_basics.md +91 -28
  25. data/guides/source/action_view_overview.md +148 -130
  26. data/guides/source/active_job_basics.md +318 -0
  27. data/guides/source/active_model_basics.md +371 -17
  28. data/guides/source/active_record_basics.md +19 -18
  29. data/guides/source/active_record_callbacks.md +12 -9
  30. data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
  31. data/guides/source/active_record_postgresql.md +433 -0
  32. data/guides/source/active_record_querying.md +263 -265
  33. data/guides/source/active_record_validations.md +20 -11
  34. data/guides/source/active_support_core_extensions.md +159 -72
  35. data/guides/source/active_support_instrumentation.md +10 -7
  36. data/guides/source/api_documentation_guidelines.md +62 -16
  37. data/guides/source/asset_pipeline.md +258 -63
  38. data/guides/source/association_basics.md +81 -74
  39. data/guides/source/caching_with_rails.md +32 -7
  40. data/guides/source/command_line.md +52 -30
  41. data/guides/source/configuring.md +132 -29
  42. data/guides/source/constant_autoloading_and_reloading.md +1297 -0
  43. data/guides/source/contributing_to_ruby_on_rails.md +192 -112
  44. data/guides/source/credits.html.erb +2 -2
  45. data/guides/source/debugging_rails_applications.md +440 -286
  46. data/guides/source/development_dependencies_install.md +47 -36
  47. data/guides/source/documents.yaml +19 -7
  48. data/guides/source/engines.md +182 -182
  49. data/guides/source/form_helpers.md +79 -56
  50. data/guides/source/generators.md +24 -11
  51. data/guides/source/getting_started.md +337 -198
  52. data/guides/source/i18n.md +108 -65
  53. data/guides/source/index.html.erb +1 -0
  54. data/guides/source/initialization.md +108 -61
  55. data/guides/source/layout.html.erb +1 -4
  56. data/guides/source/layouts_and_rendering.md +27 -25
  57. data/guides/source/maintenance_policy.md +6 -3
  58. data/guides/source/nested_model_forms.md +7 -4
  59. data/guides/source/plugins.md +27 -27
  60. data/guides/source/rails_application_templates.md +21 -3
  61. data/guides/source/rails_on_rack.md +8 -4
  62. data/guides/source/routing.md +98 -72
  63. data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
  64. data/guides/source/security.md +38 -32
  65. data/guides/source/testing.md +188 -117
  66. data/guides/source/upgrading_ruby_on_rails.md +254 -28
  67. data/guides/source/working_with_javascript_in_rails.md +18 -16
  68. data/guides/w3c_validator.rb +2 -0
  69. metadata +40 -96
  70. data/guides/bug_report_templates/generic_gem.rb +0 -15
  71. data/guides/bug_report_templates/generic_master.rb +0 -26
  72. data/guides/code/getting_started/Gemfile +0 -40
  73. data/guides/code/getting_started/Gemfile.lock +0 -125
  74. data/guides/code/getting_started/README.rdoc +0 -28
  75. data/guides/code/getting_started/Rakefile +0 -6
  76. data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
  77. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
  78. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
  79. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
  80. data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
  81. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
  82. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
  83. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
  84. data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
  85. data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
  86. data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
  87. data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
  88. data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
  89. data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
  90. data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
  91. data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
  92. data/guides/code/getting_started/app/models/comment.rb +0 -3
  93. data/guides/code/getting_started/app/models/post.rb +0 -7
  94. data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
  95. data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
  96. data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
  97. data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
  98. data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
  99. data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
  100. data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
  101. data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
  102. data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
  103. data/guides/code/getting_started/bin/bundle +0 -4
  104. data/guides/code/getting_started/bin/rails +0 -4
  105. data/guides/code/getting_started/bin/rake +0 -4
  106. data/guides/code/getting_started/config/application.rb +0 -18
  107. data/guides/code/getting_started/config/boot.rb +0 -4
  108. data/guides/code/getting_started/config/database.yml +0 -25
  109. data/guides/code/getting_started/config/environment.rb +0 -5
  110. data/guides/code/getting_started/config/environments/development.rb +0 -30
  111. data/guides/code/getting_started/config/environments/production.rb +0 -80
  112. data/guides/code/getting_started/config/environments/test.rb +0 -36
  113. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
  114. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
  115. data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
  116. data/guides/code/getting_started/config/initializers/locale.rb +0 -9
  117. data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
  118. data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
  119. data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
  120. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
  121. data/guides/code/getting_started/config/locales/en.yml +0 -23
  122. data/guides/code/getting_started/config/routes.rb +0 -7
  123. data/guides/code/getting_started/config.ru +0 -4
  124. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
  125. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
  126. data/guides/code/getting_started/db/schema.rb +0 -33
  127. data/guides/code/getting_started/db/seeds.rb +0 -7
  128. data/guides/code/getting_started/public/404.html +0 -60
  129. data/guides/code/getting_started/public/422.html +0 -60
  130. data/guides/code/getting_started/public/500.html +0 -59
  131. data/guides/code/getting_started/public/favicon.ico +0 -0
  132. data/guides/code/getting_started/public/robots.txt +0 -5
  133. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
  134. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
  135. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
  136. data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
  137. data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
  138. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
  139. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
  140. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
  141. data/guides/code/getting_started/test/models/comment_test.rb +0 -7
  142. data/guides/code/getting_started/test/models/post_test.rb +0 -7
  143. data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -93,9 +93,9 @@ The primary operation of `Model.find(options)` can be summarized as:
93
93
 
94
94
  Active Record provides several different ways of retrieving a single object.
95
95
 
96
- #### Using a Primary Key
96
+ #### `find`
97
97
 
98
- Using `Model.find(primary_key)`, you can retrieve the object corresponding to the specified _primary key_ that matches any supplied options. For example:
98
+ Using the `find` method, you can retrieve the object corresponding to the specified _primary key_ that matches any supplied options. For example:
99
99
 
100
100
  ```ruby
101
101
  # Find the client with primary key (id) 10.
@@ -109,119 +109,103 @@ The SQL equivalent of the above is:
109
109
  SELECT * FROM clients WHERE (clients.id = 10) LIMIT 1
110
110
  ```
111
111
 
112
- `Model.find(primary_key)` will raise an `ActiveRecord::RecordNotFound` exception if no matching record is found.
112
+ The `find` method will raise an `ActiveRecord::RecordNotFound` exception if no matching record is found.
113
113
 
114
- #### `take`
115
-
116
- `Model.take` retrieves a record without any implicit ordering. For example:
114
+ You can also use this method to query for multiple objects. Call the `find` method and pass in an array of primary keys. The return will be an array containing all of the matching records for the supplied _primary keys_. For example:
117
115
 
118
116
  ```ruby
119
- client = Client.take
120
- # => #<Client id: 1, first_name: "Lifo">
117
+ # Find the clients with primary keys 1 and 10.
118
+ client = Client.find([1, 10]) # Or even Client.find(1, 10)
119
+ # => [#<Client id: 1, first_name: "Lifo">, #<Client id: 10, first_name: "Ryan">]
121
120
  ```
122
121
 
123
122
  The SQL equivalent of the above is:
124
123
 
125
124
  ```sql
126
- SELECT * FROM clients LIMIT 1
125
+ SELECT * FROM clients WHERE (clients.id IN (1,10))
127
126
  ```
128
127
 
129
- `Model.take` returns `nil` if no record is found and no exception will be raised.
130
-
131
- TIP: The retrieved record may vary depending on the database engine.
128
+ WARNING: The `find` method will raise an `ActiveRecord::RecordNotFound` exception unless a matching record is found for **all** of the supplied primary keys.
132
129
 
133
- #### `first`
130
+ #### `take`
134
131
 
135
- `Model.first` finds the first record ordered by the primary key. For example:
132
+ The `take` method retrieves a record without any implicit ordering. For example:
136
133
 
137
134
  ```ruby
138
- client = Client.first
135
+ client = Client.take
139
136
  # => #<Client id: 1, first_name: "Lifo">
140
137
  ```
141
138
 
142
139
  The SQL equivalent of the above is:
143
140
 
144
141
  ```sql
145
- SELECT * FROM clients ORDER BY clients.id ASC LIMIT 1
142
+ SELECT * FROM clients LIMIT 1
146
143
  ```
147
144
 
148
- `Model.first` returns `nil` if no matching record is found and no exception will be raised.
145
+ The `take` method returns `nil` if no record is found and no exception will be raised.
149
146
 
150
- #### `last`
151
-
152
- `Model.last` finds the last record ordered by the primary key. For example:
147
+ You can pass in a numerical argument to the `take` method to return up to that number of results. For example
153
148
 
154
149
  ```ruby
155
- client = Client.last
156
- # => #<Client id: 221, first_name: "Russel">
150
+ client = Client.take(2)
151
+ # => [
152
+ #<Client id: 1, first_name: "Lifo">,
153
+ #<Client id: 220, first_name: "Sara">
154
+ ]
157
155
  ```
158
156
 
159
157
  The SQL equivalent of the above is:
160
158
 
161
159
  ```sql
162
- SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
163
- ```
164
-
165
- `Model.last` returns `nil` if no matching record is found and no exception will be raised.
166
-
167
- #### `find_by`
168
-
169
- `Model.find_by` finds the first record matching some conditions. For example:
170
-
171
- ```ruby
172
- Client.find_by first_name: 'Lifo'
173
- # => #<Client id: 1, first_name: "Lifo">
174
-
175
- Client.find_by first_name: 'Jon'
176
- # => nil
160
+ SELECT * FROM clients LIMIT 2
177
161
  ```
178
162
 
179
- It is equivalent to writing:
163
+ The `take!` method behaves exactly like `take`, except that it will raise `ActiveRecord::RecordNotFound` if no matching record is found.
180
164
 
181
- ```ruby
182
- Client.where(first_name: 'Lifo').take
183
- ```
165
+ TIP: The retrieved record may vary depending on the database engine.
184
166
 
185
- #### `take!`
167
+ #### `first`
186
168
 
187
- `Model.take!` retrieves a record without any implicit ordering. For example:
169
+ The `first` method finds the first record ordered by the primary key. For example:
188
170
 
189
171
  ```ruby
190
- client = Client.take!
172
+ client = Client.first
191
173
  # => #<Client id: 1, first_name: "Lifo">
192
174
  ```
193
175
 
194
176
  The SQL equivalent of the above is:
195
177
 
196
178
  ```sql
197
- SELECT * FROM clients LIMIT 1
179
+ SELECT * FROM clients ORDER BY clients.id ASC LIMIT 1
198
180
  ```
199
181
 
200
- `Model.take!` raises `ActiveRecord::RecordNotFound` if no matching record is found.
201
-
202
- #### `first!`
182
+ The `first` method returns `nil` if no matching record is found and no exception will be raised.
203
183
 
204
- `Model.first!` finds the first record ordered by the primary key. For example:
184
+ You can pass in a numerical argument to the `first` method to return up to that number of results. For example
205
185
 
206
186
  ```ruby
207
- client = Client.first!
208
- # => #<Client id: 1, first_name: "Lifo">
187
+ client = Client.first(3)
188
+ # => [
189
+ #<Client id: 1, first_name: "Lifo">,
190
+ #<Client id: 2, first_name: "Fifo">,
191
+ #<Client id: 3, first_name: "Filo">
192
+ ]
209
193
  ```
210
194
 
211
195
  The SQL equivalent of the above is:
212
196
 
213
197
  ```sql
214
- SELECT * FROM clients ORDER BY clients.id ASC LIMIT 1
198
+ SELECT * FROM clients ORDER BY clients.id ASC LIMIT 3
215
199
  ```
216
200
 
217
- `Model.first!` raises `ActiveRecord::RecordNotFound` if no matching record is found.
201
+ The `first!` method behaves exactly like `first`, except that it will raise `ActiveRecord::RecordNotFound` if no matching record is found.
218
202
 
219
- #### `last!`
203
+ #### `last`
220
204
 
221
- `Model.last!` finds the last record ordered by the primary key. For example:
205
+ The `last` method finds the last record ordered by the primary key. For example:
222
206
 
223
207
  ```ruby
224
- client = Client.last!
208
+ client = Client.last
225
209
  # => #<Client id: 221, first_name: "Russel">
226
210
  ```
227
211
 
@@ -231,92 +215,56 @@ The SQL equivalent of the above is:
231
215
  SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
232
216
  ```
233
217
 
234
- `Model.last!` raises `ActiveRecord::RecordNotFound` if no matching record is found.
235
-
236
- #### `find_by!`
237
-
238
- `Model.find_by!` finds the first record matching some conditions. It raises `ActiveRecord::RecordNotFound` if no matching record is found. For example:
239
-
240
- ```ruby
241
- Client.find_by! first_name: 'Lifo'
242
- # => #<Client id: 1, first_name: "Lifo">
243
-
244
- Client.find_by! first_name: 'Jon'
245
- # => ActiveRecord::RecordNotFound
246
- ```
218
+ The `last` method returns `nil` if no matching record is found and no exception will be raised.
247
219
 
248
- It is equivalent to writing:
220
+ You can pass in a numerical argument to the `last` method to return up to that number of results. For example
249
221
 
250
222
  ```ruby
251
- Client.where(first_name: 'Lifo').take!
252
- ```
253
-
254
- ### Retrieving Multiple Objects
255
-
256
- #### Using Multiple Primary Keys
257
-
258
- `Model.find(array_of_primary_key)` accepts an array of _primary keys_, returning an array containing all of the matching records for the supplied _primary keys_. For example:
259
-
260
- ```ruby
261
- # Find the clients with primary keys 1 and 10.
262
- client = Client.find([1, 10]) # Or even Client.find(1, 10)
263
- # => [#<Client id: 1, first_name: "Lifo">, #<Client id: 10, first_name: "Ryan">]
223
+ client = Client.last(3)
224
+ # => [
225
+ #<Client id: 219, first_name: "James">,
226
+ #<Client id: 220, first_name: "Sara">,
227
+ #<Client id: 221, first_name: "Russel">
228
+ ]
264
229
  ```
265
230
 
266
231
  The SQL equivalent of the above is:
267
232
 
268
233
  ```sql
269
- SELECT * FROM clients WHERE (clients.id IN (1,10))
234
+ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 3
270
235
  ```
271
236
 
272
- WARNING: `Model.find(array_of_primary_key)` will raise an `ActiveRecord::RecordNotFound` exception unless a matching record is found for **all** of the supplied primary keys.
237
+ The `last!` method behaves exactly like `last`, except that it will raise `ActiveRecord::RecordNotFound` if no matching record is found.
273
238
 
274
- #### take
239
+ #### `find_by`
275
240
 
276
- `Model.take(limit)` retrieves the first number of records specified by `limit` without any explicit ordering:
241
+ The `find_by` method finds the first record matching some conditions. For example:
277
242
 
278
243
  ```ruby
279
- Client.take(2)
280
- # => [#<Client id: 1, first_name: "Lifo">,
281
- #<Client id: 2, first_name: "Raf">]
282
- ```
283
-
284
- The SQL equivalent of the above is:
244
+ Client.find_by first_name: 'Lifo'
245
+ # => #<Client id: 1, first_name: "Lifo">
285
246
 
286
- ```sql
287
- SELECT * FROM clients LIMIT 2
247
+ Client.find_by first_name: 'Jon'
248
+ # => nil
288
249
  ```
289
250
 
290
- #### first
291
-
292
- `Model.first(limit)` finds the first number of records specified by `limit` ordered by primary key:
251
+ It is equivalent to writing:
293
252
 
294
253
  ```ruby
295
- Client.first(2)
296
- # => [#<Client id: 1, first_name: "Lifo">,
297
- #<Client id: 2, first_name: "Raf">]
298
- ```
299
-
300
- The SQL equivalent of the above is:
301
-
302
- ```sql
303
- SELECT * FROM clients ORDER BY id ASC LIMIT 2
254
+ Client.where(first_name: 'Lifo').take
304
255
  ```
305
256
 
306
- #### last
307
-
308
- `Model.last(limit)` finds the number of records specified by `limit` ordered by primary key in descending order:
257
+ The `find_by!` method behaves exactly like `find_by`, except that it will raise `ActiveRecord::RecordNotFound` if no matching record is found. For example:
309
258
 
310
259
  ```ruby
311
- Client.last(2)
312
- # => [#<Client id: 10, first_name: "Ryan">,
313
- #<Client id: 9, first_name: "John">]
260
+ Client.find_by! first_name: 'does not exist'
261
+ # => ActiveRecord::RecordNotFound
314
262
  ```
315
263
 
316
- The SQL equivalent of the above is:
264
+ This is equivalent to writing:
317
265
 
318
- ```sql
319
- SELECT * FROM clients ORDER BY id DESC LIMIT 2
266
+ ```ruby
267
+ Client.where(first_name: 'does not exist').take!
320
268
  ```
321
269
 
322
270
  ### Retrieving Multiple Objects in Batches
@@ -328,7 +276,7 @@ This may appear straightforward:
328
276
  ```ruby
329
277
  # This is very inefficient when the users table has thousands of rows.
330
278
  User.all.each do |user|
331
- NewsLetter.weekly_deliver(user)
279
+ NewsMailer.weekly(user).deliver_now
332
280
  end
333
281
  ```
334
282
 
@@ -344,7 +292,15 @@ The `find_each` method retrieves a batch of records and then yields _each_ recor
344
292
 
345
293
  ```ruby
346
294
  User.find_each do |user|
347
- NewsLetter.weekly_deliver(user)
295
+ NewsMailer.weekly(user).deliver_now
296
+ end
297
+ ```
298
+
299
+ To add conditions to a `find_each` operation you can chain other Active Record methods such as `where`:
300
+
301
+ ```ruby
302
+ User.where(weekly_subscriber: true).find_each do |user|
303
+ NewsMailer.weekly(user).deliver_now
348
304
  end
349
305
  ```
350
306
 
@@ -360,7 +316,7 @@ The `:batch_size` option allows you to specify the number of records to be retri
360
316
 
361
317
  ```ruby
362
318
  User.find_each(batch_size: 5000) do |user|
363
- NewsLetter.weekly_deliver(user)
319
+ NewsMailer.weekly(user).deliver_now
364
320
  end
365
321
  ```
366
322
 
@@ -372,7 +328,7 @@ For example, to send newsletters only to users with the primary key starting fro
372
328
 
373
329
  ```ruby
374
330
  User.find_each(start: 2000, batch_size: 5000) do |user|
375
- NewsLetter.weekly_deliver(user)
331
+ NewsMailer.weekly(user).deliver_now
376
332
  end
377
333
  ```
378
334
 
@@ -384,16 +340,14 @@ The `find_in_batches` method is similar to `find_each`, since both retrieve batc
384
340
 
385
341
  ```ruby
386
342
  # Give add_invoices an array of 1000 invoices at a time
387
- Invoice.find_in_batches(include: :invoice_lines) do |invoices|
343
+ Invoice.find_in_batches do |invoices|
388
344
  export.add_invoices(invoices)
389
345
  end
390
346
  ```
391
347
 
392
- NOTE: The `:include` option allows you to name associations that should be loaded alongside with the models.
393
-
394
348
  ##### Options for `find_in_batches`
395
349
 
396
- The `find_in_batches` method accepts the same `:batch_size` and `:start` options as `find_each`, as well as most of the options allowed by the regular `find` method, except for `:order` and `:limit`, which are reserved for internal use by `find_in_batches`.
350
+ The `find_in_batches` method accepts the same `:batch_size` and `:start` options as `find_each`.
397
351
 
398
352
  Conditions
399
353
  ----------
@@ -472,8 +426,8 @@ Client.where('locked' => true)
472
426
  In the case of a belongs_to relationship, an association key can be used to specify the model if an Active Record object is used as the value. This method works with polymorphic relationships as well.
473
427
 
474
428
  ```ruby
475
- Post.where(author: author)
476
- Author.joins(:posts).where(posts: { author: author })
429
+ Article.where(author: author)
430
+ Author.joins(:articles).where(articles: { author: author })
477
431
  ```
478
432
 
479
433
  NOTE: The values cannot be symbols. For example, you cannot do `Client.where(status: :active)`.
@@ -511,7 +465,7 @@ SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
511
465
  `NOT` SQL queries can be built by `where.not`.
512
466
 
513
467
  ```ruby
514
- Post.where.not(author: author)
468
+ Article.where.not(author: author)
515
469
  ```
516
470
 
517
471
  In other words, this query can be generated by calling `where` with no argument, then immediately chain with `not` passing `where` conditions.
@@ -659,6 +613,23 @@ FROM orders
659
613
  GROUP BY date(created_at)
660
614
  ```
661
615
 
616
+ ### Total of grouped items
617
+
618
+ To get the total of grouped items on a single query call `count` after the `group`.
619
+
620
+ ```ruby
621
+ Order.group(:status).count
622
+ # => { 'awaiting_approval' => 7, 'paid' => 12 }
623
+ ```
624
+
625
+ The SQL that would be executed would be something like this:
626
+
627
+ ```sql
628
+ SELECT COUNT (*) AS count_all, status AS status
629
+ FROM "orders"
630
+ GROUP BY status
631
+ ```
632
+
662
633
  Having
663
634
  ------
664
635
 
@@ -690,32 +661,32 @@ Overriding Conditions
690
661
  You can specify certain conditions to be removed using the `unscope` method. For example:
691
662
 
692
663
  ```ruby
693
- Post.where('id > 10').limit(20).order('id asc').except(:order)
664
+ Article.where('id > 10').limit(20).order('id asc').unscope(:order)
694
665
  ```
695
666
 
696
667
  The SQL that would be executed:
697
668
 
698
669
  ```sql
699
- SELECT * FROM posts WHERE id > 10 LIMIT 20
670
+ SELECT * FROM articles WHERE id > 10 LIMIT 20
700
671
 
701
672
  # Original query without `unscope`
702
- SELECT * FROM posts WHERE id > 10 ORDER BY id asc LIMIT 20
673
+ SELECT * FROM articles WHERE id > 10 ORDER BY id asc LIMIT 20
703
674
 
704
675
  ```
705
676
 
706
- You can additionally unscope specific where clauses. For example:
677
+ You can also unscope specific `where` clauses. For example:
707
678
 
708
679
  ```ruby
709
- Post.where(id: 10, trashed: false).unscope(where: :id)
710
- # SELECT "posts".* FROM "posts" WHERE trashed = 0
680
+ Article.where(id: 10, trashed: false).unscope(where: :id)
681
+ # SELECT "articles".* FROM "articles" WHERE trashed = 0
711
682
  ```
712
683
 
713
684
  A relation which has used `unscope` will affect any relation it is
714
685
  merged in to:
715
686
 
716
687
  ```ruby
717
- Post.order('id asc').merge(Post.unscope(:order))
718
- # SELECT "posts".* FROM "posts"
688
+ Article.order('id asc').merge(Article.unscope(:order))
689
+ # SELECT "articles".* FROM "articles"
719
690
  ```
720
691
 
721
692
  ### `only`
@@ -723,16 +694,16 @@ Post.order('id asc').merge(Post.unscope(:order))
723
694
  You can also override conditions using the `only` method. For example:
724
695
 
725
696
  ```ruby
726
- Post.where('id > 10').limit(20).order('id desc').only(:order, :where)
697
+ Article.where('id > 10').limit(20).order('id desc').only(:order, :where)
727
698
  ```
728
699
 
729
700
  The SQL that would be executed:
730
701
 
731
702
  ```sql
732
- SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
703
+ SELECT * FROM articles WHERE id > 10 ORDER BY id DESC
733
704
 
734
705
  # Original query without `only`
735
- SELECT "posts".* FROM "posts" WHERE (id > 10) ORDER BY id desc LIMIT 20
706
+ SELECT "articles".* FROM "articles" WHERE (id > 10) ORDER BY id desc LIMIT 20
736
707
 
737
708
  ```
738
709
 
@@ -741,27 +712,25 @@ SELECT "posts".* FROM "posts" WHERE (id > 10) ORDER BY id desc LIMIT 20
741
712
  The `reorder` method overrides the default scope order. For example:
742
713
 
743
714
  ```ruby
744
- class Post < ActiveRecord::Base
745
- ..
746
- ..
715
+ class Article < ActiveRecord::Base
747
716
  has_many :comments, -> { order('posted_at DESC') }
748
717
  end
749
718
 
750
- Post.find(10).comments.reorder('name')
719
+ Article.find(10).comments.reorder('name')
751
720
  ```
752
721
 
753
722
  The SQL that would be executed:
754
723
 
755
724
  ```sql
756
- SELECT * FROM posts WHERE id = 10
757
- SELECT * FROM comments WHERE post_id = 10 ORDER BY name
725
+ SELECT * FROM articles WHERE id = 10
726
+ SELECT * FROM comments WHERE article_id = 10 ORDER BY name
758
727
  ```
759
728
 
760
729
  In case the `reorder` clause is not used, the SQL executed would be:
761
730
 
762
731
  ```sql
763
- SELECT * FROM posts WHERE id = 10
764
- SELECT * FROM comments WHERE post_id = 10 ORDER BY posted_at DESC
732
+ SELECT * FROM articles WHERE id = 10
733
+ SELECT * FROM comments WHERE article_id = 10 ORDER BY posted_at DESC
765
734
  ```
766
735
 
767
736
  ### `reverse_order`
@@ -797,25 +766,25 @@ This method accepts **no** arguments.
797
766
  The `rewhere` method overrides an existing, named where condition. For example:
798
767
 
799
768
  ```ruby
800
- Post.where(trashed: true).rewhere(trashed: false)
769
+ Article.where(trashed: true).rewhere(trashed: false)
801
770
  ```
802
771
 
803
772
  The SQL that would be executed:
804
773
 
805
774
  ```sql
806
- SELECT * FROM posts WHERE `trashed` = 0
775
+ SELECT * FROM articles WHERE `trashed` = 0
807
776
  ```
808
777
 
809
778
  In case the `rewhere` clause is not used,
810
779
 
811
780
  ```ruby
812
- Post.where(trashed: true).where(trashed: false)
781
+ Article.where(trashed: true).where(trashed: false)
813
782
  ```
814
783
 
815
784
  the SQL executed would be:
816
785
 
817
786
  ```sql
818
- SELECT * FROM posts WHERE `trashed` = 1 AND `trashed` = 0
787
+ SELECT * FROM articles WHERE `trashed` = 1 AND `trashed` = 0
819
788
  ```
820
789
 
821
790
  Null Relation
@@ -824,21 +793,21 @@ Null Relation
824
793
  The `none` method returns a chainable relation with no records. Any subsequent conditions chained to the returned relation will continue generating empty relations. This is useful in scenarios where you need a chainable response to a method or a scope that could return zero results.
825
794
 
826
795
  ```ruby
827
- Post.none # returns an empty Relation and fires no queries.
796
+ Article.none # returns an empty Relation and fires no queries.
828
797
  ```
829
798
 
830
799
  ```ruby
831
- # The visible_posts method below is expected to return a Relation.
832
- @posts = current_user.visible_posts.where(name: params[:name])
800
+ # The visible_articles method below is expected to return a Relation.
801
+ @articles = current_user.visible_articles.where(name: params[:name])
833
802
 
834
- def visible_posts
803
+ def visible_articles
835
804
  case role
836
805
  when 'Country Manager'
837
- Post.where(country: country)
806
+ Article.where(country: country)
838
807
  when 'Reviewer'
839
- Post.published
808
+ Article.published
840
809
  when 'Bad User'
841
- Post.none # => returning [] or nil breaks the caller code in this case
810
+ Article.none # => returning [] or nil breaks the caller code in this case
842
811
  end
843
812
  end
844
813
  ```
@@ -963,23 +932,23 @@ SELECT clients.* FROM clients LEFT OUTER JOIN addresses ON addresses.client_id =
963
932
 
964
933
  WARNING: This method only works with `INNER JOIN`.
965
934
 
966
- Active Record lets you use the names of the [associations](association_basics.html) defined on the model as a shortcut for specifying `JOIN` clause for those associations when using the `joins` method.
935
+ Active Record lets you use the names of the [associations](association_basics.html) defined on the model as a shortcut for specifying `JOIN` clauses for those associations when using the `joins` method.
967
936
 
968
- For example, consider the following `Category`, `Post`, `Comment`, `Guest` and `Tag` models:
937
+ For example, consider the following `Category`, `Article`, `Comment`, `Guest` and `Tag` models:
969
938
 
970
939
  ```ruby
971
940
  class Category < ActiveRecord::Base
972
- has_many :posts
941
+ has_many :articles
973
942
  end
974
943
 
975
- class Post < ActiveRecord::Base
944
+ class Article < ActiveRecord::Base
976
945
  belongs_to :category
977
946
  has_many :comments
978
947
  has_many :tags
979
948
  end
980
949
 
981
950
  class Comment < ActiveRecord::Base
982
- belongs_to :post
951
+ belongs_to :article
983
952
  has_one :guest
984
953
  end
985
954
 
@@ -988,7 +957,7 @@ class Guest < ActiveRecord::Base
988
957
  end
989
958
 
990
959
  class Tag < ActiveRecord::Base
991
- belongs_to :post
960
+ belongs_to :article
992
961
  end
993
962
  ```
994
963
 
@@ -997,64 +966,64 @@ Now all of the following will produce the expected join queries using `INNER JOI
997
966
  #### Joining a Single Association
998
967
 
999
968
  ```ruby
1000
- Category.joins(:posts)
969
+ Category.joins(:articles)
1001
970
  ```
1002
971
 
1003
972
  This produces:
1004
973
 
1005
974
  ```sql
1006
975
  SELECT categories.* FROM categories
1007
- INNER JOIN posts ON posts.category_id = categories.id
976
+ INNER JOIN articles ON articles.category_id = categories.id
1008
977
  ```
1009
978
 
1010
- Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use `Category.joins(:posts).uniq`.
979
+ Or, in English: "return a Category object for all categories with articles". Note that you will see duplicate categories if more than one article has the same category. If you want unique categories, you can use `Category.joins(:articles).uniq`.
1011
980
 
1012
981
  #### Joining Multiple Associations
1013
982
 
1014
983
  ```ruby
1015
- Post.joins(:category, :comments)
984
+ Article.joins(:category, :comments)
1016
985
  ```
1017
986
 
1018
987
  This produces:
1019
988
 
1020
989
  ```sql
1021
- SELECT posts.* FROM posts
1022
- INNER JOIN categories ON posts.category_id = categories.id
1023
- INNER JOIN comments ON comments.post_id = posts.id
990
+ SELECT articles.* FROM articles
991
+ INNER JOIN categories ON articles.category_id = categories.id
992
+ INNER JOIN comments ON comments.article_id = articles.id
1024
993
  ```
1025
994
 
1026
- Or, in English: "return all posts that have a category and at least one comment". Note again that posts with multiple comments will show up multiple times.
995
+ Or, in English: "return all articles that have a category and at least one comment". Note again that articles with multiple comments will show up multiple times.
1027
996
 
1028
997
  #### Joining Nested Associations (Single Level)
1029
998
 
1030
999
  ```ruby
1031
- Post.joins(comments: :guest)
1000
+ Article.joins(comments: :guest)
1032
1001
  ```
1033
1002
 
1034
1003
  This produces:
1035
1004
 
1036
1005
  ```sql
1037
- SELECT posts.* FROM posts
1038
- INNER JOIN comments ON comments.post_id = posts.id
1006
+ SELECT articles.* FROM articles
1007
+ INNER JOIN comments ON comments.article_id = articles.id
1039
1008
  INNER JOIN guests ON guests.comment_id = comments.id
1040
1009
  ```
1041
1010
 
1042
- Or, in English: "return all posts that have a comment made by a guest."
1011
+ Or, in English: "return all articles that have a comment made by a guest."
1043
1012
 
1044
1013
  #### Joining Nested Associations (Multiple Level)
1045
1014
 
1046
1015
  ```ruby
1047
- Category.joins(posts: [{ comments: :guest }, :tags])
1016
+ Category.joins(articles: [{ comments: :guest }, :tags])
1048
1017
  ```
1049
1018
 
1050
1019
  This produces:
1051
1020
 
1052
1021
  ```sql
1053
1022
  SELECT categories.* FROM categories
1054
- INNER JOIN posts ON posts.category_id = categories.id
1055
- INNER JOIN comments ON comments.post_id = posts.id
1023
+ INNER JOIN articles ON articles.category_id = categories.id
1024
+ INNER JOIN comments ON comments.article_id = articles.id
1056
1025
  INNER JOIN guests ON guests.comment_id = comments.id
1057
- INNER JOIN tags ON tags.post_id = posts.id
1026
+ INNER JOIN tags ON tags.article_id = articles.id
1058
1027
  ```
1059
1028
 
1060
1029
  ### Specifying Conditions on the Joined Tables
@@ -1123,18 +1092,18 @@ Active Record lets you eager load any number of associations with a single `Mode
1123
1092
  #### Array of Multiple Associations
1124
1093
 
1125
1094
  ```ruby
1126
- Post.includes(:category, :comments)
1095
+ Article.includes(:category, :comments)
1127
1096
  ```
1128
1097
 
1129
- This loads all the posts and the associated category and comments for each post.
1098
+ This loads all the articles and the associated category and comments for each article.
1130
1099
 
1131
1100
  #### Nested Associations Hash
1132
1101
 
1133
1102
  ```ruby
1134
- Category.includes(posts: [{ comments: :guest }, :tags]).find(1)
1103
+ Category.includes(articles: [{ comments: :guest }, :tags]).find(1)
1135
1104
  ```
1136
1105
 
1137
- This will find the category with id 1 and eager load all of the associated posts, the associated posts' tags and comments, and every comment's guest association.
1106
+ This will find the category with id 1 and eager load all of the associated articles, the associated articles' tags and comments, and every comment's guest association.
1138
1107
 
1139
1108
  ### Specifying Conditions on Eager Loaded Associations
1140
1109
 
@@ -1143,29 +1112,30 @@ Even though Active Record lets you specify conditions on the eager loaded associ
1143
1112
  However if you must do this, you may use `where` as you would normally.
1144
1113
 
1145
1114
  ```ruby
1146
- Post.includes(:comments).where(comments: { visible: true })
1115
+ Article.includes(:comments).where(comments: { visible: true })
1147
1116
  ```
1148
1117
 
1149
1118
  This would generate a query which contains a `LEFT OUTER JOIN` whereas the
1150
1119
  `joins` method would generate one using the `INNER JOIN` function instead.
1151
1120
 
1152
1121
  ```ruby
1153
- SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible = 1)
1122
+ SELECT "articles"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "articles" LEFT OUTER JOIN "comments" ON "comments"."article_id" = "articles"."id" WHERE (comments.visible = 1)
1154
1123
  ```
1155
1124
 
1156
- If there was no `where` condition, this would generate the normal set of two
1157
- queries.
1125
+ If there was no `where` condition, this would generate the normal set of two queries.
1158
1126
 
1159
1127
  NOTE: Using `where` like this will only work when you pass it a Hash. For
1160
1128
  SQL-fragments you need use `references` to force joined tables:
1161
1129
 
1162
1130
  ```ruby
1163
- Post.includes(:comments).where("comments.visible = true").references(:comments)
1131
+ Article.includes(:comments).where("comments.visible = true").references(:comments)
1164
1132
  ```
1165
1133
 
1166
- If, in the case of this `includes` query, there were no comments for any posts,
1167
- all the posts would still be loaded. By using `joins` (an INNER JOIN), the join
1168
- conditions **must** match, otherwise no records will be returned.
1134
+ If, in the case of this `includes` query, there were no comments for any
1135
+ articles, all the articles would still be loaded. By using `joins` (an INNER
1136
+ JOIN), the join conditions **must** match, otherwise no records will be
1137
+ returned.
1138
+
1169
1139
 
1170
1140
 
1171
1141
  Scopes
@@ -1176,7 +1146,7 @@ Scoping allows you to specify commonly-used queries which can be referenced as m
1176
1146
  To define a simple scope, we use the `scope` method inside the class, passing the query that we'd like to run when this scope is called:
1177
1147
 
1178
1148
  ```ruby
1179
- class Post < ActiveRecord::Base
1149
+ class Article < ActiveRecord::Base
1180
1150
  scope :published, -> { where(published: true) }
1181
1151
  end
1182
1152
  ```
@@ -1184,7 +1154,7 @@ end
1184
1154
  This is exactly the same as defining a class method, and which you use is a matter of personal preference:
1185
1155
 
1186
1156
  ```ruby
1187
- class Post < ActiveRecord::Base
1157
+ class Article < ActiveRecord::Base
1188
1158
  def self.published
1189
1159
  where(published: true)
1190
1160
  end
@@ -1194,7 +1164,7 @@ end
1194
1164
  Scopes are also chainable within scopes:
1195
1165
 
1196
1166
  ```ruby
1197
- class Post < ActiveRecord::Base
1167
+ class Article < ActiveRecord::Base
1198
1168
  scope :published, -> { where(published: true) }
1199
1169
  scope :published_and_commented, -> { published.where("comments_count > 0") }
1200
1170
  end
@@ -1203,14 +1173,14 @@ end
1203
1173
  To call this `published` scope we can call it on either the class:
1204
1174
 
1205
1175
  ```ruby
1206
- Post.published # => [published posts]
1176
+ Article.published # => [published articles]
1207
1177
  ```
1208
1178
 
1209
- Or on an association consisting of `Post` objects:
1179
+ Or on an association consisting of `Article` objects:
1210
1180
 
1211
1181
  ```ruby
1212
1182
  category = Category.first
1213
- category.posts.published # => [published posts belonging to this category]
1183
+ category.articles.published # => [published articles belonging to this category]
1214
1184
  ```
1215
1185
 
1216
1186
  ### Passing in arguments
@@ -1218,7 +1188,7 @@ category.posts.published # => [published posts belonging to this category]
1218
1188
  Your scope can take arguments:
1219
1189
 
1220
1190
  ```ruby
1221
- class Post < ActiveRecord::Base
1191
+ class Article < ActiveRecord::Base
1222
1192
  scope :created_before, ->(time) { where("created_at < ?", time) }
1223
1193
  end
1224
1194
  ```
@@ -1226,13 +1196,13 @@ end
1226
1196
  Call the scope as if it were a class method:
1227
1197
 
1228
1198
  ```ruby
1229
- Post.created_before(Time.zone.now)
1199
+ Article.created_before(Time.zone.now)
1230
1200
  ```
1231
1201
 
1232
1202
  However, this is just duplicating the functionality that would be provided to you by a class method.
1233
1203
 
1234
1204
  ```ruby
1235
- class Post < ActiveRecord::Base
1205
+ class Article < ActiveRecord::Base
1236
1206
  def self.created_before(time)
1237
1207
  where("created_at < ?", time)
1238
1208
  end
@@ -1242,7 +1212,36 @@ end
1242
1212
  Using a class method is the preferred way to accept arguments for scopes. These methods will still be accessible on the association objects:
1243
1213
 
1244
1214
  ```ruby
1245
- category.posts.created_before(time)
1215
+ category.articles.created_before(time)
1216
+ ```
1217
+
1218
+ ### Applying a default scope
1219
+
1220
+ If we wish for a scope to be applied across all queries to the model we can use the
1221
+ `default_scope` method within the model itself.
1222
+
1223
+ ```ruby
1224
+ class Client < ActiveRecord::Base
1225
+ default_scope { where("removed_at IS NULL") }
1226
+ end
1227
+ ```
1228
+
1229
+ When queries are executed on this model, the SQL query will now look something like
1230
+ this:
1231
+
1232
+ ```sql
1233
+ SELECT * FROM clients WHERE removed_at IS NULL
1234
+ ```
1235
+
1236
+ If you need to do more complex things with a default scope, you can alternatively
1237
+ define it as a class method:
1238
+
1239
+ ```ruby
1240
+ class Client < ActiveRecord::Base
1241
+ def self.default_scope
1242
+ # Should return an ActiveRecord::Relation.
1243
+ end
1244
+ end
1246
1245
  ```
1247
1246
 
1248
1247
  ### Merging of scopes
@@ -1298,36 +1297,6 @@ User.where(state: 'inactive')
1298
1297
  As you can see above the `default_scope` is being merged in both
1299
1298
  `scope` and `where` conditions.
1300
1299
 
1301
-
1302
- ### Applying a default scope
1303
-
1304
- If we wish for a scope to be applied across all queries to the model we can use the
1305
- `default_scope` method within the model itself.
1306
-
1307
- ```ruby
1308
- class Client < ActiveRecord::Base
1309
- default_scope { where("removed_at IS NULL") }
1310
- end
1311
- ```
1312
-
1313
- When queries are executed on this model, the SQL query will now look something like
1314
- this:
1315
-
1316
- ```sql
1317
- SELECT * FROM clients WHERE removed_at IS NULL
1318
- ```
1319
-
1320
- If you need to do more complex things with a default scope, you can alternatively
1321
- define it as a class method:
1322
-
1323
- ```ruby
1324
- class Client < ActiveRecord::Base
1325
- def self.default_scope
1326
- # Should return an ActiveRecord::Relation.
1327
- end
1328
- end
1329
- ```
1330
-
1331
1300
  ### Removing All Scoping
1332
1301
 
1333
1302
  If we wish to remove scoping for any reason we can use the `unscoped` method. This is
@@ -1470,6 +1439,11 @@ If you'd like to use your own SQL to find records in a table you can use `find_b
1470
1439
  Client.find_by_sql("SELECT * FROM clients
1471
1440
  INNER JOIN orders ON clients.id = orders.client_id
1472
1441
  ORDER BY clients.created_at desc")
1442
+ # => [
1443
+ #<Client id: 1, first_name: "Lucas" >,
1444
+ #<Client id: 2, first_name: "Jan" >,
1445
+ # ...
1446
+ ]
1473
1447
  ```
1474
1448
 
1475
1449
  `find_by_sql` provides you with a simple way of making custom calls to the database and retrieving instantiated objects.
@@ -1479,12 +1453,16 @@ Client.find_by_sql("SELECT * FROM clients
1479
1453
  `find_by_sql` has a close relative called `connection#select_all`. `select_all` will retrieve objects from the database using custom SQL just like `find_by_sql` but will not instantiate them. Instead, you will get an array of hashes where each hash indicates a record.
1480
1454
 
1481
1455
  ```ruby
1482
- Client.connection.select_all("SELECT * FROM clients WHERE id = '1'")
1456
+ Client.connection.select_all("SELECT first_name, created_at FROM clients WHERE id = '1'")
1457
+ # => [
1458
+ {"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
1459
+ {"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
1460
+ ]
1483
1461
  ```
1484
1462
 
1485
1463
  ### `pluck`
1486
1464
 
1487
- `pluck` can be used to query a single or multiple columns from the underlying table of a model. It accepts a list of column names as argument and returns an array of values of the specified columns with the corresponding data type.
1465
+ `pluck` can be used to query single or multiple columns from the underlying table of a model. It accepts a list of column names as argument and returns an array of values of the specified columns with the corresponding data type.
1488
1466
 
1489
1467
  ```ruby
1490
1468
  Client.where(active: true).pluck(:id)
@@ -1606,20 +1584,20 @@ You can also use `any?` and `many?` to check for existence on a model or relatio
1606
1584
 
1607
1585
  ```ruby
1608
1586
  # via a model
1609
- Post.any?
1610
- Post.many?
1587
+ Article.any?
1588
+ Article.many?
1611
1589
 
1612
1590
  # via a named scope
1613
- Post.recent.any?
1614
- Post.recent.many?
1591
+ Article.recent.any?
1592
+ Article.recent.many?
1615
1593
 
1616
1594
  # via a relation
1617
- Post.where(published: true).any?
1618
- Post.where(published: true).many?
1595
+ Article.where(published: true).any?
1596
+ Article.where(published: true).many?
1619
1597
 
1620
1598
  # via an association
1621
- Post.first.categories.any?
1622
- Post.first.categories.many?
1599
+ Article.first.categories.any?
1600
+ Article.first.categories.many?
1623
1601
  ```
1624
1602
 
1625
1603
  Calculations
@@ -1709,19 +1687,26 @@ Running EXPLAIN
1709
1687
  You can run EXPLAIN on the queries triggered by relations. For example,
1710
1688
 
1711
1689
  ```ruby
1712
- User.where(id: 1).joins(:posts).explain
1690
+ User.where(id: 1).joins(:articles).explain
1713
1691
  ```
1714
1692
 
1715
1693
  may yield
1716
1694
 
1717
1695
  ```
1718
- EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `posts` ON `posts`.`user_id` = `users`.`id` WHERE `users`.`id` = 1
1719
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
1720
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1721
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
1722
- | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
1723
- | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
1724
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
1696
+ EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `articles` ON `articles`.`user_id` = `users`.`id` WHERE `users`.`id` = 1
1697
+ +----+-------------+----------+-------+---------------+
1698
+ | id | select_type | table | type | possible_keys |
1699
+ +----+-------------+----------+-------+---------------+
1700
+ | 1 | SIMPLE | users | const | PRIMARY |
1701
+ | 1 | SIMPLE | articles | ALL | NULL |
1702
+ +----+-------------+----------+-------+---------------+
1703
+ +---------+---------+-------+------+-------------+
1704
+ | key | key_len | ref | rows | Extra |
1705
+ +---------+---------+-------+------+-------------+
1706
+ | PRIMARY | 4 | const | 1 | |
1707
+ | NULL | NULL | NULL | 1 | Using where |
1708
+ +---------+---------+-------+------+-------------+
1709
+
1725
1710
  2 rows in set (0.00 sec)
1726
1711
  ```
1727
1712
 
@@ -1731,15 +1716,15 @@ Active Record performs a pretty printing that emulates the one of the database
1731
1716
  shells. So, the same query running with the PostgreSQL adapter would yield instead
1732
1717
 
1733
1718
  ```
1734
- EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE "users"."id" = 1
1719
+ EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "articles" ON "articles"."user_id" = "users"."id" WHERE "users"."id" = 1
1735
1720
  QUERY PLAN
1736
1721
  ------------------------------------------------------------------------------
1737
1722
  Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0)
1738
- Join Filter: (posts.user_id = users.id)
1723
+ Join Filter: (articles.user_id = users.id)
1739
1724
  -> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=4)
1740
1725
  Index Cond: (id = 1)
1741
- -> Seq Scan on posts (cost=0.00..28.88 rows=8 width=4)
1742
- Filter: (posts.user_id = 1)
1726
+ -> Seq Scan on articles (cost=0.00..28.88 rows=8 width=4)
1727
+ Filter: (articles.user_id = 1)
1743
1728
  (6 rows)
1744
1729
  ```
1745
1730
 
@@ -1748,26 +1733,39 @@ may need the results of previous ones. Because of that, `explain` actually
1748
1733
  executes the query, and then asks for the query plans. For example,
1749
1734
 
1750
1735
  ```ruby
1751
- User.where(id: 1).includes(:posts).explain
1736
+ User.where(id: 1).includes(:articles).explain
1752
1737
  ```
1753
1738
 
1754
1739
  yields
1755
1740
 
1756
1741
  ```
1757
1742
  EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
1758
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1759
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1760
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1761
- | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
1762
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1743
+ +----+-------------+-------+-------+---------------+
1744
+ | id | select_type | table | type | possible_keys |
1745
+ +----+-------------+-------+-------+---------------+
1746
+ | 1 | SIMPLE | users | const | PRIMARY |
1747
+ +----+-------------+-------+-------+---------------+
1748
+ +---------+---------+-------+------+-------+
1749
+ | key | key_len | ref | rows | Extra |
1750
+ +---------+---------+-------+------+-------+
1751
+ | PRIMARY | 4 | const | 1 | |
1752
+ +---------+---------+-------+------+-------+
1753
+
1763
1754
  1 row in set (0.00 sec)
1764
1755
 
1765
- EXPLAIN for: SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` IN (1)
1766
- +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1767
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1768
- +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1769
- | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
1770
- +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1756
+ EXPLAIN for: SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` IN (1)
1757
+ +----+-------------+----------+------+---------------+
1758
+ | id | select_type | table | type | possible_keys |
1759
+ +----+-------------+----------+------+---------------+
1760
+ | 1 | SIMPLE | articles | ALL | NULL |
1761
+ +----+-------------+----------+------+---------------+
1762
+ +------+---------+------+------+-------------+
1763
+ | key | key_len | ref | rows | Extra |
1764
+ +------+---------+------+------+-------------+
1765
+ | NULL | NULL | NULL | 1 | Using where |
1766
+ +------+---------+------+------+-------------+
1767
+
1768
+
1771
1769
  1 row in set (0.00 sec)
1772
1770
  ```
1773
1771