rails 4.0.0 → 4.2.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +30 -23
  3. data/guides/CHANGELOG.md +108 -6
  4. data/guides/Rakefile +21 -6
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/edge_badge.png +0 -0
  7. data/guides/assets/images/feature_tile.gif +0 -0
  8. data/guides/assets/images/footer_tile.gif +0 -0
  9. data/guides/assets/images/fxn.png +0 -0
  10. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  11. data/guides/assets/images/getting_started/challenge.png +0 -0
  12. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  13. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  14. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  15. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  16. data/guides/assets/images/getting_started/new_article.png +0 -0
  17. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  18. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  19. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  20. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  21. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  22. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  23. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  24. data/guides/assets/images/header_tile.gif +0 -0
  25. data/guides/assets/images/icons/README +1 -1
  26. data/guides/assets/images/icons/callouts/11.png +0 -0
  27. data/guides/assets/images/icons/callouts/12.png +0 -0
  28. data/guides/assets/images/icons/callouts/13.png +0 -0
  29. data/guides/assets/images/icons/callouts/15.png +0 -0
  30. data/guides/assets/images/icons/caution.png +0 -0
  31. data/guides/assets/images/icons/example.png +0 -0
  32. data/guides/assets/images/radar.png +0 -0
  33. data/guides/assets/images/rails4_features.png +0 -0
  34. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  35. data/guides/assets/images/vijaydev.jpg +0 -0
  36. data/guides/assets/javascripts/guides.js +36 -34
  37. data/guides/assets/stylesheets/main.css +6 -2
  38. data/guides/assets/stylesheets/print.css +1 -1
  39. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  40. data/guides/bug_report_templates/action_controller_master.rb +54 -0
  41. data/guides/bug_report_templates/active_record_gem.rb +5 -2
  42. data/guides/bug_report_templates/active_record_master.rb +3 -2
  43. data/guides/bug_report_templates/generic_gem.rb +15 -0
  44. data/guides/bug_report_templates/generic_master.rb +26 -0
  45. data/guides/rails_guides.rb +23 -4
  46. data/guides/rails_guides/generator.rb +1 -1
  47. data/guides/rails_guides/helpers.rb +4 -2
  48. data/guides/rails_guides/levenshtein.rb +27 -21
  49. data/guides/rails_guides/markdown.rb +11 -7
  50. data/guides/rails_guides/markdown/renderer.rb +1 -1
  51. data/guides/source/2_2_release_notes.md +3 -3
  52. data/guides/source/2_3_release_notes.md +12 -12
  53. data/guides/source/3_0_release_notes.md +10 -13
  54. data/guides/source/3_1_release_notes.md +7 -4
  55. data/guides/source/3_2_release_notes.md +17 -14
  56. data/guides/source/4_0_release_notes.md +110 -54
  57. data/guides/source/4_1_release_notes.md +730 -0
  58. data/guides/source/4_2_release_notes.md +877 -0
  59. data/guides/source/_license.html.erb +1 -1
  60. data/guides/source/_welcome.html.erb +6 -2
  61. data/guides/source/action_controller_overview.md +223 -57
  62. data/guides/source/action_mailer_basics.md +129 -76
  63. data/guides/source/action_view_overview.md +247 -246
  64. data/guides/source/active_job_basics.md +339 -0
  65. data/guides/source/active_model_basics.md +374 -20
  66. data/guides/source/active_record_basics.md +46 -45
  67. data/guides/source/active_record_callbacks.md +83 -28
  68. data/guides/source/{migrations.md → active_record_migrations.md} +191 -275
  69. data/guides/source/active_record_postgresql.md +433 -0
  70. data/guides/source/active_record_querying.md +382 -300
  71. data/guides/source/active_record_validations.md +64 -55
  72. data/guides/source/active_support_core_extensions.md +229 -187
  73. data/guides/source/active_support_instrumentation.md +23 -22
  74. data/guides/source/api_documentation_guidelines.md +167 -15
  75. data/guides/source/asset_pipeline.md +768 -294
  76. data/guides/source/association_basics.md +188 -96
  77. data/guides/source/autoloading_and_reloading_constants.md +1311 -0
  78. data/guides/source/caching_with_rails.md +45 -11
  79. data/guides/source/command_line.md +96 -65
  80. data/guides/source/configuring.md +404 -70
  81. data/guides/source/contributing_to_ruby_on_rails.md +270 -130
  82. data/guides/source/credits.html.erb +7 -3
  83. data/guides/source/debugging_rails_applications.md +471 -284
  84. data/guides/source/development_dependencies_install.md +115 -21
  85. data/guides/source/documents.yaml +31 -9
  86. data/guides/source/engines.md +737 -291
  87. data/guides/source/form_helpers.md +137 -89
  88. data/guides/source/generators.md +60 -28
  89. data/guides/source/getting_started.md +1007 -596
  90. data/guides/source/i18n.md +178 -96
  91. data/guides/source/index.html.erb +2 -1
  92. data/guides/source/initialization.md +248 -104
  93. data/guides/source/kindle/toc.html.erb +1 -1
  94. data/guides/source/layout.html.erb +14 -22
  95. data/guides/source/layouts_and_rendering.md +78 -46
  96. data/guides/source/maintenance_policy.md +78 -0
  97. data/guides/source/nested_model_forms.md +10 -7
  98. data/guides/source/plugins.md +66 -57
  99. data/guides/source/rails_application_templates.md +49 -12
  100. data/guides/source/rails_on_rack.md +50 -60
  101. data/guides/source/routing.md +190 -139
  102. data/guides/source/ruby_on_rails_guides_guidelines.md +12 -13
  103. data/guides/source/security.md +134 -83
  104. data/guides/source/testing.md +322 -200
  105. data/guides/source/upgrading_ruby_on_rails.md +834 -37
  106. data/guides/source/working_with_javascript_in_rails.md +36 -26
  107. data/guides/w3c_validator.rb +2 -0
  108. metadata +93 -116
  109. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  110. data/guides/assets/images/getting_started/new_post.png +0 -0
  111. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  112. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  113. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  114. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  115. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  116. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  117. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  118. data/guides/code/getting_started/Gemfile +0 -43
  119. data/guides/code/getting_started/Gemfile.lock +0 -150
  120. data/guides/code/getting_started/README.rdoc +0 -28
  121. data/guides/code/getting_started/Rakefile +0 -6
  122. data/guides/code/getting_started/app/assets/javascripts/application.js +0 -16
  123. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
  124. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
  125. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
  126. data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
  127. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
  128. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
  129. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
  130. data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
  131. data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -17
  132. data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -47
  133. data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
  134. data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
  135. data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
  136. data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
  137. data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
  138. data/guides/code/getting_started/app/models/comment.rb +0 -3
  139. data/guides/code/getting_started/app/models/post.rb +0 -7
  140. data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
  141. data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
  142. data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
  143. data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
  144. data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
  145. data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
  146. data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
  147. data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
  148. data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -3
  149. data/guides/code/getting_started/bin/bundle +0 -4
  150. data/guides/code/getting_started/bin/rails +0 -4
  151. data/guides/code/getting_started/bin/rake +0 -4
  152. data/guides/code/getting_started/config.ru +0 -4
  153. data/guides/code/getting_started/config/application.rb +0 -18
  154. data/guides/code/getting_started/config/boot.rb +0 -4
  155. data/guides/code/getting_started/config/database.yml +0 -25
  156. data/guides/code/getting_started/config/environment.rb +0 -5
  157. data/guides/code/getting_started/config/environments/development.rb +0 -30
  158. data/guides/code/getting_started/config/environments/production.rb +0 -80
  159. data/guides/code/getting_started/config/environments/test.rb +0 -36
  160. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
  161. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
  162. data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
  163. data/guides/code/getting_started/config/initializers/locale.rb +0 -9
  164. data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
  165. data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
  166. data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
  167. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
  168. data/guides/code/getting_started/config/locales/en.yml +0 -23
  169. data/guides/code/getting_started/config/routes.rb +0 -7
  170. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
  171. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
  172. data/guides/code/getting_started/db/schema.rb +0 -33
  173. data/guides/code/getting_started/db/seeds.rb +0 -7
  174. data/guides/code/getting_started/public/404.html +0 -58
  175. data/guides/code/getting_started/public/422.html +0 -58
  176. data/guides/code/getting_started/public/500.html +0 -57
  177. data/guides/code/getting_started/public/favicon.ico +0 -0
  178. data/guides/code/getting_started/public/robots.txt +0 -5
  179. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
  180. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
  181. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
  182. data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
  183. data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
  184. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
  185. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
  186. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
  187. data/guides/code/getting_started/test/models/comment_test.rb +0 -7
  188. data/guides/code/getting_started/test/models/post_test.rb +0 -7
  189. data/guides/code/getting_started/test/test_helper.rb +0 -15
  190. data/guides/source/kindle/KINDLE.md +0 -26
