rails 4.0.13 → 4.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -17
  3. data/guides/CHANGELOG.md +68 -34
  4. data/guides/assets/images/edge_badge.png +0 -0
  5. data/guides/assets/images/feature_tile.gif +0 -0
  6. data/guides/assets/images/footer_tile.gif +0 -0
  7. data/guides/assets/images/fxn.png +0 -0
  8. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  9. data/guides/assets/images/getting_started/challenge.png +0 -0
  10. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  11. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  12. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  13. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  14. data/guides/assets/images/getting_started/new_article.png +0 -0
  15. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  16. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  17. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  18. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  19. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  20. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  21. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  22. data/guides/assets/images/header_tile.gif +0 -0
  23. data/guides/assets/images/icons/README +1 -1
  24. data/guides/assets/images/icons/callouts/11.png +0 -0
  25. data/guides/assets/images/icons/callouts/12.png +0 -0
  26. data/guides/assets/images/icons/callouts/13.png +0 -0
  27. data/guides/assets/images/icons/callouts/15.png +0 -0
  28. data/guides/assets/images/icons/caution.png +0 -0
  29. data/guides/assets/images/icons/example.png +0 -0
  30. data/guides/assets/images/radar.png +0 -0
  31. data/guides/assets/images/rails4_features.png +0 -0
  32. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  33. data/guides/assets/images/vijaydev.jpg +0 -0
  34. data/guides/assets/javascripts/guides.js +30 -34
  35. data/guides/assets/stylesheets/main.css +2 -1
  36. data/guides/assets/stylesheets/print.css +1 -1
  37. data/guides/bug_report_templates/action_controller_gem.rb +9 -4
  38. data/guides/bug_report_templates/action_controller_master.rb +4 -2
  39. data/guides/bug_report_templates/active_record_gem.rb +5 -2
  40. data/guides/bug_report_templates/active_record_master.rb +2 -1
  41. data/guides/bug_report_templates/generic_gem.rb +15 -0
  42. data/guides/bug_report_templates/generic_master.rb +26 -0
  43. data/guides/code/getting_started/Gemfile +21 -24
  44. data/guides/code/getting_started/Gemfile.lock +78 -73
  45. data/guides/code/getting_started/Rakefile +1 -1
  46. data/guides/code/getting_started/app/assets/javascripts/application.js +1 -2
  47. data/guides/code/getting_started/app/views/layouts/application.html.erb +2 -2
  48. data/guides/code/getting_started/config/environment.rb +1 -1
  49. data/guides/code/getting_started/config/environments/development.rb +2 -2
  50. data/guides/code/getting_started/config/environments/production.rb +3 -3
  51. data/guides/code/getting_started/config/environments/test.rb +2 -2
  52. data/guides/code/getting_started/config/initializers/secret_token.rb +1 -1
  53. data/guides/code/getting_started/config/initializers/session_store.rb +1 -1
  54. data/guides/code/getting_started/config/routes.rb +1 -1
  55. data/guides/code/getting_started/config.ru +1 -1
  56. data/guides/code/getting_started/public/404.html +2 -0
  57. data/guides/code/getting_started/public/422.html +2 -0
  58. data/guides/code/getting_started/public/500.html +2 -0
  59. data/guides/code/getting_started/test/test_helper.rb +0 -3
  60. data/guides/rails_guides/helpers.rb +3 -1
  61. data/guides/source/2_2_release_notes.md +2 -2
  62. data/guides/source/2_3_release_notes.md +8 -8
  63. data/guides/source/3_0_release_notes.md +2 -3
  64. data/guides/source/3_1_release_notes.md +2 -2
  65. data/guides/source/3_2_release_notes.md +12 -12
  66. data/guides/source/4_0_release_notes.md +79 -46
  67. data/guides/source/4_1_release_notes.md +731 -0
  68. data/guides/source/_welcome.html.erb +5 -2
  69. data/guides/source/action_controller_overview.md +189 -40
  70. data/guides/source/action_mailer_basics.md +27 -27
  71. data/guides/source/action_view_overview.md +131 -20
  72. data/guides/source/active_model_basics.md +6 -6
  73. data/guides/source/active_record_basics.md +15 -15
  74. data/guides/source/active_record_callbacks.md +18 -16
  75. data/guides/source/active_record_querying.md +93 -51
  76. data/guides/source/active_record_validations.md +26 -24
  77. data/guides/source/active_support_core_extensions.md +72 -118
  78. data/guides/source/active_support_instrumentation.md +13 -4
  79. data/guides/source/api_documentation_guidelines.md +104 -6
  80. data/guides/source/asset_pipeline.md +573 -244
  81. data/guides/source/association_basics.md +94 -22
  82. data/guides/source/caching_with_rails.md +15 -6
  83. data/guides/source/command_line.md +55 -46
  84. data/guides/source/configuring.md +248 -52
  85. data/guides/source/contributing_to_ruby_on_rails.md +18 -17
  86. data/guides/source/credits.html.erb +2 -2
  87. data/guides/source/debugging_rails_applications.md +39 -8
  88. data/guides/source/development_dependencies_install.md +91 -8
  89. data/guides/source/documents.yaml +4 -0
  90. data/guides/source/engines.md +678 -232
  91. data/guides/source/form_helpers.md +53 -35
  92. data/guides/source/generators.md +19 -15
  93. data/guides/source/getting_started.md +758 -497
  94. data/guides/source/i18n.md +64 -28
  95. data/guides/source/index.html.erb +1 -1
  96. data/guides/source/initialization.md +155 -58
  97. data/guides/source/kindle/toc.html.erb +1 -1
  98. data/guides/source/layout.html.erb +2 -2
  99. data/guides/source/layouts_and_rendering.md +59 -26
  100. data/guides/source/maintenance_policy.md +3 -3
  101. data/guides/source/migrations.md +101 -62
  102. data/guides/source/nested_model_forms.md +3 -3
  103. data/guides/source/plugins.md +34 -31
  104. data/guides/source/rails_application_templates.md +27 -8
  105. data/guides/source/rails_on_rack.md +41 -58
  106. data/guides/source/routing.md +115 -104
  107. data/guides/source/ruby_on_rails_guides_guidelines.md +2 -2
  108. data/guides/source/security.md +81 -36
  109. data/guides/source/testing.md +56 -79
  110. data/guides/source/upgrading_ruby_on_rails.md +531 -21
  111. data/guides/source/working_with_javascript_in_rails.md +19 -11
  112. metadata +51 -23
  113. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  114. data/guides/assets/images/getting_started/new_post.png +0 -0
  115. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  116. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  117. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  118. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  119. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  120. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  121. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  122. data/guides/source/kindle/KINDLE.md +0 -26
