rails 4.1.6 → 4.2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +12 -10
- data/guides/CHANGELOG.md +64 -17
- data/guides/Rakefile +21 -6
- data/guides/assets/images/getting_started/article_with_comments.png +0 -0
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_gem.rb +3 -3
- data/guides/bug_report_templates/action_controller_master.rb +3 -2
- data/guides/bug_report_templates/active_record_gem.rb +1 -1
- data/guides/bug_report_templates/generic_gem.rb +15 -0
- data/guides/bug_report_templates/generic_master.rb +26 -0
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +27 -21
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides.rb +2 -2
- data/guides/source/2_2_release_notes.md +1 -1
- data/guides/source/2_3_release_notes.md +4 -4
- data/guides/source/3_0_release_notes.md +8 -8
- data/guides/source/3_1_release_notes.md +6 -3
- data/guides/source/3_2_release_notes.md +6 -3
- data/guides/source/4_0_release_notes.md +6 -3
- data/guides/source/4_1_release_notes.md +9 -10
- data/guides/source/4_2_release_notes.md +877 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +6 -8
- data/guides/source/action_controller_overview.md +25 -8
- data/guides/source/action_mailer_basics.md +97 -29
- data/guides/source/action_view_overview.md +142 -191
- data/guides/source/active_job_basics.md +339 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +25 -24
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +264 -268
- data/guides/source/active_record_validations.md +23 -13
- data/guides/source/active_support_core_extensions.md +115 -123
- data/guides/source/active_support_instrumentation.md +10 -18
- data/guides/source/api_documentation_guidelines.md +63 -17
- data/guides/source/asset_pipeline.md +259 -120
- data/guides/source/association_basics.md +96 -80
- data/guides/source/autoloading_and_reloading_constants.md +1311 -0
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +161 -33
- data/guides/source/contributing_to_ruby_on_rails.md +198 -114
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +440 -286
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +217 -196
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +359 -219
- data/guides/source/i18n.md +110 -66
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +109 -62
- data/guides/source/layout.html.erb +5 -11
- data/guides/source/layouts_and_rendering.md +26 -26
- data/guides/source/maintenance_policy.md +6 -3
- data/guides/source/nested_model_forms.md +7 -4
- data/guides/source/plugins.md +27 -27
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +8 -5
- data/guides/source/routing.md +113 -73
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +40 -34
- data/guides/source/testing.md +199 -119
- data/guides/source/upgrading_ruby_on_rails.md +289 -31
- data/guides/source/working_with_javascript_in_rails.md +19 -17
- data/guides/w3c_validator.rb +2 -0
- metadata +42 -95
- data/guides/code/getting_started/Gemfile +0 -40
- data/guides/code/getting_started/Gemfile.lock +0 -125
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -60
- data/guides/code/getting_started/public/422.html +0 -60
- data/guides/code/getting_started/public/500.html +0 -59
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -361,6 +361,8 @@ class Product < ActiveRecord::Base
|
|
361
361
|
end
|
362
362
|
```
|
363
363
|
|
364
|
+
Alternatively, you can require that the specified attribute does _not_ match the regular expression by using the `:without` option.
|
365
|
+
|
364
366
|
The default error message is _"is invalid"_.
|
365
367
|
|
366
368
|
### `inclusion`
|
@@ -425,7 +427,7 @@ class Essay < ActiveRecord::Base
|
|
425
427
|
validates :content, length: {
|
426
428
|
minimum: 300,
|
427
429
|
maximum: 400,
|
428
|
-
tokenizer: lambda { |str| str.
|
430
|
+
tokenizer: lambda { |str| str.split(/\s+/) },
|
429
431
|
too_short: "must have at least %{count} words",
|
430
432
|
too_long: "must have at most %{count} words"
|
431
433
|
}
|
@@ -524,9 +526,16 @@ If you validate the presence of an object associated via a `has_one` or
|
|
524
526
|
`marked_for_destruction?`.
|
525
527
|
|
526
528
|
Since `false.blank?` is true, if you want to validate the presence of a boolean
|
527
|
-
field you should use
|
529
|
+
field you should use one of the following validations:
|
530
|
+
|
531
|
+
```ruby
|
532
|
+
validates :boolean_field_name, presence: true
|
533
|
+
validates :boolean_field_name, inclusion: { in: [true, false] }
|
534
|
+
validates :boolean_field_name, exclusion: { in: [nil] }
|
535
|
+
```
|
528
536
|
|
529
|
-
|
537
|
+
By using one of these validations, you will ensure the value will NOT be `nil`
|
538
|
+
which would result in a `NULL` value in most cases.
|
530
539
|
|
531
540
|
### `absence`
|
532
541
|
|
@@ -698,7 +707,7 @@ we don't want names and surnames to begin with lower case.
|
|
698
707
|
```ruby
|
699
708
|
class Person < ActiveRecord::Base
|
700
709
|
validates_each :name, :surname do |record, attr, value|
|
701
|
-
record.errors.add(attr, 'must start with upper case') if value =~ /\A[
|
710
|
+
record.errors.add(attr, 'must start with upper case') if value =~ /\A[[:lower:]]/
|
702
711
|
end
|
703
712
|
end
|
704
713
|
```
|
@@ -910,8 +919,8 @@ end
|
|
910
919
|
The easiest way to add custom validators for validating individual attributes
|
911
920
|
is with the convenient `ActiveModel::EachValidator`. In this case, the custom
|
912
921
|
validator class must implement a `validate_each` method which takes three
|
913
|
-
arguments: record, attribute and value
|
914
|
-
attribute to be validated and the value of the attribute in the passed
|
922
|
+
arguments: record, attribute, and value. These correspond to the instance, the
|
923
|
+
attribute to be validated, and the value of the attribute in the passed
|
915
924
|
instance.
|
916
925
|
|
917
926
|
```ruby
|
@@ -935,8 +944,9 @@ own custom validators.
|
|
935
944
|
|
936
945
|
You can also create methods that verify the state of your models and add
|
937
946
|
messages to the `errors` collection when they are invalid. You must then
|
938
|
-
register these methods by using the `validate`
|
939
|
-
|
947
|
+
register these methods by using the `validate`
|
948
|
+
([API](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validate))
|
949
|
+
class method, passing in the symbols for the validation methods' names.
|
940
950
|
|
941
951
|
You can pass more than one symbol for each class method and the respective
|
942
952
|
validations will be run in the same order as they were registered.
|
@@ -1129,15 +1139,15 @@ generating a scaffold, Rails will put some ERB into the `_form.html.erb` that
|
|
1129
1139
|
it generates that displays the full list of errors on that model.
|
1130
1140
|
|
1131
1141
|
Assuming we have a model that's been saved in an instance variable named
|
1132
|
-
`@
|
1142
|
+
`@article`, it looks like this:
|
1133
1143
|
|
1134
1144
|
```ruby
|
1135
|
-
<% if @
|
1145
|
+
<% if @article.errors.any? %>
|
1136
1146
|
<div id="error_explanation">
|
1137
|
-
<h2><%= pluralize(@
|
1147
|
+
<h2><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h2>
|
1138
1148
|
|
1139
1149
|
<ul>
|
1140
|
-
<% @
|
1150
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1141
1151
|
<li><%= msg %></li>
|
1142
1152
|
<% end %>
|
1143
1153
|
</ul>
|
@@ -1151,7 +1161,7 @@ the entry.
|
|
1151
1161
|
|
1152
1162
|
```
|
1153
1163
|
<div class="field_with_errors">
|
1154
|
-
<input id="
|
1164
|
+
<input id="article_title" name="article[title]" size="30" type="text" value="">
|
1155
1165
|
</div>
|
1156
1166
|
```
|
1157
1167
|
|
@@ -157,12 +157,12 @@ Active Support provides `duplicable?` to programmatically query an object about
|
|
157
157
|
|
158
158
|
```ruby
|
159
159
|
"foo".duplicable? # => true
|
160
|
-
"".duplicable?
|
160
|
+
"".duplicable? # => true
|
161
161
|
0.0.duplicable? # => false
|
162
|
-
false.duplicable?
|
162
|
+
false.duplicable? # => false
|
163
163
|
```
|
164
164
|
|
165
|
-
By definition all objects are `duplicable?` except `nil`, `false`, `true`, symbols, numbers, class, and
|
165
|
+
By definition all objects are `duplicable?` except `nil`, `false`, `true`, symbols, numbers, class, module, and method objects.
|
166
166
|
|
167
167
|
WARNING: Any class can disallow duplication by removing `dup` and `clone` or raising exceptions from them. Thus only `rescue` can tell whether a given arbitrary object is duplicable. `duplicable?` depends on the hard-coded list above, but it is much faster than `rescue`. Use it only if you know the hard-coded list is enough in your use case.
|
168
168
|
|
@@ -572,12 +572,12 @@ NOTE: Defined in `active_support/core_ext/module/aliasing.rb`.
|
|
572
572
|
|
573
573
|
#### `alias_attribute`
|
574
574
|
|
575
|
-
Model attributes have a reader, a writer, and a predicate. You can alias a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (
|
575
|
+
Model attributes have a reader, a writer, and a predicate. You can alias a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (one mnemonic is that they go in the same order as if you did an assignment):
|
576
576
|
|
577
577
|
```ruby
|
578
578
|
class User < ActiveRecord::Base
|
579
|
-
#
|
580
|
-
#
|
579
|
+
# You can refer to the email column as "login".
|
580
|
+
# This can be meaningful for authentication code.
|
581
581
|
alias_attribute :login, :email
|
582
582
|
end
|
583
583
|
```
|
@@ -761,7 +761,7 @@ Arguments may be bare constant names:
|
|
761
761
|
Math.qualified_const_get("E") # => 2.718281828459045
|
762
762
|
```
|
763
763
|
|
764
|
-
These methods are analogous to their
|
764
|
+
These methods are analogous to their built-in counterparts. In particular,
|
765
765
|
`qualified_constant_defined?` accepts an optional second argument to be
|
766
766
|
able to say whether you want the predicate to look in the ancestors.
|
767
767
|
This flag is taken into account for each constant in the expression while
|
@@ -792,7 +792,7 @@ N.qualified_const_defined?("C::X") # => true
|
|
792
792
|
As the last example implies, the second argument defaults to true,
|
793
793
|
as in `const_defined?`.
|
794
794
|
|
795
|
-
For coherence with the
|
795
|
+
For coherence with the built-in methods only relative paths are accepted.
|
796
796
|
Absolute qualified constant names like `::Math::PI` raise `NameError`.
|
797
797
|
|
798
798
|
NOTE: Defined in `active_support/core_ext/module/qualified_const.rb`.
|
@@ -964,20 +964,7 @@ NOTE: Defined in `active_support/core_ext/module/delegation.rb`
|
|
964
964
|
|
965
965
|
There are cases where you need to define a method with `define_method`, but don't know whether a method with that name already exists. If it does, a warning is issued if they are enabled. No big deal, but not clean either.
|
966
966
|
|
967
|
-
The method `redefine_method` prevents such a potential warning, removing the existing method before if needed.
|
968
|
-
|
969
|
-
```ruby
|
970
|
-
redefine_method("#{reflection.name}=") do |new_value|
|
971
|
-
association = association_instance_get(reflection.name)
|
972
|
-
|
973
|
-
if association.nil? || association.target != new_value
|
974
|
-
association = association_proxy_class.new(self, reflection)
|
975
|
-
end
|
976
|
-
|
977
|
-
association.replace(new_value)
|
978
|
-
association_instance_set(reflection.name, new_value.nil? ? nil : association)
|
979
|
-
end
|
980
|
-
```
|
967
|
+
The method `redefine_method` prevents such a potential warning, removing the existing method before if needed.
|
981
968
|
|
982
969
|
NOTE: Defined in `active_support/core_ext/module/remove_method.rb`
|
983
970
|
|
@@ -1024,7 +1011,7 @@ self.default_params = {
|
|
1024
1011
|
}.freeze
|
1025
1012
|
```
|
1026
1013
|
|
1027
|
-
They can be
|
1014
|
+
They can also be accessed and overridden at the instance level.
|
1028
1015
|
|
1029
1016
|
```ruby
|
1030
1017
|
A.x = 1
|
@@ -1178,9 +1165,9 @@ Inserting data into HTML templates needs extra care. For example, you can't just
|
|
1178
1165
|
|
1179
1166
|
#### Safe Strings
|
1180
1167
|
|
1181
|
-
Active Support has the concept of
|
1168
|
+
Active Support has the concept of _(html) safe_ strings. A safe string is one that is marked as being insertable into HTML as is. It is trusted, no matter whether it has been escaped or not.
|
1182
1169
|
|
1183
|
-
Strings are considered to be
|
1170
|
+
Strings are considered to be _unsafe_ by default:
|
1184
1171
|
|
1185
1172
|
```ruby
|
1186
1173
|
"".html_safe? # => false
|
@@ -1281,7 +1268,7 @@ The method `squish` strips leading and trailing whitespace, and substitutes runs
|
|
1281
1268
|
|
1282
1269
|
There's also the destructive version `String#squish!`.
|
1283
1270
|
|
1284
|
-
Note that it handles both ASCII and Unicode whitespace
|
1271
|
+
Note that it handles both ASCII and Unicode whitespace.
|
1285
1272
|
|
1286
1273
|
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1287
1274
|
|
@@ -1323,6 +1310,38 @@ In above examples "dear" gets cut first, but then `:separator` prevents it.
|
|
1323
1310
|
|
1324
1311
|
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1325
1312
|
|
1313
|
+
### `truncate_words`
|
1314
|
+
|
1315
|
+
The method `truncate_words` returns a copy of its receiver truncated after a given number of words:
|
1316
|
+
|
1317
|
+
```ruby
|
1318
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(4)
|
1319
|
+
# => "Oh dear! Oh dear!..."
|
1320
|
+
```
|
1321
|
+
|
1322
|
+
Ellipsis can be customized with the `:omission` option:
|
1323
|
+
|
1324
|
+
```ruby
|
1325
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(4, omission: '…')
|
1326
|
+
# => "Oh dear! Oh dear!…"
|
1327
|
+
```
|
1328
|
+
|
1329
|
+
Pass a `:separator` to truncate the string at a natural break:
|
1330
|
+
|
1331
|
+
```ruby
|
1332
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(3, separator: '!')
|
1333
|
+
# => "Oh dear! Oh dear! I shall be late..."
|
1334
|
+
```
|
1335
|
+
|
1336
|
+
The option `:separator` can be a regexp:
|
1337
|
+
|
1338
|
+
```ruby
|
1339
|
+
"Oh dear! Oh dear! I shall be late!".truncate_words(4, separator: /\s/)
|
1340
|
+
# => "Oh dear! Oh dear!..."
|
1341
|
+
```
|
1342
|
+
|
1343
|
+
NOTE: Defined in `active_support/core_ext/string/filters.rb`.
|
1344
|
+
|
1326
1345
|
### `inquiry`
|
1327
1346
|
|
1328
1347
|
The `inquiry` method converts a string into a `StringInquirer` object making equality checks prettier.
|
@@ -1644,6 +1663,9 @@ Given a string with a qualified constant name, `demodulize` returns the very con
|
|
1644
1663
|
"Product".demodulize # => "Product"
|
1645
1664
|
"Backoffice::UsersController".demodulize # => "UsersController"
|
1646
1665
|
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
|
1666
|
+
"::Inflections".demodulize # => "Inflections"
|
1667
|
+
"".demodulize # => ""
|
1668
|
+
|
1647
1669
|
```
|
1648
1670
|
|
1649
1671
|
Active Record for example uses this method to compute the name of a counter cache column:
|
@@ -1738,7 +1760,7 @@ NOTE: Defined in `active_support/core_ext/string/inflections.rb`.
|
|
1738
1760
|
The method `constantize` resolves the constant reference expression in its receiver:
|
1739
1761
|
|
1740
1762
|
```ruby
|
1741
|
-
"
|
1763
|
+
"Integer".constantize # => Integer
|
1742
1764
|
|
1743
1765
|
module M
|
1744
1766
|
X = 1
|
@@ -1778,34 +1800,47 @@ NOTE: Defined in `active_support/core_ext/string/inflections.rb`.
|
|
1778
1800
|
|
1779
1801
|
#### `humanize`
|
1780
1802
|
|
1781
|
-
The method `humanize`
|
1803
|
+
The method `humanize` tweaks an attribute name for display to end users.
|
1804
|
+
|
1805
|
+
Specifically performs these transformations:
|
1806
|
+
|
1807
|
+
* Applies human inflection rules to the argument.
|
1808
|
+
* Deletes leading underscores, if any.
|
1809
|
+
* Removes a "_id" suffix if present.
|
1810
|
+
* Replaces underscores with spaces, if any.
|
1811
|
+
* Downcases all words except acronyms.
|
1812
|
+
* Capitalizes the first word.
|
1813
|
+
|
1814
|
+
The capitalization of the first word can be turned off by setting the
|
1815
|
+
+:capitalize+ option to false (default is true).
|
1782
1816
|
|
1783
1817
|
```ruby
|
1784
|
-
"name".humanize
|
1785
|
-
"author_id".humanize
|
1786
|
-
"
|
1818
|
+
"name".humanize # => "Name"
|
1819
|
+
"author_id".humanize # => "Author"
|
1820
|
+
"author_id".humanize(capitalize: false) # => "author"
|
1821
|
+
"comments_count".humanize # => "Comments count"
|
1822
|
+
"_id".humanize # => "Id"
|
1787
1823
|
```
|
1788
1824
|
|
1789
|
-
|
1825
|
+
If "SSL" was defined to be an acronym:
|
1790
1826
|
|
1791
1827
|
```ruby
|
1792
|
-
|
1828
|
+
'ssl_error'.humanize # => "SSL error"
|
1793
1829
|
```
|
1794
1830
|
|
1795
|
-
The helper method `full_messages` uses `humanize` as a fallback to include
|
1831
|
+
The helper method `full_messages` uses `humanize` as a fallback to include
|
1832
|
+
attribute names:
|
1796
1833
|
|
1797
1834
|
```ruby
|
1798
1835
|
def full_messages
|
1799
|
-
|
1800
|
-
|
1801
|
-
each do |attribute, messages|
|
1802
|
-
...
|
1803
|
-
attr_name = attribute.to_s.gsub('.', '_').humanize
|
1804
|
-
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
|
1805
|
-
...
|
1806
|
-
end
|
1836
|
+
map { |attribute, message| full_message(attribute, message) }
|
1837
|
+
end
|
1807
1838
|
|
1808
|
-
|
1839
|
+
def full_message
|
1840
|
+
...
|
1841
|
+
attr_name = attribute.to_s.tr('.', '_').humanize
|
1842
|
+
attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
|
1843
|
+
...
|
1809
1844
|
end
|
1810
1845
|
```
|
1811
1846
|
|
@@ -1915,24 +1950,6 @@ as well as adding or subtracting their results from a Time object. For example:
|
|
1915
1950
|
(4.months + 5.years).from_now
|
1916
1951
|
```
|
1917
1952
|
|
1918
|
-
While these methods provide precise calculation when used as in the examples above, care
|
1919
|
-
should be taken to note that this is not true if the result of `months', `years', etc is
|
1920
|
-
converted before use:
|
1921
|
-
|
1922
|
-
```ruby
|
1923
|
-
# equivalent to 30.days.to_i.from_now
|
1924
|
-
1.month.to_i.from_now
|
1925
|
-
|
1926
|
-
# equivalent to 365.25.days.to_f.from_now
|
1927
|
-
1.year.to_f.from_now
|
1928
|
-
```
|
1929
|
-
|
1930
|
-
In such cases, Ruby's core [Date](http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html) and
|
1931
|
-
[Time](http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html) should be used for precision
|
1932
|
-
date and time arithmetic.
|
1933
|
-
|
1934
|
-
NOTE: Defined in `active_support/core_ext/numeric/time.rb`.
|
1935
|
-
|
1936
1953
|
### Formatting
|
1937
1954
|
|
1938
1955
|
Enables the formatting of numbers in a variety of ways.
|
@@ -2595,8 +2612,7 @@ To do so, the method loops over the pairs and builds nodes that depend on the _v
|
|
2595
2612
|
```ruby
|
2596
2613
|
XML_TYPE_NAMES = {
|
2597
2614
|
"Symbol" => "symbol",
|
2598
|
-
"
|
2599
|
-
"Bignum" => "integer",
|
2615
|
+
"Integer" => "integer",
|
2600
2616
|
"BigDecimal" => "decimal",
|
2601
2617
|
"Float" => "float",
|
2602
2618
|
"TrueClass" => "boolean",
|
@@ -2719,11 +2735,14 @@ The method `transform_keys` accepts a block and returns a hash that has applied
|
|
2719
2735
|
# => {"" => nil, "A" => :a, "1" => 1}
|
2720
2736
|
```
|
2721
2737
|
|
2722
|
-
|
2738
|
+
In case of key collision, one of the values will be chosen. The chosen value may not always be the same given the same hash:
|
2723
2739
|
|
2724
2740
|
```ruby
|
2725
2741
|
{"a" => 1, a: 2}.transform_keys { |key| key.to_s.upcase }
|
2726
|
-
#
|
2742
|
+
# The result could either be
|
2743
|
+
# => {"A"=>2}
|
2744
|
+
# or
|
2745
|
+
# => {"A"=>1}
|
2727
2746
|
```
|
2728
2747
|
|
2729
2748
|
This method may be useful for example to build specialized conversions. For instance `stringify_keys` and `symbolize_keys` use `transform_keys` to perform their key conversions:
|
@@ -2758,11 +2777,14 @@ The method `stringify_keys` returns a hash that has a stringified version of the
|
|
2758
2777
|
# => {"" => nil, "a" => :a, "1" => 1}
|
2759
2778
|
```
|
2760
2779
|
|
2761
|
-
|
2780
|
+
In case of key collision, one of the values will be chosen. The chosen value may not always be the same given the same hash:
|
2762
2781
|
|
2763
2782
|
```ruby
|
2764
2783
|
{"a" => 1, a: 2}.stringify_keys
|
2765
|
-
#
|
2784
|
+
# The result could either be
|
2785
|
+
# => {"a"=>2}
|
2786
|
+
# or
|
2787
|
+
# => {"a"=>1}
|
2766
2788
|
```
|
2767
2789
|
|
2768
2790
|
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionView::Helpers::FormHelper` defines:
|
@@ -2799,11 +2821,14 @@ The method `symbolize_keys` returns a hash that has a symbolized version of the
|
|
2799
2821
|
|
2800
2822
|
WARNING. Note in the previous example only one key was symbolized.
|
2801
2823
|
|
2802
|
-
|
2824
|
+
In case of key collision, one of the values will be chosen. The chosen value may not always be the same given the same hash:
|
2803
2825
|
|
2804
2826
|
```ruby
|
2805
2827
|
{"a" => 1, a: 2}.symbolize_keys
|
2806
|
-
#
|
2828
|
+
# The result could either be
|
2829
|
+
# => {:a=>2}
|
2830
|
+
# or
|
2831
|
+
# => {:a=>1}
|
2807
2832
|
```
|
2808
2833
|
|
2809
2834
|
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionController::UrlRewriter` defines
|
@@ -2848,6 +2873,20 @@ Active Record does not accept unknown options when building associations, for ex
|
|
2848
2873
|
|
2849
2874
|
NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
|
2850
2875
|
|
2876
|
+
### Working with Values
|
2877
|
+
|
2878
|
+
#### `transform_values` && `transform_values!`
|
2879
|
+
|
2880
|
+
The method `transform_values` accepts a block and returns a hash that has applied the block operations to each of the values in the receiver.
|
2881
|
+
|
2882
|
+
```ruby
|
2883
|
+
{ nil => nil, 1 => 1, :x => :a }.transform_values { |value| value.to_s.upcase }
|
2884
|
+
# => {nil=>"", 1=>"1", :x=>"A"}
|
2885
|
+
```
|
2886
|
+
There's also the bang variant `transform_values!` that applies the block operations to values in the very receiver.
|
2887
|
+
|
2888
|
+
NOTE: Defined in `active_support/core_text/hash/transform_values.rb`.
|
2889
|
+
|
2851
2890
|
### Slicing
|
2852
2891
|
|
2853
2892
|
Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes:
|
@@ -2911,7 +2950,7 @@ NOTE: Defined in `active_support/core_ext/hash/indifferent_access.rb`.
|
|
2911
2950
|
|
2912
2951
|
### Compacting
|
2913
2952
|
|
2914
|
-
The methods `compact` and `compact!` return a Hash without items with `nil` value.
|
2953
|
+
The methods `compact` and `compact!` return a Hash without items with `nil` value.
|
2915
2954
|
|
2916
2955
|
```ruby
|
2917
2956
|
{a: 1, b: 2, c: nil}.compact # => {a: 1, b: 2}
|
@@ -3003,53 +3042,6 @@ The method `Range#overlaps?` says whether any two given ranges have non-void int
|
|
3003
3042
|
|
3004
3043
|
NOTE: Defined in `active_support/core_ext/range/overlaps.rb`.
|
3005
3044
|
|
3006
|
-
Extensions to `Proc`
|
3007
|
-
--------------------
|
3008
|
-
|
3009
|
-
### `bind`
|
3010
|
-
|
3011
|
-
As you surely know Ruby has an `UnboundMethod` class whose instances are methods that belong to the limbo of methods without a self. The method `Module#instance_method` returns an unbound method for example:
|
3012
|
-
|
3013
|
-
```ruby
|
3014
|
-
Hash.instance_method(:delete) # => #<UnboundMethod: Hash#delete>
|
3015
|
-
```
|
3016
|
-
|
3017
|
-
An unbound method is not callable as is, you need to bind it first to an object with `bind`:
|
3018
|
-
|
3019
|
-
```ruby
|
3020
|
-
clear = Hash.instance_method(:clear)
|
3021
|
-
clear.bind({a: 1}).call # => {}
|
3022
|
-
```
|
3023
|
-
|
3024
|
-
Active Support defines `Proc#bind` with an analogous purpose:
|
3025
|
-
|
3026
|
-
```ruby
|
3027
|
-
Proc.new { size }.bind([]).call # => 0
|
3028
|
-
```
|
3029
|
-
|
3030
|
-
As you see that's callable and bound to the argument, the return value is indeed a `Method`.
|
3031
|
-
|
3032
|
-
NOTE: To do so `Proc#bind` actually creates a method under the hood. If you ever see a method with a weird name like `__bind_1256598120_237302` in a stack trace you know now where it comes from.
|
3033
|
-
|
3034
|
-
Action Pack uses this trick in `rescue_from` for example, which accepts the name of a method and also a proc as callbacks for a given rescued exception. It has to call them in either case, so a bound method is returned by `handler_for_rescue`, thus simplifying the code in the caller:
|
3035
|
-
|
3036
|
-
```ruby
|
3037
|
-
def handler_for_rescue(exception)
|
3038
|
-
_, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
|
3039
|
-
...
|
3040
|
-
end
|
3041
|
-
|
3042
|
-
case rescuer
|
3043
|
-
when Symbol
|
3044
|
-
method(rescuer)
|
3045
|
-
when Proc
|
3046
|
-
rescuer.bind(self)
|
3047
|
-
end
|
3048
|
-
end
|
3049
|
-
```
|
3050
|
-
|
3051
|
-
NOTE: Defined in `active_support/core_ext/proc.rb`.
|
3052
|
-
|
3053
3045
|
Extensions to `Date`
|
3054
3046
|
--------------------
|
3055
3047
|
|
@@ -3658,9 +3650,9 @@ t.advance(seconds: 1)
|
|
3658
3650
|
|
3659
3651
|
#### `Time.current`
|
3660
3652
|
|
3661
|
-
Active Support defines `Time.current` to be today in the current time zone. That's like `Time.now`, except that it honors the user time zone, if defined. It also defines
|
3653
|
+
Active Support defines `Time.current` to be today in the current time zone. That's like `Time.now`, except that it honors the user time zone, if defined. It also defines the instance predicates `past?`, `today?`, and `future?`, all of them relative to `Time.current`.
|
3662
3654
|
|
3663
|
-
When making Time comparisons using methods which honor the user time zone, make sure to use `Time.current`
|
3655
|
+
When making Time comparisons using methods which honor the user time zone, make sure to use `Time.current` instead of `Time.now`. There are cases where the user time zone might be in the future compared to the system time zone, which `Time.now` uses by default. This means `Time.now.to_date` may equal `Date.yesterday`.
|
3664
3656
|
|
3665
3657
|
#### `all_day`, `all_week`, `all_month`, `all_quarter` and `all_year`
|
3666
3658
|
|
@@ -3824,7 +3816,7 @@ The name may be given as a symbol or string. A symbol is tested against the bare
|
|
3824
3816
|
|
3825
3817
|
TIP: A symbol can represent a fully-qualified constant name as in `:"ActiveRecord::Base"`, so the behavior for symbols is defined for convenience, not because it has to be that way technically.
|
3826
3818
|
|
3827
|
-
For example, when an action of `
|
3819
|
+
For example, when an action of `ArticlesController` is called Rails tries optimistically to use `ArticlesHelper`. It is OK that the helper module does not exist, so if an exception for that constant name is raised it should be silenced. But it could be the case that `articles_helper.rb` raises a `NameError` due to an actual unknown constant. That should be reraised. The method `missing_name?` provides a way to distinguish both cases:
|
3828
3820
|
|
3829
3821
|
```ruby
|
3830
3822
|
def default_helper_module!
|
@@ -3838,7 +3830,7 @@ rescue NameError => e
|
|
3838
3830
|
end
|
3839
3831
|
```
|
3840
3832
|
|
3841
|
-
NOTE: Defined in `
|
3833
|
+
NOTE: Defined in `active_support/core_ext/name_error.rb`.
|
3842
3834
|
|
3843
3835
|
Extensions to `LoadError`
|
3844
3836
|
-------------------------
|
@@ -3847,7 +3839,7 @@ Active Support adds `is_missing?` to `LoadError`, and also assigns that class to
|
|
3847
3839
|
|
3848
3840
|
Given a path name `is_missing?` tests whether the exception was raised due to that particular file (except perhaps for the ".rb" extension).
|
3849
3841
|
|
3850
|
-
For example, when an action of `
|
3842
|
+
For example, when an action of `ArticlesController` is called Rails tries to load `articles_helper.rb`, but that file may not exist. That's fine, the helper module is not mandatory so Rails silences a load error. But it could be the case that the helper module does exist and in turn requires another library that is missing. In that case Rails must reraise the exception. The method `is_missing?` provides a way to distinguish both cases:
|
3851
3843
|
|
3852
3844
|
```ruby
|
3853
3845
|
def default_helper_module!
|
@@ -3861,4 +3853,4 @@ rescue NameError => e
|
|
3861
3853
|
end
|
3862
3854
|
```
|
3863
3855
|
|
3864
|
-
NOTE: Defined in `
|
3856
|
+
NOTE: Defined in `active_support/core_ext/load_error.rb`.
|
@@ -17,7 +17,7 @@ After reading this guide, you will know:
|
|
17
17
|
Introduction to instrumentation
|
18
18
|
-------------------------------
|
19
19
|
|
20
|
-
The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the Rails framework, as described below in
|
20
|
+
The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the Rails framework, as described below in (TODO: link to section detailing each hook point). With this API, developers can choose to be notified when certain events occur inside their application or another piece of Ruby code.
|
21
21
|
|
22
22
|
For example, there is a hook provided within Active Record that is called every time Active Record uses an SQL query on a database. This hook could be **subscribed** to, and used to track the number of queries during a certain action. There's another hook around the processing of an action of a controller. This could be used, for instance, to track how long a specific action has taken.
|
23
23
|
|
@@ -135,7 +135,9 @@ Action Controller
|
|
135
135
|
| `:format` | html/js/json/xml etc |
|
136
136
|
| `:method` | HTTP request verb |
|
137
137
|
| `:path` | Request path |
|
138
|
+
| `:status` | HTTP status code |
|
138
139
|
| `:view_runtime` | Amount spent in view in ms |
|
140
|
+
| `:db_runtime` | Amount spent executing database queries in ms |
|
139
141
|
|
140
142
|
```ruby
|
141
143
|
{
|
@@ -223,11 +225,11 @@ Active Record
|
|
223
225
|
|
224
226
|
### sql.active_record
|
225
227
|
|
226
|
-
| Key
|
227
|
-
|
|
228
|
-
| `:sql`
|
229
|
-
| `:name`
|
230
|
-
| `:
|
228
|
+
| Key | Value |
|
229
|
+
| ---------------- | --------------------- |
|
230
|
+
| `:sql` | SQL statement |
|
231
|
+
| `:name` | Name of the operation |
|
232
|
+
| `:connection_id` | `self.object_id` |
|
231
233
|
|
232
234
|
INFO. The adapters will add their own data as well.
|
233
235
|
|
@@ -303,17 +305,6 @@ Action Mailer
|
|
303
305
|
}
|
304
306
|
```
|
305
307
|
|
306
|
-
ActiveResource
|
307
|
-
--------------
|
308
|
-
|
309
|
-
### request.active_resource
|
310
|
-
|
311
|
-
| Key | Value |
|
312
|
-
| -------------- | -------------------- |
|
313
|
-
| `:method` | HTTP method |
|
314
|
-
| `:request_uri` | Complete URI |
|
315
|
-
| `:result` | HTTP response object |
|
316
|
-
|
317
308
|
Active Support
|
318
309
|
--------------
|
319
310
|
|
@@ -364,7 +355,7 @@ INFO. Options passed to fetch will be merged with the payload.
|
|
364
355
|
| ------ | --------------------- |
|
365
356
|
| `:key` | Key used in the store |
|
366
357
|
|
367
|
-
INFO. Cache stores
|
358
|
+
INFO. Cache stores may add their own keys
|
368
359
|
|
369
360
|
```ruby
|
370
361
|
{
|
@@ -457,6 +448,7 @@ Most times you only care about the data itself. Here is a shortcut to just get t
|
|
457
448
|
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
|
458
449
|
data = args.extract_options!
|
459
450
|
data # { extra: :information }
|
451
|
+
end
|
460
452
|
```
|
461
453
|
|
462
454
|
You may also subscribe to events matching a regular expression. This enables you to subscribe to
|