@@ -0,0 +1,433 @@
1
+ Active Record and PostgreSQL
2
+ ============================
3
+
4
+ This guide covers PostgreSQL specific usage of Active Record.
5
+
6
+ After reading this guide, you will know:
7
+
8
+ * How to use PostgreSQL's datatypes.
9
+ * How to use UUID primary keys.
10
+ * How to implement full text search with PostgreSQL.
11
+ * How to back your Active Record models with database views.
12
+
13
+ --------------------------------------------------------------------------------
14
+
15
+ In order to use the PostgreSQL adapter you need to have at least version 8.2
16
+ installed. Older versions are not supported.
17
+
18
+ To get started with PostgreSQL have a look at the
19
+ [configuring Rails guide](configuring.html#configuring-a-postgresql-database).
20
+ It describes how to properly setup Active Record for PostgreSQL.
21
+
22
+ Datatypes
23
+ ---------
24
+
25
+ PostgreSQL offers a number of specific datatypes. Following is a list of types,
26
+ that are supported by the PostgreSQL adapter.
27
+
28
+ ### Bytea
29
+
30
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-binary.html)
31
+ * [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-binarystring.html)
32
+
33
+ ```ruby
34
+ # db/migrate/20140207133952_create_documents.rb
35
+ create_table :documents do |t|
36
+ t.binary 'payload'
37
+ end
38
+
39
+ # app/models/document.rb
40
+ class Document < ActiveRecord::Base
41
+ end
42
+
43
+ # Usage
44
+ data = File.read(Rails.root + "tmp/output.pdf")
45
+ Document.create payload: data
46
+ ```
47
+
48
+ ### Array
49
+
50
+ * [type definition](http://www.postgresql.org/docs/9.3/static/arrays.html)
51
+ * [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-array.html)
52
+
53
+ ```ruby
54
+ # db/migrate/20140207133952_create_books.rb
55
+ create_table :books do |t|
56
+ t.string 'title'
57
+ t.string 'tags', array: true
58
+ t.integer 'ratings', array: true
59
+ end
60
+ add_index :books, :tags, using: 'gin'
61
+ add_index :books, :ratings, using: 'gin'
62
+
63
+ # app/models/book.rb
64
+ class Book < ActiveRecord::Base
65
+ end
66
+
67
+ # Usage
68
+ Book.create title: "Brave New World",
69
+ tags: ["fantasy", "fiction"],
70
+ ratings: [4, 5]
71
+
72
+ ## Books for a single tag
73
+ Book.where("'fantasy' = ANY (tags)")
74
+
75
+ ## Books for multiple tags
76
+ Book.where("tags @> ARRAY[?]::varchar[]", ["fantasy", "fiction"])
77
+
78
+ ## Books with 3 or more ratings
79
+ Book.where("array_length(ratings, 1) >= 3")
80
+ ```
81
+
82
+ ### Hstore
83
+
84
+ * [type definition](http://www.postgresql.org/docs/9.3/static/hstore.html)
85
+
86
+ ```ruby
87
+ # db/migrate/20131009135255_create_profiles.rb
88
+ ActiveRecord::Schema.define do
89
+ create_table :profiles do |t|
90
+ t.hstore 'settings'
91
+ end
92
+ end
93
+
94
+ # app/models/profile.rb
95
+ class Profile < ActiveRecord::Base
96
+ end
97
+
98
+ # Usage
99
+ Profile.create(settings: { "color" => "blue", "resolution" => "800x600" })
100
+
101
+ profile = Profile.first
102
+ profile.settings # => {"color"=>"blue", "resolution"=>"800x600"}
103
+
104
+ profile.settings = {"color" => "yellow", "resolution" => "1280x1024"}
105
+ profile.save!
106
+ ```
107
+
108
+ ### JSON
109
+
110
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-json.html)
111
+ * [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-json.html)
112
+
113
+ ```ruby
114
+ # db/migrate/20131220144913_create_events.rb
115
+ create_table :events do |t|
116
+ t.json 'payload'
117
+ end
118
+
119
+ # app/models/event.rb
120
+ class Event < ActiveRecord::Base
121
+ end
122
+
123
+ # Usage
124
+ Event.create(payload: { kind: "user_renamed", change: ["jack", "john"]})
125
+
126
+ event = Event.first
127
+ event.payload # => {"kind"=>"user_renamed", "change"=>["jack", "john"]}
128
+
129
+ ## Query based on JSON document
130
+ # The -> operator returns the original JSON type (which might be an object), whereas ->> returns text
131
+ Event.where("payload->>'kind' = ?", "user_renamed")
132
+ ```
133
+
134
+ ### Range Types
135
+
136
+ * [type definition](http://www.postgresql.org/docs/9.3/static/rangetypes.html)
137
+ * [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-range.html)
138
+
139
+ This type is mapped to Ruby [`Range`](http://www.ruby-doc.org/core-2.1.1/Range.html) objects.
140
+
141
+ ```ruby
142
+ # db/migrate/20130923065404_create_events.rb
143
+ create_table :events do |t|
144
+ t.daterange 'duration'
145
+ end
146
+
147
+ # app/models/event.rb
148
+ class Event < ActiveRecord::Base
149
+ end
150
+
151
+ # Usage
152
+ Event.create(duration: Date.new(2014, 2, 11)..Date.new(2014, 2, 12))
153
+
154
+ event = Event.first
155
+ event.duration # => Tue, 11 Feb 2014...Thu, 13 Feb 2014
156
+
157
+ ## All Events on a given date
158
+ Event.where("duration @> ?::date", Date.new(2014, 2, 12))
159
+
160
+ ## Working with range bounds
161
+ event = Event.
162
+ select("lower(duration) AS starts_at").
163
+ select("upper(duration) AS ends_at").first
164
+
165
+ event.starts_at # => Tue, 11 Feb 2014
166
+ event.ends_at # => Thu, 13 Feb 2014
167
+ ```
168
+
169
+ ### Composite Types
170
+
171
+ * [type definition](http://www.postgresql.org/docs/9.3/static/rowtypes.html)
172
+
173
+ Currently there is no special support for composite types. They are mapped to
174
+ normal text columns:
175
+
176
+ ```sql
177
+ CREATE TYPE full_address AS
178
+ (
179
+ city VARCHAR(90),
180
+ street VARCHAR(90)
181
+ );
182
+ ```
183
+
184
+ ```ruby
185
+ # db/migrate/20140207133952_create_contacts.rb
186
+ execute <<-SQL
187
+ CREATE TYPE full_address AS
188
+ (
189
+ city VARCHAR(90),
190
+ street VARCHAR(90)
191
+ );
192
+ SQL
193
+ create_table :contacts do |t|
194
+ t.column :address, :full_address
195
+ end
196
+
197
+ # app/models/contact.rb
198
+ class Contact < ActiveRecord::Base
199
+ end
200
+
201
+ # Usage
202
+ Contact.create address: "(Paris,Champs-Élysées)"
203
+ contact = Contact.first
204
+ contact.address # => "(Paris,Champs-Élysées)"
205
+ contact.address = "(Paris,Rue Basse)"
206
+ contact.save!
207
+ ```
208
+
209
+ ### Enumerated Types
210
+
211
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-enum.html)
212
+
213
+ Currently there is no special support for enumerated types. They are mapped as
214
+ normal text columns:
215
+
216
+ ```ruby
217
+ # db/migrate/20131220144913_create_articles.rb
218
+ execute <<-SQL
219
+ CREATE TYPE article_status AS ENUM ('draft', 'published');
220
+ SQL
221
+ create_table :articles do |t|
222
+ t.column :status, :article_status
223
+ end
224
+
225
+ # app/models/article.rb
226
+ class Article < ActiveRecord::Base
227
+ end
228
+
229
+ # Usage
230
+ Article.create status: "draft"
231
+ article = Article.first
232
+ article.status # => "draft"
233
+
234
+ article.status = "published"
235
+ article.save!
236
+ ```
237
+
238
+ ### UUID
239
+
240
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-uuid.html)
241
+ * [generator functions](http://www.postgresql.org/docs/9.3/static/uuid-ossp.html)
242
+
243
+
244
+ ```ruby
245
+ # db/migrate/20131220144913_create_revisions.rb
246
+ create_table :revisions do |t|
247
+ t.column :identifier, :uuid
248
+ end
249
+
250
+ # app/models/revision.rb
251
+ class Revision < ActiveRecord::Base
252
+ end
253
+
254
+ # Usage
255
+ Revision.create identifier: "A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11"
256
+
257
+ revision = Revision.first
258
+ revision.identifier # => "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"
259
+ ```
260
+
261
+ ### Bit String Types
262
+
263
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-bit.html)
264
+ * [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-bitstring.html)
265
+
266
+ ```ruby
267
+ # db/migrate/20131220144913_create_users.rb
268
+ create_table :users, force: true do |t|
269
+ t.column :settings, "bit(8)"
270
+ end
271
+
272
+ # app/models/device.rb
273
+ class User < ActiveRecord::Base
274
+ end
275
+
276
+ # Usage
277
+ User.create settings: "01010011"
278
+ user = User.first
279
+ user.settings # => "01010011"
280
+ user.settings = "0xAF"
281
+ user.settings # => 10101111
282
+ user.save!
283
+ ```
284
+
285
+ ### Network Address Types
286
+
287
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-net-types.html)
288
+
289
+ The types `inet` and `cidr` are mapped to Ruby
290
+ [`IPAddr`](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/ipaddr/rdoc/IPAddr.html)
291
+ objects. The `macaddr` type is mapped to normal text.
292
+
293
+ ```ruby
294
+ # db/migrate/20140508144913_create_devices.rb
295
+ create_table(:devices, force: true) do |t|
296
+ t.inet 'ip'
297
+ t.cidr 'network'
298
+ t.macaddr 'address'
299
+ end
300
+
301
+ # app/models/device.rb
302
+ class Device < ActiveRecord::Base
303
+ end
304
+
305
+ # Usage
306
+ macbook = Device.create(ip: "192.168.1.12",
307
+ network: "192.168.2.0/24",
308
+ address: "32:01:16:6d:05:ef")
309
+
310
+ macbook.ip
311
+ # => #<IPAddr: IPv4:192.168.1.12/255.255.255.255>
312
+
313
+ macbook.network
314
+ # => #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
315
+
316
+ macbook.address
317
+ # => "32:01:16:6d:05:ef"
318
+ ```
319
+
320
+ ### Geometric Types
321
+
322
+ * [type definition](http://www.postgresql.org/docs/9.3/static/datatype-geometric.html)
323
+
324
+ All geometric types, with the exception of `points` are mapped to normal text.
325
+ A point is casted to an array containing `x` and `y` coordinates.
326
+
327
+
328
+ UUID Primary Keys
329
+ -----------------
330
+
331
+ NOTE: you need to enable the `uuid-ossp` extension to generate UUIDs.
332
+
333
+ ```ruby
334
+ # db/migrate/20131220144913_create_devices.rb
335
+ enable_extension 'uuid-ossp' unless extension_enabled?('uuid-ossp')
336
+ create_table :devices, id: :uuid, default: 'uuid_generate_v4()' do |t|
337
+ t.string :kind
338
+ end
339
+
340
+ # app/models/device.rb
341
+ class Device < ActiveRecord::Base
342
+ end
343
+
344
+ # Usage
345
+ device = Device.create
346
+ device.id # => "814865cd-5a1d-4771-9306-4268f188fe9e"
347
+ ```
348
+
349
+ Full Text Search
350
+ ----------------
351
+
352
+ ```ruby
353
+ # db/migrate/20131220144913_create_documents.rb
354
+ create_table :documents do |t|
355
+ t.string 'title'
356
+ t.string 'body'
357
+ end
358
+
359
+ execute "CREATE INDEX documents_idx ON documents USING gin(to_tsvector('english', title || ' ' || body));"
360
+
361
+ # app/models/document.rb
362
+ class Document < ActiveRecord::Base
363
+ end
364
+
365
+ # Usage
366
+ Document.create(title: "Cats and Dogs", body: "are nice!")
367
+
368
+ ## all documents matching 'cat & dog'
369
+ Document.where("to_tsvector('english', title || ' ' || body) @@ to_tsquery(?)",
370
+ "cat & dog")
371
+ ```
372
+
373
+ Database Views
374
+ --------------
375
+
376
+ * [view creation](http://www.postgresql.org/docs/9.3/static/sql-createview.html)
377
+
378
+ Imagine you need to work with a legacy database containing the following table:
379
+
380
+ ```
381
+ rails_pg_guide=# \d "TBL_ART"
382
+ Table "public.TBL_ART"
383
+ Column | Type | Modifiers
384
+ ------------+-----------------------------+------------------------------------------------------------
385
+ INT_ID | integer | not null default nextval('"TBL_ART_INT_ID_seq"'::regclass)
386
+ STR_TITLE | character varying |
387
+ STR_STAT | character varying | default 'draft'::character varying
388
+ DT_PUBL_AT | timestamp without time zone |
389
+ BL_ARCH | boolean | default false
390
+ Indexes:
391
+ "TBL_ART_pkey" PRIMARY KEY, btree ("INT_ID")
392
+ ```
393
+
394
+ This table does not follow the Rails conventions at all.
395
+ Because simple PostgreSQL views are updateable by default,
396
+ we can wrap it as follows:
397
+
398
+ ```ruby
399
+ # db/migrate/20131220144913_create_articles_view.rb
400
+ execute <<-SQL
401
+ CREATE VIEW articles AS
402
+ SELECT "INT_ID" AS id,
403
+ "STR_TITLE" AS title,
404
+ "STR_STAT" AS status,
405
+ "DT_PUBL_AT" AS published_at,
406
+ "BL_ARCH" AS archived
407
+ FROM "TBL_ART"
408
+ WHERE "BL_ARCH" = 'f'
409
+ SQL
410
+
411
+ # app/models/article.rb
412
+ class Article < ActiveRecord::Base
413
+ self.primary_key = "id"
414
+ def archive!
415
+ update_attribute :archived, true
416
+ end
417
+ end
418
+
419
+ # Usage
420
+ first = Article.create! title: "Winter is coming",
421
+ status: "published",
422
+ published_at: 1.year.ago
423
+ second = Article.create! title: "Brace yourself",
424
+ status: "draft",
425
+ published_at: 1.month.ago
426
+
427
+ Article.count # => 1
428
+ first.archive!
429
+ Article.count # => 2
430
+ ```
431
+
432
+ NOTE: This application only cares about non-archived `Articles`. A view also
433
+ allows for conditions so we can exclude the archived `Articles` directly.
@@ -58,6 +58,7 @@ The methods are:
58
58
 
59
59
  * `bind`
60
60
  * `create_with`
61
+ * `distinct`
61
62
  * `eager_load`
62
63
  * `extending`
63
64
  * `from`
@@ -76,7 +77,6 @@ The methods are:
76
77
  * `reorder`
77
78
  * `reverse_order`
78
79
  * `select`
79
- * `distinct`
80
80
  * `uniq`
81
81
  * `where`
82
82
 
@@ -91,11 +91,11 @@ The primary operation of `Model.find(options)` can be summarized as:
91
91
 
92
92
  ### Retrieving a Single Object
93
93
 
94
- Active Record provides five different ways of retrieving a single object.
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.
113
-
114
- #### `take`
112
+ The `find` method will raise an `ActiveRecord::RecordNotFound` exception if no matching record is found.
115
113
 
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.
128
+ WARNING: The `find` method will raise an `ActiveRecord::RecordNotFound` exception unless a matching record is found for **all** of the supplied primary keys.
130
129
 
131
- TIP: The retrieved record may vary depending on the database engine.
132
-
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.
182
+ The `first` method returns `nil` if no matching record is found and no exception will be raised.
201
183
 
202
- #### `first!`
203
-
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
- ```
247
-
248
- It is equivalent to writing:
249
-
250
- ```ruby
251
- Client.where(first_name: 'Lifo').take!
252
- ```
253
-
254
- ### Retrieving Multiple Objects
255
-
256
- #### Using Multiple Primary Keys
218
+ The `last` method returns `nil` if no matching record is found and no exception will be raised.
257
219
 
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:
220
+ You can pass in a numerical argument to the `last` method to return up to that number of results. For example
259
221
 
260
222
  ```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,28 +328,24 @@ 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
 
379
- Another example would be if you wanted multiple workers handling the same processing queue. You could have each worker handle 10000 records by setting the appropriate `:start` option on each worker.
380
-
381
335
  #### `find_in_batches`
382
336
 
383
337
  The `find_in_batches` method is similar to `find_each`, since both retrieve batches of records. The difference is that `find_in_batches` yields _batches_ to the block as an array of models, instead of individually. The following example will yield to the supplied block an array of up to 1000 invoices at a time, with the final block containing any remaining invoices:
384
338
 
385
339
  ```ruby
386
340
  # Give add_invoices an array of 1000 invoices at a time
387
- Invoice.find_in_batches(include: :invoice_lines) do |invoices|
341
+ Invoice.find_in_batches do |invoices|
388
342
  export.add_invoices(invoices)
389
343
  end
390
344
  ```
391
345
 
392
- NOTE: The `:include` option allows you to name associations that should be loaded alongside with the models.
393
-
394
346
  ##### Options for `find_in_batches`
395
347
 
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`.
348
+ The `find_in_batches` method accepts the same `:batch_size` and `:start` options as `find_each`.
397
349
 
398
350
  Conditions
399
351
  ----------
@@ -436,7 +388,7 @@ to this code:
436
388
  Client.where("orders_count = #{params[:orders]}")
437
389
  ```
438
390
 
439
- because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database **as-is**. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
391
+ because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database **as-is**. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out they can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
440
392
 
441
393
  TIP: For more information on the dangers of SQL injection, see the [Ruby on Rails Security Guide](security.html#sql-injection).
442
394
 
@@ -472,8 +424,8 @@ Client.where('locked' => true)
472
424
  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
425
 
474
426
  ```ruby
475
- Post.where(author: author)
476
- Author.joins(:posts).where(posts: {author: author})
427
+ Article.where(author: author)
428
+ Author.joins(:articles).where(articles: { author: author })
477
429
  ```
478
430
 
479
431
  NOTE: The values cannot be symbols. For example, you cannot do `Client.where(status: :active)`.
@@ -511,7 +463,7 @@ SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
511
463
  `NOT` SQL queries can be built by `where.not`.
512
464
 
513
465
  ```ruby
514
- Post.where.not(author: author)
466
+ Article.where.not(author: author)
515
467
  ```
516
468
 
517
469
  In other words, this query can be generated by calling `where` with no argument, then immediately chain with `not` passing `where` conditions.
@@ -524,12 +476,18 @@ To retrieve records from the database in a specific order, you can use the `orde
524
476
  For example, if you're getting a set of records and want to order them in ascending order by the `created_at` field in your table:
525
477
 
526
478
  ```ruby
479
+ Client.order(:created_at)
480
+ # OR
527
481
  Client.order("created_at")
528
482
  ```
529
483
 
530
484
  You could specify `ASC` or `DESC` as well:
531
485
 
532
486
  ```ruby
487
+ Client.order(created_at: :desc)
488
+ # OR
489
+ Client.order(created_at: :asc)
490
+ # OR
533
491
  Client.order("created_at DESC")
534
492
  # OR
535
493
  Client.order("created_at ASC")
@@ -538,16 +496,20 @@ Client.order("created_at ASC")
538
496
  Or ordering by multiple fields:
539
497
 
540
498
  ```ruby
499
+ Client.order(orders_count: :asc, created_at: :desc)
500
+ # OR
501
+ Client.order(:orders_count, created_at: :desc)
502
+ # OR
541
503
  Client.order("orders_count ASC, created_at DESC")
542
504
  # OR
543
505
  Client.order("orders_count ASC", "created_at DESC")
544
506
  ```
545
507
 
546
- If you want to call `order` multiple times e.g. in different context, new order will prepend previous one
508
+ If you want to call `order` multiple times e.g. in different context, new order will append previous one
547
509
 
548
510
  ```ruby
549
511
  Client.order("orders_count ASC").order("created_at DESC")
550
- # SELECT * FROM clients ORDER BY created_at DESC, orders_count ASC
512
+ # SELECT * FROM clients ORDER BY orders_count ASC, created_at DESC
551
513
  ```
552
514
 
553
515
  Selecting Specific Fields
@@ -649,6 +611,23 @@ FROM orders
649
611
  GROUP BY date(created_at)
650
612
  ```
651
613
 
614
+ ### Total of grouped items
615
+
616
+ To get the total of grouped items on a single query call `count` after the `group`.
617
+
618
+ ```ruby
619
+ Order.group(:status).count
620
+ # => { 'awaiting_approval' => 7, 'paid' => 12 }
621
+ ```
622
+
623
+ The SQL that would be executed would be something like this:
624
+
625
+ ```sql
626
+ SELECT COUNT (*) AS count_all, status AS status
627
+ FROM "orders"
628
+ GROUP BY status
629
+ ```
630
+
652
631
  Having
653
632
  ------
654
633
 
@@ -675,39 +654,37 @@ This will return single order objects for each day, but only those that are orde
675
654
  Overriding Conditions
676
655
  ---------------------
677
656
 
678
- ### `except`
657
+ ### `unscope`
679
658
 
680
- You can specify certain conditions to be excepted by using the `except` method. For example:
659
+ You can specify certain conditions to be removed using the `unscope` method. For example:
681
660
 
682
661
  ```ruby
683
- Post.where('id > 10').limit(20).order('id asc').except(:order)
662
+ Article.where('id > 10').limit(20).order('id asc').unscope(:order)
684
663
  ```
685
664
 
686
665
  The SQL that would be executed:
687
666
 
688
667
  ```sql
689
- SELECT * FROM posts WHERE id > 10 LIMIT 20
690
- ```
691
-
692
- ### `unscope`
668
+ SELECT * FROM articles WHERE id > 10 LIMIT 20
693
669
 
694
- The `except` method does not work when the relation is merged. For example:
670
+ # Original query without `unscope`
671
+ SELECT * FROM articles WHERE id > 10 ORDER BY id asc LIMIT 20
695
672
 
696
- ```ruby
697
- Post.comments.except(:order)
698
673
  ```
699
674
 
700
- will still have an order if the order comes from a default scope on Comment. In order to remove all ordering, even from relations which are merged in, use unscope as follows:
675
+ You can also unscope specific `where` clauses. For example:
701
676
 
702
677
  ```ruby
703
- Post.order('id DESC').limit(20).unscope(:order) = Post.limit(20)
704
- Post.order('id DESC').limit(20).unscope(:order, :limit) = Post.all
678
+ Article.where(id: 10, trashed: false).unscope(where: :id)
679
+ # SELECT "articles".* FROM "articles" WHERE trashed = 0
705
680
  ```
706
681
 
707
- You can additionally unscope specific where clauses. For example:
682
+ A relation which has used `unscope` will affect any relation it is
683
+ merged in to:
708
684
 
709
685
  ```ruby
710
- Post.where(:id => 10).limit(1).unscope(where: :id, :limit).order('id DESC') = Post.order('id DESC')
686
+ Article.order('id asc').merge(Article.unscope(:order))
687
+ # SELECT "articles".* FROM "articles"
711
688
  ```
712
689
 
713
690
  ### `only`
@@ -715,13 +692,17 @@ Post.where(:id => 10).limit(1).unscope(where: :id, :limit).order('id DESC') = Po
715
692
  You can also override conditions using the `only` method. For example:
716
693
 
717
694
  ```ruby
718
- Post.where('id > 10').limit(20).order('id desc').only(:order, :where)
695
+ Article.where('id > 10').limit(20).order('id desc').only(:order, :where)
719
696
  ```
720
697
 
721
698
  The SQL that would be executed:
722
699
 
723
700
  ```sql
724
- SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
701
+ SELECT * FROM articles WHERE id > 10 ORDER BY id DESC
702
+
703
+ # Original query without `only`
704
+ SELECT "articles".* FROM "articles" WHERE (id > 10) ORDER BY id desc LIMIT 20
705
+
725
706
  ```
726
707
 
727
708
  ### `reorder`
@@ -729,25 +710,25 @@ SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
729
710
  The `reorder` method overrides the default scope order. For example:
730
711
 
731
712
  ```ruby
732
- class Post < ActiveRecord::Base
733
- ..
734
- ..
735
- has_many :comments, order: 'posted_at DESC'
713
+ class Article < ActiveRecord::Base
714
+ has_many :comments, -> { order('posted_at DESC') }
736
715
  end
737
716
 
738
- Post.find(10).comments.reorder('name')
717
+ Article.find(10).comments.reorder('name')
739
718
  ```
740
719
 
741
720
  The SQL that would be executed:
742
721
 
743
722
  ```sql
744
- SELECT * FROM posts WHERE id = 10 ORDER BY name
723
+ SELECT * FROM articles WHERE id = 10
724
+ SELECT * FROM comments WHERE article_id = 10 ORDER BY name
745
725
  ```
746
726
 
747
727
  In case the `reorder` clause is not used, the SQL executed would be:
748
728
 
749
729
  ```sql
750
- SELECT * FROM posts WHERE id = 10 ORDER BY posted_at DESC
730
+ SELECT * FROM articles WHERE id = 10
731
+ SELECT * FROM comments WHERE article_id = 10 ORDER BY posted_at DESC
751
732
  ```
752
733
 
753
734
  ### `reverse_order`
@@ -778,27 +759,53 @@ SELECT * FROM clients WHERE orders_count > 10 ORDER BY clients.id DESC
778
759
 
779
760
  This method accepts **no** arguments.
780
761
 
762
+ ### `rewhere`
763
+
764
+ The `rewhere` method overrides an existing, named where condition. For example:
765
+
766
+ ```ruby
767
+ Article.where(trashed: true).rewhere(trashed: false)
768
+ ```
769
+
770
+ The SQL that would be executed:
771
+
772
+ ```sql
773
+ SELECT * FROM articles WHERE `trashed` = 0
774
+ ```
775
+
776
+ In case the `rewhere` clause is not used,
777
+
778
+ ```ruby
779
+ Article.where(trashed: true).where(trashed: false)
780
+ ```
781
+
782
+ the SQL executed would be:
783
+
784
+ ```sql
785
+ SELECT * FROM articles WHERE `trashed` = 1 AND `trashed` = 0
786
+ ```
787
+
781
788
  Null Relation
782
789
  -------------
783
790
 
784
791
  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.
785
792
 
786
793
  ```ruby
787
- Post.none # returns an empty Relation and fires no queries.
794
+ Article.none # returns an empty Relation and fires no queries.
788
795
  ```
789
796
 
790
797
  ```ruby
791
- # The visible_posts method below is expected to return a Relation.
792
- @posts = current_user.visible_posts.where(name: params[:name])
798
+ # The visible_articles method below is expected to return a Relation.
799
+ @articles = current_user.visible_articles.where(name: params[:name])
793
800
 
794
- def visible_posts
801
+ def visible_articles
795
802
  case role
796
803
  when 'Country Manager'
797
- Post.where(country: country)
804
+ Article.where(country: country)
798
805
  when 'Reviewer'
799
- Post.published
806
+ Article.published
800
807
  when 'Bad User'
801
- Post.none # => returning [] or nil breaks the caller code in this case
808
+ Article.none # => returning [] or nil breaks the caller code in this case
802
809
  end
803
810
  end
804
811
  ```
@@ -867,7 +874,7 @@ For example:
867
874
  Item.transaction do
868
875
  i = Item.lock.first
869
876
  i.name = 'Jones'
870
- i.save
877
+ i.save!
871
878
  end
872
879
  ```
873
880
 
@@ -923,23 +930,23 @@ SELECT clients.* FROM clients LEFT OUTER JOIN addresses ON addresses.client_id =
923
930
 
924
931
  WARNING: This method only works with `INNER JOIN`.
925
932
 
926
- 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.
933
+ 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.
927
934
 
928
- For example, consider the following `Category`, `Post`, `Comments` and `Guest` models:
935
+ For example, consider the following `Category`, `Article`, `Comment`, `Guest` and `Tag` models:
929
936
 
930
937
  ```ruby
931
938
  class Category < ActiveRecord::Base
932
- has_many :posts
939
+ has_many :articles
933
940
  end
934
941
 
935
- class Post < ActiveRecord::Base
942
+ class Article < ActiveRecord::Base
936
943
  belongs_to :category
937
944
  has_many :comments
938
945
  has_many :tags
939
946
  end
940
947
 
941
948
  class Comment < ActiveRecord::Base
942
- belongs_to :post
949
+ belongs_to :article
943
950
  has_one :guest
944
951
  end
945
952
 
@@ -948,7 +955,7 @@ class Guest < ActiveRecord::Base
948
955
  end
949
956
 
950
957
  class Tag < ActiveRecord::Base
951
- belongs_to :post
958
+ belongs_to :article
952
959
  end
953
960
  ```
954
961
 
@@ -957,64 +964,64 @@ Now all of the following will produce the expected join queries using `INNER JOI
957
964
  #### Joining a Single Association
958
965
 
959
966
  ```ruby
960
- Category.joins(:posts)
967
+ Category.joins(:articles)
961
968
  ```
962
969
 
963
970
  This produces:
964
971
 
965
972
  ```sql
966
973
  SELECT categories.* FROM categories
967
- INNER JOIN posts ON posts.category_id = categories.id
974
+ INNER JOIN articles ON articles.category_id = categories.id
968
975
  ```
969
976
 
970
- 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`.
977
+ 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`.
971
978
 
972
979
  #### Joining Multiple Associations
973
980
 
974
981
  ```ruby
975
- Post.joins(:category, :comments)
982
+ Article.joins(:category, :comments)
976
983
  ```
977
984
 
978
985
  This produces:
979
986
 
980
987
  ```sql
981
- SELECT posts.* FROM posts
982
- INNER JOIN categories ON posts.category_id = categories.id
983
- INNER JOIN comments ON comments.post_id = posts.id
988
+ SELECT articles.* FROM articles
989
+ INNER JOIN categories ON articles.category_id = categories.id
990
+ INNER JOIN comments ON comments.article_id = articles.id
984
991
  ```
985
992
 
986
- 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.
993
+ 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.
987
994
 
988
995
  #### Joining Nested Associations (Single Level)
989
996
 
990
997
  ```ruby
991
- Post.joins(comments: :guest)
998
+ Article.joins(comments: :guest)
992
999
  ```
993
1000
 
994
1001
  This produces:
995
1002
 
996
1003
  ```sql
997
- SELECT posts.* FROM posts
998
- INNER JOIN comments ON comments.post_id = posts.id
1004
+ SELECT articles.* FROM articles
1005
+ INNER JOIN comments ON comments.article_id = articles.id
999
1006
  INNER JOIN guests ON guests.comment_id = comments.id
1000
1007
  ```
1001
1008
 
1002
- Or, in English: "return all posts that have a comment made by a guest."
1009
+ Or, in English: "return all articles that have a comment made by a guest."
1003
1010
 
1004
1011
  #### Joining Nested Associations (Multiple Level)
1005
1012
 
1006
1013
  ```ruby
1007
- Category.joins(posts: [{comments: :guest}, :tags])
1014
+ Category.joins(articles: [{ comments: :guest }, :tags])
1008
1015
  ```
1009
1016
 
1010
1017
  This produces:
1011
1018
 
1012
1019
  ```sql
1013
1020
  SELECT categories.* FROM categories
1014
- INNER JOIN posts ON posts.category_id = categories.id
1015
- INNER JOIN comments ON comments.post_id = posts.id
1021
+ INNER JOIN articles ON articles.category_id = categories.id
1022
+ INNER JOIN comments ON comments.article_id = articles.id
1016
1023
  INNER JOIN guests ON guests.comment_id = comments.id
1017
- INNER JOIN tags ON tags.post_id = posts.id
1024
+ INNER JOIN tags ON tags.article_id = articles.id
1018
1025
  ```
1019
1026
 
1020
1027
  ### Specifying Conditions on the Joined Tables
@@ -1030,7 +1037,7 @@ An alternative and cleaner syntax is to nest the hash conditions:
1030
1037
 
1031
1038
  ```ruby
1032
1039
  time_range = (Time.now.midnight - 1.day)..Time.now.midnight
1033
- Client.joins(:orders).where(orders: {created_at: time_range})
1040
+ Client.joins(:orders).where(orders: { created_at: time_range })
1034
1041
  ```
1035
1042
 
1036
1043
  This will find all clients who have orders that were created yesterday, again using a `BETWEEN` SQL expression.
@@ -1083,18 +1090,18 @@ Active Record lets you eager load any number of associations with a single `Mode
1083
1090
  #### Array of Multiple Associations
1084
1091
 
1085
1092
  ```ruby
1086
- Post.includes(:category, :comments)
1093
+ Article.includes(:category, :comments)
1087
1094
  ```
1088
1095
 
1089
- This loads all the posts and the associated category and comments for each post.
1096
+ This loads all the articles and the associated category and comments for each article.
1090
1097
 
1091
1098
  #### Nested Associations Hash
1092
1099
 
1093
1100
  ```ruby
1094
- Category.includes(posts: [{comments: :guest}, :tags]).find(1)
1101
+ Category.includes(articles: [{ comments: :guest }, :tags]).find(1)
1095
1102
  ```
1096
1103
 
1097
- 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.
1104
+ 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.
1098
1105
 
1099
1106
  ### Specifying Conditions on Eager Loaded Associations
1100
1107
 
@@ -1103,18 +1110,31 @@ Even though Active Record lets you specify conditions on the eager loaded associ
1103
1110
  However if you must do this, you may use `where` as you would normally.
1104
1111
 
1105
1112
  ```ruby
1106
- Post.includes(:comments).where("comments.visible" => true)
1113
+ Article.includes(:comments).where(comments: { visible: true })
1107
1114
  ```
1108
1115
 
1109
- This would generate a query which contains a `LEFT OUTER JOIN` whereas the `joins` method would generate one using the `INNER JOIN` function instead.
1116
+ This would generate a query which contains a `LEFT OUTER JOIN` whereas the
1117
+ `joins` method would generate one using the `INNER JOIN` function instead.
1110
1118
 
1111
1119
  ```ruby
1112
- 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)
1120
+ 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)
1113
1121
  ```
1114
1122
 
1115
1123
  If there was no `where` condition, this would generate the normal set of two queries.
1116
1124
 
1117
- If, in the case of this `includes` query, there were no comments for any posts, all the posts would still be loaded. By using `joins` (an INNER JOIN), the join conditions **must** match, otherwise no records will be returned.
1125
+ NOTE: Using `where` like this will only work when you pass it a Hash. For
1126
+ SQL-fragments you need use `references` to force joined tables:
1127
+
1128
+ ```ruby
1129
+ Article.includes(:comments).where("comments.visible = true").references(:comments)
1130
+ ```
1131
+
1132
+ If, in the case of this `includes` query, there were no comments for any
1133
+ articles, all the articles would still be loaded. By using `joins` (an INNER
1134
+ JOIN), the join conditions **must** match, otherwise no records will be
1135
+ returned.
1136
+
1137
+
1118
1138
 
1119
1139
  Scopes
1120
1140
  ------
@@ -1124,7 +1144,7 @@ Scoping allows you to specify commonly-used queries which can be referenced as m
1124
1144
  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:
1125
1145
 
1126
1146
  ```ruby
1127
- class Post < ActiveRecord::Base
1147
+ class Article < ActiveRecord::Base
1128
1148
  scope :published, -> { where(published: true) }
1129
1149
  end
1130
1150
  ```
@@ -1132,7 +1152,7 @@ end
1132
1152
  This is exactly the same as defining a class method, and which you use is a matter of personal preference:
1133
1153
 
1134
1154
  ```ruby
1135
- class Post < ActiveRecord::Base
1155
+ class Article < ActiveRecord::Base
1136
1156
  def self.published
1137
1157
  where(published: true)
1138
1158
  end
@@ -1142,7 +1162,7 @@ end
1142
1162
  Scopes are also chainable within scopes:
1143
1163
 
1144
1164
  ```ruby
1145
- class Post < ActiveRecord::Base
1165
+ class Article < ActiveRecord::Base
1146
1166
  scope :published, -> { where(published: true) }
1147
1167
  scope :published_and_commented, -> { published.where("comments_count > 0") }
1148
1168
  end
@@ -1151,14 +1171,14 @@ end
1151
1171
  To call this `published` scope we can call it on either the class:
1152
1172
 
1153
1173
  ```ruby
1154
- Post.published # => [published posts]
1174
+ Article.published # => [published articles]
1155
1175
  ```
1156
1176
 
1157
- Or on an association consisting of `Post` objects:
1177
+ Or on an association consisting of `Article` objects:
1158
1178
 
1159
1179
  ```ruby
1160
1180
  category = Category.first
1161
- category.posts.published # => [published posts belonging to this category]
1181
+ category.articles.published # => [published articles belonging to this category]
1162
1182
  ```
1163
1183
 
1164
1184
  ### Passing in arguments
@@ -1166,21 +1186,21 @@ category.posts.published # => [published posts belonging to this category]
1166
1186
  Your scope can take arguments:
1167
1187
 
1168
1188
  ```ruby
1169
- class Post < ActiveRecord::Base
1189
+ class Article < ActiveRecord::Base
1170
1190
  scope :created_before, ->(time) { where("created_at < ?", time) }
1171
1191
  end
1172
1192
  ```
1173
1193
 
1174
- This may then be called using this:
1194
+ Call the scope as if it were a class method:
1175
1195
 
1176
1196
  ```ruby
1177
- Post.created_before(Time.zone.now)
1197
+ Article.created_before(Time.zone.now)
1178
1198
  ```
1179
1199
 
1180
1200
  However, this is just duplicating the functionality that would be provided to you by a class method.
1181
1201
 
1182
1202
  ```ruby
1183
- class Post < ActiveRecord::Base
1203
+ class Article < ActiveRecord::Base
1184
1204
  def self.created_before(time)
1185
1205
  where("created_at < ?", time)
1186
1206
  end
@@ -1190,7 +1210,36 @@ end
1190
1210
  Using a class method is the preferred way to accept arguments for scopes. These methods will still be accessible on the association objects:
1191
1211
 
1192
1212
  ```ruby
1193
- category.posts.created_before(time)
1213
+ category.articles.created_before(time)
1214
+ ```
1215
+
1216
+ ### Applying a default scope
1217
+
1218
+ If we wish for a scope to be applied across all queries to the model we can use the
1219
+ `default_scope` method within the model itself.
1220
+
1221
+ ```ruby
1222
+ class Client < ActiveRecord::Base
1223
+ default_scope { where("removed_at IS NULL") }
1224
+ end
1225
+ ```
1226
+
1227
+ When queries are executed on this model, the SQL query will now look something like
1228
+ this:
1229
+
1230
+ ```sql
1231
+ SELECT * FROM clients WHERE removed_at IS NULL
1232
+ ```
1233
+
1234
+ If you need to do more complex things with a default scope, you can alternatively
1235
+ define it as a class method:
1236
+
1237
+ ```ruby
1238
+ class Client < ActiveRecord::Base
1239
+ def self.default_scope
1240
+ # Should return an ActiveRecord::Relation.
1241
+ end
1242
+ end
1194
1243
  ```
1195
1244
 
1196
1245
  ### Merging of scopes
@@ -1203,80 +1252,49 @@ class User < ActiveRecord::Base
1203
1252
  scope :inactive, -> { where state: 'inactive' }
1204
1253
  end
1205
1254
 
1206
- ```ruby
1207
1255
  User.active.inactive
1208
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive'
1256
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive'
1209
1257
  ```
1210
1258
 
1211
1259
  We can mix and match `scope` and `where` conditions and the final sql
1212
- will have all conditions joined with `AND` .
1260
+ will have all conditions joined with `AND`.
1213
1261
 
1214
1262
  ```ruby
1215
1263
  User.active.where(state: 'finished')
1216
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'finished'
1264
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'finished'
1217
1265
  ```
1218
1266
 
1219
1267
  If we do want the `last where clause` to win then `Relation#merge` can
1220
- be used .
1268
+ be used.
1221
1269
 
1222
1270
  ```ruby
1223
1271
  User.active.merge(User.inactive)
1224
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
1272
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
1225
1273
  ```
1226
1274
 
1227
- One important caveat is that `default_scope` will be overridden by
1275
+ One important caveat is that `default_scope` will be prepended in
1228
1276
  `scope` and `where` conditions.
1229
1277
 
1230
1278
  ```ruby
1231
1279
  class User < ActiveRecord::Base
1232
- default_scope { where state: 'pending' }
1280
+ default_scope { where state: 'pending' }
1233
1281
  scope :active, -> { where state: 'active' }
1234
1282
  scope :inactive, -> { where state: 'inactive' }
1235
1283
  end
1236
1284
 
1237
1285
  User.all
1238
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
1286
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
1239
1287
 
1240
1288
  User.active
1241
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
1289
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'active'
1242
1290
 
1243
1291
  User.where(state: 'inactive')
1244
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
1292
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'inactive'
1245
1293
  ```
1246
1294
 
1247
- As you can see above the `default_scope` is being overridden by both
1295
+ As you can see above the `default_scope` is being merged in both
1248
1296
  `scope` and `where` conditions.
1249
1297
 
1250
-
1251
- ### Applying a default scope
1252
-
1253
- If we wish for a scope to be applied across all queries to the model we can use the
1254
- `default_scope` method within the model itself.
1255
-
1256
- ```ruby
1257
- class Client < ActiveRecord::Base
1258
- default_scope { where("removed_at IS NULL") }
1259
- end
1260
- ```
1261
-
1262
- When queries are executed on this model, the SQL query will now look something like
1263
- this:
1264
-
1265
- ```sql
1266
- SELECT * FROM clients WHERE removed_at IS NULL
1267
- ```
1268
-
1269
- If you need to do more complex things with a default scope, you can alternatively
1270
- define it as a class method:
1271
-
1272
- ```ruby
1273
- class Client < ActiveRecord::Base
1274
- def self.default_scope
1275
- # Should return an ActiveRecord::Relation.
1276
- end
1277
- end
1278
- ```
1279
-
1280
1298
  ### Removing All Scoping
1281
1299
 
1282
1300
  If we wish to remove scoping for any reason we can use the `unscoped` method. This is
@@ -1284,7 +1302,7 @@ especially useful if a `default_scope` is specified in the model and should not
1284
1302
  applied for this particular query.
1285
1303
 
1286
1304
  ```ruby
1287
- Client.unscoped.all
1305
+ Client.unscoped.load
1288
1306
  ```
1289
1307
 
1290
1308
  This method removes all scoping and will do a normal query on the table.
@@ -1301,11 +1319,6 @@ Client.unscoped {
1301
1319
  Dynamic Finders
1302
1320
  ---------------
1303
1321
 
1304
- NOTE: Dynamic finders have been deprecated in Rails 4.0 and will be
1305
- removed in Rails 4.1. The best practice is to use Active Record scopes
1306
- instead. You can find the deprecation gem at
1307
- https://github.com/rails/activerecord-deprecated_finders
1308
-
1309
1322
  For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called `first_name` on your `Client` model for example, you get `find_by_first_name` for free from Active Record. If you have a `locked` field on the `Client` model, you also get `find_by_locked` and methods.
1310
1323
 
1311
1324
  You can specify an exclamation point (`!`) on the end of the dynamic finders to get them to raise an `ActiveRecord::RecordNotFound` error if they do not return any records, like `Client.find_by_name!("Ryan")`
@@ -1315,6 +1328,11 @@ If you want to find both by name and locked, you can chain these finders togethe
1315
1328
  Find or Build a New Object
1316
1329
  --------------------------
1317
1330
 
1331
+ NOTE: Some dynamic finders have been deprecated in Rails 4.0 and will be
1332
+ removed in Rails 4.1. The best practice is to use Active Record scopes
1333
+ instead. You can find the deprecation gem at
1334
+ https://github.com/rails/activerecord-deprecated_finders
1335
+
1318
1336
  It's common that you need to find a record or create it if it doesn't exist. You can do that with the `find_or_create_by` and `find_or_create_by!` methods.
1319
1337
 
1320
1338
  ### `find_or_create_by`
@@ -1341,7 +1359,7 @@ COMMIT
1341
1359
 
1342
1360
  The new record might not be saved to the database; that depends on whether validations passed or not (just like `create`).
1343
1361
 
1344
- Suppose we want to set the 'locked' attribute to true if we're
1362
+ Suppose we want to set the 'locked' attribute to `false` if we're
1345
1363
  creating a new record, but we don't want to include it in the query. So
1346
1364
  we want to find the client named "Andy", or if that client doesn't
1347
1365
  exist, create a client named "Andy" which is not locked.
@@ -1418,7 +1436,12 @@ If you'd like to use your own SQL to find records in a table you can use `find_b
1418
1436
  ```ruby
1419
1437
  Client.find_by_sql("SELECT * FROM clients
1420
1438
  INNER JOIN orders ON clients.id = orders.client_id
1421
- ORDER clients.created_at desc")
1439
+ ORDER BY clients.created_at desc")
1440
+ # => [
1441
+ #<Client id: 1, first_name: "Lucas" >,
1442
+ #<Client id: 2, first_name: "Jan" >,
1443
+ # ...
1444
+ ]
1422
1445
  ```
1423
1446
 
1424
1447
  `find_by_sql` provides you with a simple way of making custom calls to the database and retrieving instantiated objects.
@@ -1428,12 +1451,16 @@ Client.find_by_sql("SELECT * FROM clients
1428
1451
  `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.
1429
1452
 
1430
1453
  ```ruby
1431
- Client.connection.select_all("SELECT * FROM clients WHERE id = '1'")
1454
+ Client.connection.select_all("SELECT first_name, created_at FROM clients WHERE id = '1'")
1455
+ # => [
1456
+ {"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
1457
+ {"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
1458
+ ]
1432
1459
  ```
1433
1460
 
1434
1461
  ### `pluck`
1435
1462
 
1436
- `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.
1463
+ `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.
1437
1464
 
1438
1465
  ```ruby
1439
1466
  Client.where(active: true).pluck(:id)
@@ -1449,7 +1476,7 @@ Client.pluck(:id, :name)
1449
1476
  # => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
1450
1477
  ```
1451
1478
 
1452
- `pluck` makes it possible to replace code like
1479
+ `pluck` makes it possible to replace code like:
1453
1480
 
1454
1481
  ```ruby
1455
1482
  Client.select(:id).map { |c| c.id }
@@ -1459,7 +1486,7 @@ Client.select(:id).map(&:id)
1459
1486
  Client.select(:id, :name).map { |c| [c.id, c.name] }
1460
1487
  ```
1461
1488
 
1462
- with
1489
+ with:
1463
1490
 
1464
1491
  ```ruby
1465
1492
  Client.pluck(:id)
@@ -1467,6 +1494,37 @@ Client.pluck(:id)
1467
1494
  Client.pluck(:id, :name)
1468
1495
  ```
1469
1496
 
1497
+ Unlike `select`, `pluck` directly converts a database result into a Ruby `Array`,
1498
+ without constructing `ActiveRecord` objects. This can mean better performance for
1499
+ a large or often-running query. However, any model method overrides will
1500
+ not be available. For example:
1501
+
1502
+ ```ruby
1503
+ class Client < ActiveRecord::Base
1504
+ def name
1505
+ "I am #{super}"
1506
+ end
1507
+ end
1508
+
1509
+ Client.select(:name).map &:name
1510
+ # => ["I am David", "I am Jeremy", "I am Jose"]
1511
+
1512
+ Client.pluck(:name)
1513
+ # => ["David", "Jeremy", "Jose"]
1514
+ ```
1515
+
1516
+ Furthermore, unlike `select` and other `Relation` scopes, `pluck` triggers an immediate
1517
+ query, and thus cannot be chained with any further scopes, although it can work with
1518
+ scopes already constructed earlier:
1519
+
1520
+ ```ruby
1521
+ Client.pluck(:name).limit(1)
1522
+ # => NoMethodError: undefined method `limit' for #<Array:0x007ff34d3ad6d8>
1523
+
1524
+ Client.limit(1).pluck(:name)
1525
+ # => ["David"]
1526
+ ```
1527
+
1470
1528
  ### `ids`
1471
1529
 
1472
1530
  `ids` can be used to pluck all the IDs for the relation using the table's primary key.
@@ -1488,18 +1546,21 @@ Person.ids
1488
1546
  Existence of Objects
1489
1547
  --------------------
1490
1548
 
1491
- If you simply want to check for the existence of the object there's a method called `exists?`. This method will query the database using the same query as `find`, but instead of returning an object or collection of objects it will return either `true` or `false`.
1549
+ If you simply want to check for the existence of the object there's a method called `exists?`.
1550
+ This method will query the database using the same query as `find`, but instead of returning an
1551
+ object or collection of objects it will return either `true` or `false`.
1492
1552
 
1493
1553
  ```ruby
1494
1554
  Client.exists?(1)
1495
1555
  ```
1496
1556
 
1497
- The `exists?` method also takes multiple ids, but the catch is that it will return true if any one of those records exists.
1557
+ The `exists?` method also takes multiple values, but the catch is that it will return `true` if any
1558
+ one of those records exists.
1498
1559
 
1499
1560
  ```ruby
1500
- Client.exists?(1,2,3)
1561
+ Client.exists?(id: [1,2,3])
1501
1562
  # or
1502
- Client.exists?([1,2,3])
1563
+ Client.exists?(name: ['John', 'Sergei'])
1503
1564
  ```
1504
1565
 
1505
1566
  It's even possible to use `exists?` without any arguments on a model or a relation.
@@ -1508,7 +1569,8 @@ It's even possible to use `exists?` without any arguments on a model or a relati
1508
1569
  Client.where(first_name: 'Ryan').exists?
1509
1570
  ```
1510
1571
 
1511
- The above returns `true` if there is at least one client with the `first_name` 'Ryan' and `false` otherwise.
1572
+ The above returns `true` if there is at least one client with the `first_name` 'Ryan' and `false`
1573
+ otherwise.
1512
1574
 
1513
1575
  ```ruby
1514
1576
  Client.exists?
@@ -1520,20 +1582,20 @@ You can also use `any?` and `many?` to check for existence on a model or relatio
1520
1582
 
1521
1583
  ```ruby
1522
1584
  # via a model
1523
- Post.any?
1524
- Post.many?
1585
+ Article.any?
1586
+ Article.many?
1525
1587
 
1526
1588
  # via a named scope
1527
- Post.recent.any?
1528
- Post.recent.many?
1589
+ Article.recent.any?
1590
+ Article.recent.many?
1529
1591
 
1530
1592
  # via a relation
1531
- Post.where(published: true).any?
1532
- Post.where(published: true).many?
1593
+ Article.where(published: true).any?
1594
+ Article.where(published: true).many?
1533
1595
 
1534
1596
  # via an association
1535
- Post.first.categories.any?
1536
- Post.first.categories.many?
1597
+ Article.first.categories.any?
1598
+ Article.first.categories.many?
1537
1599
  ```
1538
1600
 
1539
1601
  Calculations
@@ -1558,7 +1620,7 @@ Client.where(first_name: 'Ryan').count
1558
1620
  You can also use various finder methods on a relation for performing complex calculations:
1559
1621
 
1560
1622
  ```ruby
1561
- Client.includes("orders").where(first_name: 'Ryan', orders: {status: 'received'}).count
1623
+ Client.includes("orders").where(first_name: 'Ryan', orders: { status: 'received' }).count
1562
1624
  ```
1563
1625
 
1564
1626
  Which will execute:
@@ -1623,19 +1685,26 @@ Running EXPLAIN
1623
1685
  You can run EXPLAIN on the queries triggered by relations. For example,
1624
1686
 
1625
1687
  ```ruby
1626
- User.where(id: 1).joins(:posts).explain
1688
+ User.where(id: 1).joins(:articles).explain
1627
1689
  ```
1628
1690
 
1629
1691
  may yield
1630
1692
 
1631
1693
  ```
1632
- EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `posts` ON `posts`.`user_id` = `users`.`id` WHERE `users`.`id` = 1
1633
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
1634
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1635
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
1636
- | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
1637
- | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
1638
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
1694
+ EXPLAIN for: SELECT `users`.* FROM `users` INNER JOIN `articles` ON `articles`.`user_id` = `users`.`id` WHERE `users`.`id` = 1
1695
+ +----+-------------+----------+-------+---------------+
1696
+ | id | select_type | table | type | possible_keys |
1697
+ +----+-------------+----------+-------+---------------+
1698
+ | 1 | SIMPLE | users | const | PRIMARY |
1699
+ | 1 | SIMPLE | articles | ALL | NULL |
1700
+ +----+-------------+----------+-------+---------------+
1701
+ +---------+---------+-------+------+-------------+
1702
+ | key | key_len | ref | rows | Extra |
1703
+ +---------+---------+-------+------+-------------+
1704
+ | PRIMARY | 4 | const | 1 | |
1705
+ | NULL | NULL | NULL | 1 | Using where |
1706
+ +---------+---------+-------+------+-------------+
1707
+
1639
1708
  2 rows in set (0.00 sec)
1640
1709
  ```
1641
1710
 
@@ -1645,15 +1714,15 @@ Active Record performs a pretty printing that emulates the one of the database
1645
1714
  shells. So, the same query running with the PostgreSQL adapter would yield instead
1646
1715
 
1647
1716
  ```
1648
- EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" WHERE "users"."id" = 1
1717
+ EXPLAIN for: SELECT "users".* FROM "users" INNER JOIN "articles" ON "articles"."user_id" = "users"."id" WHERE "users"."id" = 1
1649
1718
  QUERY PLAN
1650
1719
  ------------------------------------------------------------------------------
1651
1720
  Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0)
1652
- Join Filter: (posts.user_id = users.id)
1721
+ Join Filter: (articles.user_id = users.id)
1653
1722
  -> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=4)
1654
1723
  Index Cond: (id = 1)
1655
- -> Seq Scan on posts (cost=0.00..28.88 rows=8 width=4)
1656
- Filter: (posts.user_id = 1)
1724
+ -> Seq Scan on articles (cost=0.00..28.88 rows=8 width=4)
1725
+ Filter: (articles.user_id = 1)
1657
1726
  (6 rows)
1658
1727
  ```
1659
1728
 
@@ -1662,26 +1731,39 @@ may need the results of previous ones. Because of that, `explain` actually
1662
1731
  executes the query, and then asks for the query plans. For example,
1663
1732
 
1664
1733
  ```ruby
1665
- User.where(id: 1).includes(:posts).explain
1734
+ User.where(id: 1).includes(:articles).explain
1666
1735
  ```
1667
1736
 
1668
1737
  yields
1669
1738
 
1670
1739
  ```
1671
1740
  EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
1672
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1673
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1674
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1675
- | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
1676
- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
1741
+ +----+-------------+-------+-------+---------------+
1742
+ | id | select_type | table | type | possible_keys |
1743
+ +----+-------------+-------+-------+---------------+
1744
+ | 1 | SIMPLE | users | const | PRIMARY |
1745
+ +----+-------------+-------+-------+---------------+
1746
+ +---------+---------+-------+------+-------+
1747
+ | key | key_len | ref | rows | Extra |
1748
+ +---------+---------+-------+------+-------+
1749
+ | PRIMARY | 4 | const | 1 | |
1750
+ +---------+---------+-------+------+-------+
1751
+
1677
1752
  1 row in set (0.00 sec)
1678
1753
 
1679
- EXPLAIN for: SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` IN (1)
1680
- +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1681
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1682
- +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1683
- | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
1684
- +----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1754
+ EXPLAIN for: SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` IN (1)
1755
+ +----+-------------+----------+------+---------------+
1756
+ | id | select_type | table | type | possible_keys |
1757
+ +----+-------------+----------+------+---------------+
1758
+ | 1 | SIMPLE | articles | ALL | NULL |
1759
+ +----+-------------+----------+------+---------------+
1760
+ +------+---------+------+------+-------------+
1761
+ | key | key_len | ref | rows | Extra |
1762
+ +------+---------+------+------+-------------+
1763
+ | NULL | NULL | NULL | 1 | Using where |
1764
+ +------+---------+------+------+-------------+
1765
+
1766
+
1685
1767
  1 row in set (0.00 sec)
1686
1768
  ```
1687
1769