@@ -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,7 +91,7 @@ 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
96
  #### Using a Primary Key
97
97
 
@@ -473,7 +473,7 @@ In the case of a belongs_to relationship, an association key can be used to spec
473
473
 
474
474
  ```ruby
475
475
  Post.where(author: author)
476
- Author.joins(:posts).where(posts: {author: author})
476
+ Author.joins(:posts).where(posts: { author: author })
477
477
  ```
478
478
 
479
479
  NOTE: The values cannot be symbols. For example, you cannot do `Client.where(status: :active)`.
@@ -685,9 +685,9 @@ This will return single order objects for each day, but only those that are orde
685
685
  Overriding Conditions
686
686
  ---------------------
687
687
 
688
- ### `except`
688
+ ### `unscope`
689
689
 
690
- You can specify certain conditions to be excepted by using the `except` method. For example:
690
+ You can specify certain conditions to be removed using the `unscope` method. For example:
691
691
 
692
692
  ```ruby
693
693
  Post.where('id > 10').limit(20).order('id asc').except(:order)
@@ -697,27 +697,25 @@ The SQL that would be executed:
697
697
 
698
698
  ```sql
699
699
  SELECT * FROM posts WHERE id > 10 LIMIT 20
700
- ```
701
700
 
702
- ### `unscope`
701
+ # Original query without `unscope`
702
+ SELECT * FROM posts WHERE id > 10 ORDER BY id asc LIMIT 20
703
703
 
704
- The `except` method does not work when the relation is merged. For example:
705
-
706
- ```ruby
707
- Post.comments.except(:order)
708
704
  ```
709
705
 
710
- 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:
706
+ You can additionally unscope specific where clauses. For example:
711
707
 
712
708
  ```ruby
