rails 4.1.16 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -10
- data/guides/CHANGELOG.md +15 -100
- 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_master.rb +1 -0
- 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 +6 -3
- 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 +5 -6
- 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 +81 -7
- data/guides/source/action_mailer_basics.md +91 -28
- data/guides/source/action_view_overview.md +148 -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} +95 -220
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +263 -265
- data/guides/source/active_record_validations.md +20 -11
- data/guides/source/active_support_core_extensions.md +159 -72
- data/guides/source/active_support_instrumentation.md +10 -7
- data/guides/source/api_documentation_guidelines.md +62 -16
- data/guides/source/asset_pipeline.md +258 -63
- 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 +440 -286
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +182 -182
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +337 -198
- data/guides/source/i18n.md +108 -65
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +108 -61
- data/guides/source/layout.html.erb +1 -4
- data/guides/source/layouts_and_rendering.md +27 -25
- data/guides/source/maintenance_policy.md +6 -3
- 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 +8 -4
- data/guides/source/routing.md +98 -72
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +38 -32
- data/guides/source/testing.md +188 -117
- data/guides/source/upgrading_ruby_on_rails.md +254 -28
- data/guides/source/working_with_javascript_in_rails.md +18 -16
- data/guides/w3c_validator.rb +2 -0
- metadata +40 -96
- data/guides/bug_report_templates/generic_gem.rb +0 -15
- data/guides/bug_report_templates/generic_master.rb +0 -26
- 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
@@ -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
|
-
####
|
96
|
+
#### `find`
|
97
97
|
|
98
|
-
Using `
|
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
|
-
`
|
112
|
+
The `find` method will raise an `ActiveRecord::RecordNotFound` exception if no matching record is found.
|
113
113
|
|
114
|
-
|
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
|
-
|
120
|
-
|
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
|
125
|
+
SELECT * FROM clients WHERE (clients.id IN (1,10))
|
127
126
|
```
|
128
127
|
|
129
|
-
`
|
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
|
-
#### `
|
130
|
+
#### `take`
|
134
131
|
|
135
|
-
`
|
132
|
+
The `take` method retrieves a record without any implicit ordering. For example:
|
136
133
|
|
137
134
|
```ruby
|
138
|
-
client = Client.
|
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
|
142
|
+
SELECT * FROM clients LIMIT 1
|
146
143
|
```
|
147
144
|
|
148
|
-
`
|
145
|
+
The `take` method returns `nil` if no record is found and no exception will be raised.
|
149
146
|
|
150
|
-
|
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.
|
156
|
-
# =>
|
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
|
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
|
-
|
163
|
+
The `take!` method behaves exactly like `take`, except that it will raise `ActiveRecord::RecordNotFound` if no matching record is found.
|
180
164
|
|
181
|
-
|
182
|
-
Client.where(first_name: 'Lifo').take
|
183
|
-
```
|
165
|
+
TIP: The retrieved record may vary depending on the database engine.
|
184
166
|
|
185
|
-
#### `
|
167
|
+
#### `first`
|
186
168
|
|
187
|
-
`
|
169
|
+
The `first` method finds the first record ordered by the primary key. For example:
|
188
170
|
|
189
171
|
```ruby
|
190
|
-
client = Client.
|
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
|
-
`
|
201
|
-
|
202
|
-
#### `first!`
|
182
|
+
The `first` method returns `nil` if no matching record is found and no exception will be raised.
|
203
183
|
|
204
|
-
|
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
|
-
# =>
|
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
|
198
|
+
SELECT * FROM clients ORDER BY clients.id ASC LIMIT 3
|
215
199
|
```
|
216
200
|
|
217
|
-
`
|
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
|
-
`
|
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
|
-
`
|
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
|
-
|
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.
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
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
|
234
|
+
SELECT * FROM clients ORDER BY clients.id DESC LIMIT 3
|
270
235
|
```
|
271
236
|
|
272
|
-
|
237
|
+
The `last!` method behaves exactly like `last`, except that it will raise `ActiveRecord::RecordNotFound` if no matching record is found.
|
273
238
|
|
274
|
-
####
|
239
|
+
#### `find_by`
|
275
240
|
|
276
|
-
`
|
241
|
+
The `find_by` method finds the first record matching some conditions. For example:
|
277
242
|
|
278
243
|
```ruby
|
279
|
-
Client.
|
280
|
-
# =>
|
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
|
-
|
287
|
-
|
247
|
+
Client.find_by first_name: 'Jon'
|
248
|
+
# => nil
|
288
249
|
```
|
289
250
|
|
290
|
-
|
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.
|
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
|
-
|
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.
|
312
|
-
# =>
|
313
|
-
#<Client id: 9, first_name: "John">]
|
260
|
+
Client.find_by! first_name: 'does not exist'
|
261
|
+
# => ActiveRecord::RecordNotFound
|
314
262
|
```
|
315
263
|
|
316
|
-
|
264
|
+
This is equivalent to writing:
|
317
265
|
|
318
|
-
```
|
319
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
476
|
-
Author.joins(:
|
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
|
-
|
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
|
-
|
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
|
670
|
+
SELECT * FROM articles WHERE id > 10 LIMIT 20
|
700
671
|
|
701
672
|
# Original query without `unscope`
|
702
|
-
SELECT * FROM
|
673
|
+
SELECT * FROM articles WHERE id > 10 ORDER BY id asc LIMIT 20
|
703
674
|
|
704
675
|
```
|
705
676
|
|
706
|
-
You can
|
677
|
+
You can also unscope specific `where` clauses. For example:
|
707
678
|
|
708
679
|
```ruby
|
709
|
-
|
710
|
-
# SELECT "
|
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
|
-
|
718
|
-
# SELECT "
|
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
|
-
|
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
|
703
|
+
SELECT * FROM articles WHERE id > 10 ORDER BY id DESC
|
733
704
|
|
734
705
|
# Original query without `only`
|
735
|
-
SELECT "
|
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
|
745
|
-
..
|
746
|
-
..
|
715
|
+
class Article < ActiveRecord::Base
|
747
716
|
has_many :comments, -> { order('posted_at DESC') }
|
748
717
|
end
|
749
718
|
|
750
|
-
|
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
|
757
|
-
SELECT * FROM comments WHERE
|
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
|
764
|
-
SELECT * FROM comments WHERE
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
796
|
+
Article.none # returns an empty Relation and fires no queries.
|
828
797
|
```
|
829
798
|
|
830
799
|
```ruby
|
831
|
-
# The
|
832
|
-
@
|
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
|
803
|
+
def visible_articles
|
835
804
|
case role
|
836
805
|
when 'Country Manager'
|
837
|
-
|
806
|
+
Article.where(country: country)
|
838
807
|
when 'Reviewer'
|
839
|
-
|
808
|
+
Article.published
|
840
809
|
when 'Bad User'
|
841
|
-
|
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`
|
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`, `
|
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 :
|
941
|
+
has_many :articles
|
973
942
|
end
|
974
943
|
|
975
|
-
class
|
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 :
|
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 :
|
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(:
|
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
|
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
|
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
|
-
|
984
|
+
Article.joins(:category, :comments)
|
1016
985
|
```
|
1017
986
|
|
1018
987
|
This produces:
|
1019
988
|
|
1020
989
|
```sql
|
1021
|
-
SELECT
|
1022
|
-
INNER JOIN categories ON
|
1023
|
-
INNER JOIN comments ON comments.
|
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
|
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
|
-
|
1000
|
+
Article.joins(comments: :guest)
|
1032
1001
|
```
|
1033
1002
|
|
1034
1003
|
This produces:
|
1035
1004
|
|
1036
1005
|
```sql
|
1037
|
-
SELECT
|
1038
|
-
INNER JOIN comments ON comments.
|
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
|
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(
|
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
|
1055
|
-
INNER JOIN comments ON comments.
|
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.
|
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
|
-
|
1095
|
+
Article.includes(:category, :comments)
|
1127
1096
|
```
|
1128
1097
|
|
1129
|
-
This loads all the
|
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(
|
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
|
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
|
-
|
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 "
|
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
|
-
|
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
|
1167
|
-
all the
|
1168
|
-
conditions **must** match, otherwise no records will be
|
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
|
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
|
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
|
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
|
-
|
1176
|
+
Article.published # => [published articles]
|
1207
1177
|
```
|
1208
1178
|
|
1209
|
-
Or on an association consisting of `
|
1179
|
+
Or on an association consisting of `Article` objects:
|
1210
1180
|
|
1211
1181
|
```ruby
|
1212
1182
|
category = Category.first
|
1213
|
-
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
|
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
|
-
|
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
|
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.
|
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
|
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
|
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
|
-
|
1610
|
-
|
1587
|
+
Article.any?
|
1588
|
+
Article.many?
|
1611
1589
|
|
1612
1590
|
# via a named scope
|
1613
|
-
|
1614
|
-
|
1591
|
+
Article.recent.any?
|
1592
|
+
Article.recent.many?
|
1615
1593
|
|
1616
1594
|
# via a relation
|
1617
|
-
|
1618
|
-
|
1595
|
+
Article.where(published: true).any?
|
1596
|
+
Article.where(published: true).many?
|
1619
1597
|
|
1620
1598
|
# via an association
|
1621
|
-
|
1622
|
-
|
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(:
|
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 `
|
1719
|
-
|
1720
|
-
| id | select_type | table
|
1721
|
-
|
1722
|
-
| 1 | SIMPLE | users
|
1723
|
-
| 1 | SIMPLE |
|
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 "
|
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: (
|
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
|
1742
|
-
Filter: (
|
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(:
|
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 |
|
1760
|
-
|
1761
|
-
| 1 | SIMPLE | users | const | PRIMARY |
|
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 `
|
1766
|
-
|
1767
|
-
| id | select_type | table
|
1768
|
-
|
1769
|
-
| 1 | SIMPLE |
|
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
|
|