713
- Post.order('id DESC').limit(20).unscope(:order) = Post.limit(20)
714
- Post.order('id DESC').limit(20).unscope(:order, :limit) = Post.all
709
+ Post.where(id: 10, trashed: false).unscope(where: :id)
710
+ # SELECT "posts".* FROM "posts" WHERE trashed = 0
715
711
  ```
716
712
 
717
- You can additionally unscope specific where clauses. For example:
713
+ A relation which has used `unscope` will affect any relation it is
714
+ merged in to:
718
715
 
719
716
  ```ruby
720
- Post.where(:id => 10).limit(1).unscope(where: :id, :limit).order('id DESC') = Post.order('id DESC')
717
+ Post.order('id asc').merge(Post.unscope(:order))
718
+ # SELECT "posts".* FROM "posts"
721
719
  ```
722
720
 
723
721
  ### `only`
@@ -732,6 +730,10 @@ The SQL that would be executed:
732
730
 
733
731
  ```sql
734
732
  SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
733
+
734
+ # Original query without `only`
735
+ SELECT "posts".* FROM "posts" WHERE (id > 10) ORDER BY id desc LIMIT 20
736
+
735
737
  ```
736
738
 
737
739
  ### `reorder`
@@ -742,7 +744,7 @@ The `reorder` method overrides the default scope order. For example:
742
744
  class Post < ActiveRecord::Base
743
745
  ..
744
746
  ..
745
- has_many :comments, order: 'posted_at DESC'
747
+ has_many :comments, -> { order('posted_at DESC') }
746
748
  end
747
749
 
748
750
  Post.find(10).comments.reorder('name')
@@ -751,13 +753,15 @@ Post.find(10).comments.reorder('name')
751
753
  The SQL that would be executed:
752
754
 
753
755
  ```sql
754
- SELECT * FROM posts WHERE id = 10 ORDER BY name
756
+ SELECT * FROM posts WHERE id = 10
757
+ SELECT * FROM comments WHERE post_id = 10 ORDER BY name
755
758
  ```
756
759
 
757
760
  In case the `reorder` clause is not used, the SQL executed would be:
758
761
 
759
762
  ```sql
760
- SELECT * FROM posts WHERE id = 10 ORDER BY posted_at DESC
763
+ SELECT * FROM posts WHERE id = 10
764
+ SELECT * FROM comments WHERE post_id = 10 ORDER BY posted_at DESC
761
765
  ```
762
766
 
763
767
  ### `reverse_order`
@@ -788,6 +792,32 @@ SELECT * FROM clients WHERE orders_count > 10 ORDER BY clients.id DESC
788
792
 
789
793
  This method accepts **no** arguments.
790
794
 
795
+ ### `rewhere`
796
+
797
+ The `rewhere` method overrides an existing, named where condition. For example:
798
+
799
+ ```ruby
800
+ Post.where(trashed: true).rewhere(trashed: false)
801
+ ```
802
+
803
+ The SQL that would be executed:
804
+
805
+ ```sql
806
+ SELECT * FROM posts WHERE `trashed` = 0
807
+ ```
808
+
809
+ In case the `rewhere` clause is not used,
810
+
811
+ ```ruby
812
+ Post.where(trashed: true).where(trashed: false)
813
+ ```
814
+
815
+ the SQL executed would be:
816
+
817
+ ```sql
818
+ SELECT * FROM posts WHERE `trashed` = 1 AND `trashed` = 0
819
+ ```
820
+
791
821
  Null Relation
792
822
  -------------
793
823
 
@@ -826,8 +856,6 @@ client.save
826
856
 
827
857
  As `client` is explicitly set to be a readonly object, the above code will raise an `ActiveRecord::ReadOnlyRecord` exception when calling `client.save` with an updated value of _visits_.
828
858
 
829
- NOTE: using `joins` without an explicit `select` will return readonly records.
830
-
831
859
  Locking Records for Update
832
860
  --------------------------
833
861
 
@@ -931,15 +959,13 @@ This will result in the following SQL:
931
959
  SELECT clients.* FROM clients LEFT OUTER JOIN addresses ON addresses.client_id = clients.id
932
960
  ```
933
961
 
934
- NOTE: using `joins` might return readonly records. See [readonly](active_record_querying.html#readonly-objects) for more details.
935
-
936
962
  ### Using Array/Hash of Named Associations
937
963
 
938
964
  WARNING: This method only works with `INNER JOIN`.
939
965
 
940
966
  Active Record lets you use the names of the [associations](association_basics.html) defined on the model as a shortcut for specifying `JOIN` clause for those associations when using the `joins` method.
941
967
 
942
- For example, consider the following `Category`, `Post`, `Comments` and `Guest` models:
968
+ For example, consider the following `Category`, `Post`, `Comment`, `Guest` and `Tag` models:
943
969
 
944
970
  ```ruby
945
971
  class Category < ActiveRecord::Base
@@ -1018,7 +1044,7 @@ Or, in English: "return all posts that have a comment made by a guest."
1018
1044
  #### Joining Nested Associations (Multiple Level)
1019
1045
 
1020
1046
  ```ruby
1021
- Category.joins(posts: [{comments: :guest}, :tags])
1047
+ Category.joins(posts: [{ comments: :guest }, :tags])
1022
1048
  ```
1023
1049
 
1024
1050
  This produces:
@@ -1044,7 +1070,7 @@ An alternative and cleaner syntax is to nest the hash conditions:
1044
1070
 
1045
1071
  ```ruby
1046
1072
  time_range = (Time.now.midnight - 1.day)..Time.now.midnight
1047
- Client.joins(:orders).where(orders: {created_at: time_range})
1073
+ Client.joins(:orders).where(orders: { created_at: time_range })
1048
1074
  ```
1049
1075
 
1050
1076
  This will find all clients who have orders that were created yesterday, again using a `BETWEEN` SQL expression.
@@ -1105,7 +1131,7 @@ This loads all the posts and the associated category and comments for each post.
1105
1131
  #### Nested Associations Hash
1106
1132
 
1107
1133
  ```ruby
1108
- Category.includes(posts: [{comments: :guest}, :tags]).find(1)
1134
+ Category.includes(posts: [{ comments: :guest }, :tags]).find(1)
1109
1135
  ```
1110
1136
 
1111
1137
  This will find the category with id 1 and eager load all of the associated posts, the associated posts' tags and comments, and every comment's guest association.
@@ -1117,18 +1143,30 @@ Even though Active Record lets you specify conditions on the eager loaded associ
1117
1143
  However if you must do this, you may use `where` as you would normally.
1118
1144
 
1119
1145
  ```ruby
1120
- Post.includes(:comments).where("comments.visible" => true)
1146
+ Post.includes(:comments).where(comments: { visible: true })
1121
1147
  ```
1122
1148
 
1123
- This would generate a query which contains a `LEFT OUTER JOIN` whereas the `joins` method would generate one using the `INNER JOIN` function instead.
1149
+ This would generate a query which contains a `LEFT OUTER JOIN` whereas the
1150
+ `joins` method would generate one using the `INNER JOIN` function instead.
1124
1151
 
1125
1152
  ```ruby
1126
1153
  SELECT "posts"."id" AS t0_r0, ... "comments"."updated_at" AS t1_r5 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE (comments.visible = 1)
1127
1154
  ```
1128
1155
 
1129
- If there was no `where` condition, this would generate the normal set of two queries.
1156
+ If there was no `where` condition, this would generate the normal set of two
1157
+ queries.
1158
+
1159
+ NOTE: Using `where` like this will only work when you pass it a Hash. For
1160
+ SQL-fragments you need use `references` to force joined tables:
1161
+
1162
+ ```ruby
1163
+ Post.includes(:comments).where("comments.visible = true").references(:comments)
1164
+ ```
1165
+
1166
+ If, in the case of this `includes` query, there were no comments for any posts,
1167
+ all the posts would still be loaded. By using `joins` (an INNER JOIN), the join
1168
+ conditions **must** match, otherwise no records will be returned.
1130
1169
 
1131
- 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.
1132
1170
 
1133
1171
  Scopes
1134
1172
  ------
@@ -1185,7 +1223,7 @@ class Post < ActiveRecord::Base
1185
1223
  end
1186
1224
  ```
1187
1225
 
1188
- This may then be called using this:
1226
+ Call the scope as if it were a class method:
1189
1227
 
1190
1228
  ```ruby
1191
1229
  Post.created_before(Time.zone.now)
@@ -1218,46 +1256,46 @@ class User < ActiveRecord::Base
1218
1256
  end
1219
1257
 
1220
1258
  User.active.inactive
1221
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive'
1259
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive'
1222
1260
  ```
1223
1261
 
1224
1262
  We can mix and match `scope` and `where` conditions and the final sql
1225
- will have all conditions joined with `AND` .
1263
+ will have all conditions joined with `AND`.
1226
1264
 
1227
1265
  ```ruby
1228
1266
  User.active.where(state: 'finished')
1229
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'finished'
1267
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'finished'
1230
1268
  ```
1231
1269
 
1232
1270
  If we do want the `last where clause` to win then `Relation#merge` can
1233
- be used .
1271
+ be used.
1234
1272
 
1235
1273
  ```ruby
1236
1274
  User.active.merge(User.inactive)
1237
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
1275
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
1238
1276
  ```
1239
1277
 
1240
- One important caveat is that `default_scope` will be overridden by
1278
+ One important caveat is that `default_scope` will be prepended in
1241
1279
  `scope` and `where` conditions.
1242
1280
 
1243
1281
  ```ruby
1244
1282
  class User < ActiveRecord::Base
1245
- default_scope { where state: 'pending' }
1283
+ default_scope { where state: 'pending' }
1246
1284
  scope :active, -> { where state: 'active' }
1247
1285
  scope :inactive, -> { where state: 'inactive' }
1248
1286
  end
1249
1287
 
1250
1288
  User.all
1251
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
1289
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
1252
1290
 
1253
1291
  User.active
1254
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
1292
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'active'
1255
1293
 
1256
1294
  User.where(state: 'inactive')
1257
- # => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
1295
+ # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'inactive'
1258
1296
  ```
1259
1297
 
1260
- As you can see above the `default_scope` is being overridden by both
1298
+ As you can see above the `default_scope` is being merged in both
1261
1299
  `scope` and `where` conditions.
1262
1300
 
1263
1301
 
@@ -1354,7 +1392,7 @@ COMMIT
1354
1392
 
1355
1393
  The new record might not be saved to the database; that depends on whether validations passed or not (just like `create`).
1356
1394
 
1357
- Suppose we want to set the 'locked' attribute to true if we're
1395
+ Suppose we want to set the 'locked' attribute to `false` if we're
1358
1396
  creating a new record, but we don't want to include it in the query. So
1359
1397
  we want to find the client named "Andy", or if that client doesn't
1360
1398
  exist, create a client named "Andy" which is not locked.
@@ -1431,7 +1469,7 @@ If you'd like to use your own SQL to find records in a table you can use `find_b
1431
1469
  ```ruby
1432
1470
  Client.find_by_sql("SELECT * FROM clients
1433
1471
  INNER JOIN orders ON clients.id = orders.client_id
1434
- ORDER clients.created_at desc")
1472
+ ORDER BY clients.created_at desc")
1435
1473
  ```
1436
1474
 
1437
1475
  `find_by_sql` provides you with a simple way of making custom calls to the database and retrieving instantiated objects.
@@ -1532,18 +1570,21 @@ Person.ids
1532
1570
  Existence of Objects
1533
1571
  --------------------
1534
1572
 
1535
- 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`.
1573
+ If you simply want to check for the existence of the object there's a method called `exists?`.
1574
+ This method will query the database using the same query as `find`, but instead of returning an
1575
+ object or collection of objects it will return either `true` or `false`.
1536
1576
 
1537
1577
  ```ruby
1538
1578
  Client.exists?(1)
1539
1579
  ```
1540
1580
 
1541
- The `exists?` method also takes multiple ids, but the catch is that it will return true if any one of those records exists.
1581
+ The `exists?` method also takes multiple values, but the catch is that it will return `true` if any
1582
+ one of those records exists.
1542
1583
 
1543
1584
  ```ruby
1544
- Client.exists?(1,2,3)
1585
+ Client.exists?(id: [1,2,3])
1545
1586
  # or
1546
- Client.exists?([1,2,3])
1587
+ Client.exists?(name: ['John', 'Sergei'])
1547
1588
  ```
1548
1589
 
1549
1590
  It's even possible to use `exists?` without any arguments on a model or a relation.
@@ -1552,7 +1593,8 @@ It's even possible to use `exists?` without any arguments on a model or a relati
1552
1593
  Client.where(first_name: 'Ryan').exists?
1553
1594
  ```
1554
1595
 
1555
- The above returns `true` if there is at least one client with the `first_name` 'Ryan' and `false` otherwise.
1596
+ The above returns `true` if there is at least one client with the `first_name` 'Ryan' and `false`
1597
+ otherwise.
1556
1598
 
1557
1599
  ```ruby
1558
1600
  Client.exists?
@@ -1602,7 +1644,7 @@ Client.where(first_name: 'Ryan').count
1602
1644
  You can also use various finder methods on a relation for performing complex calculations:
1603
1645
 
1604
1646
  ```ruby
1605
- Client.includes("orders").where(first_name: 'Ryan', orders: {status: 'received'}).count
1647
+ Client.includes("orders").where(first_name: 'Ryan', orders: { status: 'received' }).count
1606
1648
  ```
1607
1649
 
1608
1650
  Which will execute:
@@ -85,7 +85,7 @@ end
85
85
  We can see how it works by looking at some `rails console` output:
86
86
 
87
87
  ```ruby
88
- $ rails console
88
+ $ bin/rails console
89
89
  >> p = Person.new(name: "John Doe")
90
90
  => #<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil>
91
91
  >> p.new_record?
@@ -162,8 +162,8 @@ Person.create(name: nil).valid? # => false
162
162
  ```
163
163
 
164
164
  After Active Record has performed validations, any errors found can be accessed
165
- through the `errors` instance method, which returns a collection of errors. By
166
- definition, an object is valid if this collection is empty after running
165
+ through the `errors.messages` instance method, which returns a collection of errors.
166
+ By definition, an object is valid if this collection is empty after running
167
167
  validations.
168
168
 
169
169
  Note that an object instantiated with `new` will not report errors even if it's
@@ -175,28 +175,28 @@ class Person < ActiveRecord::Base
175
175
  end
176
176
 
177
177
  >> p = Person.new
178
- #=> #<Person id: nil, name: nil>
179
- >> p.errors
180
- #=> {}
178
+ # => #<Person id: nil, name: nil>
179
+ >> p.errors.messages
180
+ # => {}
181
181
 
182
182
  >> p.valid?
183
- #=> false
184
- >> p.errors
185
- #=> {name:["can't be blank"]}
183
+ # => false
184
+ >> p.errors.messages
185
+ # => {name:["can't be blank"]}
186
186
 
187
187
  >> p = Person.create
188
- #=> #<Person id: nil, name: nil>
189
- >> p.errors
190
- #=> {name:["can't be blank"]}
188
+ # => #<Person id: nil, name: nil>
189
+ >> p.errors.messages
190
+ # => {name:["can't be blank"]}
191
191
 
192
192
  >> p.save
193
- #=> false
193
+ # => false
194
194
 
195
195
  >> p.save!
196
- #=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
196
+ # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
197
197
 
198
198
  >> Person.create!
199
- #=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
199
+ # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
200
200
  ```
201
201
 
202
202
  `invalid?` is simply the inverse of `valid?`. It triggers your validations,
@@ -357,7 +357,7 @@ given regular expression, which is specified using the `:with` option.
357
357
  ```ruby
358
358
  class Product < ActiveRecord::Base
359
359
  validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
360
- message: "Only letters allowed" }
360
+ message: "only allows letters" }
361
361
  end
362
362
  ```
363
363
 
@@ -526,7 +526,7 @@ If you validate the presence of an object associated via a `has_one` or
526
526
  Since `false.blank?` is true, if you want to validate the presence of a boolean
527
527
  field you should use `validates :field_name, inclusion: { in: [true, false] }`.
528
528
 
529
- The default error message is _"can't be empty"_.
529
+ The default error message is _"can't be blank"_.
530
530
 
531
531
  ### `absence`
532
532
 
@@ -575,7 +575,9 @@ This helper validates that the attribute's value is unique right before the
575
575
  object gets saved. It does not create a uniqueness constraint in the database,
576
576
  so it may happen that two different database connections create two records
577
577
  with the same value for a column that you intend to be unique. To avoid that,
578
- you must create a unique index in your database.
578
+ you must create a unique index on both columns in your database. See
579
+ [the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html)
580
+ for more details about multiple column indexes.
579
581
 
580
582
  ```ruby
581
583
  class Account < ActiveRecord::Base
@@ -682,7 +684,7 @@ class GoodnessValidator
682
684
  end
683
685
  end
684
686
 
685
- #
687
+ # ...
686
688
  end
687
689
  ```
688
690
 
@@ -734,8 +736,8 @@ class Topic < ActiveRecord::Base
734
736
  validates :title, length: { is: 5 }, allow_blank: true
735
737
  end
736
738
 
737
- Topic.create("title" => "").valid? # => true
738
- Topic.create("title" => nil).valid? # => true
739
+ Topic.create(title: "").valid? # => true
740
+ Topic.create(title: nil).valid? # => true
739
741
  ```
740
742
 
741
743
  ### `:message`
@@ -781,7 +783,7 @@ end
781
783
  Person.new.valid? # => ActiveModel::StrictValidationFailed: Name can't be blank
782
784
  ```
783
785
 
784
- There is also an ability to pass custom exception to `:strict` option
786
+ There is also an ability to pass custom exception to `:strict` option.
785
787
 
786
788
  ```ruby
787
789
  class Person < ActiveRecord::Base
@@ -990,12 +992,12 @@ end
990
992
 
991
993
  person = Person.new
992
994
  person.valid? # => false
993
- person.errors
995
+ person.errors.messages
994
996
  # => {:name=>["can't be blank", "is too short (minimum is 3 characters)"]}
995
997
 
996
998
  person = Person.new(name: "John Doe")
997
999
  person.valid? # => true
998
- person.errors # => []
1000
+ person.errors.messages # => {}
999
1001
  ```
1000
1002
 
1001
1003
  ### `errors[]`