rails 4.1.16 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -10
- data/guides/CHANGELOG.md +15 -100
- data/guides/Rakefile +5 -3
- data/guides/assets/javascripts/guides.js +6 -0
- data/guides/assets/stylesheets/main.css +4 -1
- data/guides/bug_report_templates/action_controller_master.rb +1 -0
- data/guides/rails_guides/helpers.rb +1 -1
- data/guides/rails_guides/levenshtein.rb +29 -21
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/rails_guides/markdown.rb +11 -7
- data/guides/rails_guides.rb +2 -2
- data/guides/source/2_2_release_notes.md +1 -1
- data/guides/source/2_3_release_notes.md +4 -4
- data/guides/source/3_0_release_notes.md +8 -8
- data/guides/source/3_1_release_notes.md +6 -3
- data/guides/source/3_2_release_notes.md +6 -3
- data/guides/source/4_0_release_notes.md +6 -3
- data/guides/source/4_1_release_notes.md +5 -6
- data/guides/source/4_2_release_notes.md +850 -0
- data/guides/source/_license.html.erb +1 -1
- data/guides/source/_welcome.html.erb +2 -8
- data/guides/source/action_controller_overview.md +81 -7
- data/guides/source/action_mailer_basics.md +91 -28
- data/guides/source/action_view_overview.md +148 -130
- data/guides/source/active_job_basics.md +318 -0
- data/guides/source/active_model_basics.md +371 -17
- data/guides/source/active_record_basics.md +19 -18
- data/guides/source/active_record_callbacks.md +12 -9
- data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
- data/guides/source/active_record_postgresql.md +433 -0
- data/guides/source/active_record_querying.md +263 -265
- data/guides/source/active_record_validations.md +20 -11
- data/guides/source/active_support_core_extensions.md +159 -72
- data/guides/source/active_support_instrumentation.md +10 -7
- data/guides/source/api_documentation_guidelines.md +62 -16
- data/guides/source/asset_pipeline.md +258 -63
- data/guides/source/association_basics.md +81 -74
- data/guides/source/caching_with_rails.md +32 -7
- data/guides/source/command_line.md +52 -30
- data/guides/source/configuring.md +132 -29
- data/guides/source/constant_autoloading_and_reloading.md +1297 -0
- data/guides/source/contributing_to_ruby_on_rails.md +192 -112
- data/guides/source/credits.html.erb +2 -2
- data/guides/source/debugging_rails_applications.md +440 -286
- data/guides/source/development_dependencies_install.md +47 -36
- data/guides/source/documents.yaml +19 -7
- data/guides/source/engines.md +182 -182
- data/guides/source/form_helpers.md +79 -56
- data/guides/source/generators.md +24 -11
- data/guides/source/getting_started.md +337 -198
- data/guides/source/i18n.md +108 -65
- data/guides/source/index.html.erb +1 -0
- data/guides/source/initialization.md +108 -61
- data/guides/source/layout.html.erb +1 -4
- data/guides/source/layouts_and_rendering.md +27 -25
- data/guides/source/maintenance_policy.md +6 -3
- data/guides/source/nested_model_forms.md +7 -4
- data/guides/source/plugins.md +27 -27
- data/guides/source/rails_application_templates.md +21 -3
- data/guides/source/rails_on_rack.md +8 -4
- data/guides/source/routing.md +98 -72
- data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
- data/guides/source/security.md +38 -32
- data/guides/source/testing.md +188 -117
- data/guides/source/upgrading_ruby_on_rails.md +254 -28
- data/guides/source/working_with_javascript_in_rails.md +18 -16
- data/guides/w3c_validator.rb +2 -0
- metadata +40 -96
- data/guides/bug_report_templates/generic_gem.rb +0 -15
- data/guides/bug_report_templates/generic_master.rb +0 -26
- data/guides/code/getting_started/Gemfile +0 -40
- data/guides/code/getting_started/Gemfile.lock +0 -125
- data/guides/code/getting_started/README.rdoc +0 -28
- data/guides/code/getting_started/Rakefile +0 -6
- data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
- data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
- data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
- data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
- data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
- data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
- data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
- data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
- data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
- data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
- data/guides/code/getting_started/app/models/comment.rb +0 -3
- data/guides/code/getting_started/app/models/post.rb +0 -7
- data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
- data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
- data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
- data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
- data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
- data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
- data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
- data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
- data/guides/code/getting_started/bin/bundle +0 -4
- data/guides/code/getting_started/bin/rails +0 -4
- data/guides/code/getting_started/bin/rake +0 -4
- data/guides/code/getting_started/config/application.rb +0 -18
- data/guides/code/getting_started/config/boot.rb +0 -4
- data/guides/code/getting_started/config/database.yml +0 -25
- data/guides/code/getting_started/config/environment.rb +0 -5
- data/guides/code/getting_started/config/environments/development.rb +0 -30
- data/guides/code/getting_started/config/environments/production.rb +0 -80
- data/guides/code/getting_started/config/environments/test.rb +0 -36
- data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
- data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
- data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
- data/guides/code/getting_started/config/initializers/locale.rb +0 -9
- data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
- data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
- data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
- data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
- data/guides/code/getting_started/config/locales/en.yml +0 -23
- data/guides/code/getting_started/config/routes.rb +0 -7
- data/guides/code/getting_started/config.ru +0 -4
- data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
- data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
- data/guides/code/getting_started/db/schema.rb +0 -33
- data/guides/code/getting_started/db/seeds.rb +0 -7
- data/guides/code/getting_started/public/404.html +0 -60
- data/guides/code/getting_started/public/422.html +0 -60
- data/guides/code/getting_started/public/500.html +0 -59
- data/guides/code/getting_started/public/favicon.ico +0 -0
- data/guides/code/getting_started/public/robots.txt +0 -5
- data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
- data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
- data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
- data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
- data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
- data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
- data/guides/code/getting_started/test/models/comment_test.rb +0 -7
- data/guides/code/getting_started/test/models/post_test.rb +0 -7
- data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -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
|
@@ -1129,15 +1138,15 @@ generating a scaffold, Rails will put some ERB into the `_form.html.erb` that
|
|
1129
1138
|
it generates that displays the full list of errors on that model.
|
1130
1139
|
|
1131
1140
|
Assuming we have a model that's been saved in an instance variable named
|
1132
|
-
`@
|
1141
|
+
`@article`, it looks like this:
|
1133
1142
|
|
1134
1143
|
```ruby
|
1135
|
-
<% if @
|
1144
|
+
<% if @article.errors.any? %>
|
1136
1145
|
<div id="error_explanation">
|
1137
|
-
<h2><%= pluralize(@
|
1146
|
+
<h2><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h2>
|
1138
1147
|
|
1139
1148
|
<ul>
|
1140
|
-
<% @
|
1149
|
+
<% @article.errors.full_messages.each do |msg| %>
|
1141
1150
|
<li><%= msg %></li>
|
1142
1151
|
<% end %>
|
1143
1152
|
</ul>
|
@@ -1151,7 +1160,7 @@ the entry.
|
|
1151
1160
|
|
1152
1161
|
```
|
1153
1162
|
<div class="field_with_errors">
|
1154
|
-
<input id="
|
1163
|
+
<input id="article_title" name="article[title]" size="30" type="text" value="">
|
1155
1164
|
</div>
|
1156
1165
|
```
|
1157
1166
|
|
@@ -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
|
@@ -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:
|
@@ -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.
|
@@ -2719,11 +2736,14 @@ The method `transform_keys` accepts a block and returns a hash that has applied
|
|
2719
2736
|
# => {"" => nil, "A" => :a, "1" => 1}
|
2720
2737
|
```
|
2721
2738
|
|
2722
|
-
|
2739
|
+
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
2740
|
|
2724
2741
|
```ruby
|
2725
2742
|
{"a" => 1, a: 2}.transform_keys { |key| key.to_s.upcase }
|
2726
|
-
#
|
2743
|
+
# The result could either be
|
2744
|
+
# => {"A"=>2}
|
2745
|
+
# or
|
2746
|
+
# => {"A"=>1}
|
2727
2747
|
```
|
2728
2748
|
|
2729
2749
|
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 +2778,14 @@ The method `stringify_keys` returns a hash that has a stringified version of the
|
|
2758
2778
|
# => {"" => nil, "a" => :a, "1" => 1}
|
2759
2779
|
```
|
2760
2780
|
|
2761
|
-
|
2781
|
+
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
2782
|
|
2763
2783
|
```ruby
|
2764
2784
|
{"a" => 1, a: 2}.stringify_keys
|
2765
|
-
#
|
2785
|
+
# The result could either be
|
2786
|
+
# => {"a"=>2}
|
2787
|
+
# or
|
2788
|
+
# => {"a"=>1}
|
2766
2789
|
```
|
2767
2790
|
|
2768
2791
|
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionView::Helpers::FormHelper` defines:
|
@@ -2799,11 +2822,14 @@ The method `symbolize_keys` returns a hash that has a symbolized version of the
|
|
2799
2822
|
|
2800
2823
|
WARNING. Note in the previous example only one key was symbolized.
|
2801
2824
|
|
2802
|
-
|
2825
|
+
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
2826
|
|
2804
2827
|
```ruby
|
2805
2828
|
{"a" => 1, a: 2}.symbolize_keys
|
2806
|
-
#
|
2829
|
+
# The result could either be
|
2830
|
+
# => {:a=>2}
|
2831
|
+
# or
|
2832
|
+
# => {:a=>1}
|
2807
2833
|
```
|
2808
2834
|
|
2809
2835
|
This method may be useful for example to easily accept both symbols and strings as options. For instance `ActionController::UrlRewriter` defines
|
@@ -2848,6 +2874,20 @@ Active Record does not accept unknown options when building associations, for ex
|
|
2848
2874
|
|
2849
2875
|
NOTE: Defined in `active_support/core_ext/hash/keys.rb`.
|
2850
2876
|
|
2877
|
+
### Working with Values
|
2878
|
+
|
2879
|
+
#### `transform_values` && `transform_values!`
|
2880
|
+
|
2881
|
+
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.
|
2882
|
+
|
2883
|
+
```ruby
|
2884
|
+
{ nil => nil, 1 => 1, :x => :a }.transform_values { |value| value.to_s.upcase }
|
2885
|
+
# => {nil=>"", 1=>"1", :x=>"A"}
|
2886
|
+
```
|
2887
|
+
There's also the bang variant `transform_values!` that applies the block operations to values in the very receiver.
|
2888
|
+
|
2889
|
+
NOTE: Defined in `active_support/core_text/hash/transform_values.rb`.
|
2890
|
+
|
2851
2891
|
### Slicing
|
2852
2892
|
|
2853
2893
|
Ruby has built-in support for taking slices out of strings and arrays. Active Support extends slicing to hashes:
|
@@ -2911,7 +2951,7 @@ NOTE: Defined in `active_support/core_ext/hash/indifferent_access.rb`.
|
|
2911
2951
|
|
2912
2952
|
### Compacting
|
2913
2953
|
|
2914
|
-
The methods `compact` and `compact!` return a Hash without items with `nil` value.
|
2954
|
+
The methods `compact` and `compact!` return a Hash without items with `nil` value.
|
2915
2955
|
|
2916
2956
|
```ruby
|
2917
2957
|
{a: 1, b: 2, c: nil}.compact # => {a: 1, b: 2}
|
@@ -3003,6 +3043,53 @@ The method `Range#overlaps?` says whether any two given ranges have non-void int
|
|
3003
3043
|
|
3004
3044
|
NOTE: Defined in `active_support/core_ext/range/overlaps.rb`.
|
3005
3045
|
|
3046
|
+
Extensions to `Proc`
|
3047
|
+
--------------------
|
3048
|
+
|
3049
|
+
### `bind`
|
3050
|
+
|
3051
|
+
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:
|
3052
|
+
|
3053
|
+
```ruby
|
3054
|
+
Hash.instance_method(:delete) # => #<UnboundMethod: Hash#delete>
|
3055
|
+
```
|
3056
|
+
|
3057
|
+
An unbound method is not callable as is, you need to bind it first to an object with `bind`:
|
3058
|
+
|
3059
|
+
```ruby
|
3060
|
+
clear = Hash.instance_method(:clear)
|
3061
|
+
clear.bind({a: 1}).call # => {}
|
3062
|
+
```
|
3063
|
+
|
3064
|
+
Active Support defines `Proc#bind` with an analogous purpose:
|
3065
|
+
|
3066
|
+
```ruby
|
3067
|
+
Proc.new { size }.bind([]).call # => 0
|
3068
|
+
```
|
3069
|
+
|
3070
|
+
As you see that's callable and bound to the argument, the return value is indeed a `Method`.
|
3071
|
+
|
3072
|
+
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.
|
3073
|
+
|
3074
|
+
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:
|
3075
|
+
|
3076
|
+
```ruby
|
3077
|
+
def handler_for_rescue(exception)
|
3078
|
+
_, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
|
3079
|
+
...
|
3080
|
+
end
|
3081
|
+
|
3082
|
+
case rescuer
|
3083
|
+
when Symbol
|
3084
|
+
method(rescuer)
|
3085
|
+
when Proc
|
3086
|
+
rescuer.bind(self)
|
3087
|
+
end
|
3088
|
+
end
|
3089
|
+
```
|
3090
|
+
|
3091
|
+
NOTE: Defined in `active_support/core_ext/proc.rb`.
|
3092
|
+
|
3006
3093
|
Extensions to `Date`
|
3007
3094
|
--------------------
|
3008
3095
|
|
@@ -3611,9 +3698,9 @@ t.advance(seconds: 1)
|
|
3611
3698
|
|
3612
3699
|
#### `Time.current`
|
3613
3700
|
|
3614
|
-
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
|
3701
|
+
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`.
|
3615
3702
|
|
3616
|
-
When making Time comparisons using methods which honor the user time zone, make sure to use `Time.current`
|
3703
|
+
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`.
|
3617
3704
|
|
3618
3705
|
#### `all_day`, `all_week`, `all_month`, `all_quarter` and `all_year`
|
3619
3706
|
|
@@ -3777,7 +3864,7 @@ The name may be given as a symbol or string. A symbol is tested against the bare
|
|
3777
3864
|
|
3778
3865
|
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.
|
3779
3866
|
|
3780
|
-
For example, when an action of `
|
3867
|
+
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:
|
3781
3868
|
|
3782
3869
|
```ruby
|
3783
3870
|
def default_helper_module!
|
@@ -3791,7 +3878,7 @@ rescue NameError => e
|
|
3791
3878
|
end
|
3792
3879
|
```
|
3793
3880
|
|
3794
|
-
NOTE: Defined in `
|
3881
|
+
NOTE: Defined in `active_support/core_ext/name_error.rb`.
|
3795
3882
|
|
3796
3883
|
Extensions to `LoadError`
|
3797
3884
|
-------------------------
|
@@ -3800,7 +3887,7 @@ Active Support adds `is_missing?` to `LoadError`, and also assigns that class to
|
|
3800
3887
|
|
3801
3888
|
Given a path name `is_missing?` tests whether the exception was raised due to that particular file (except perhaps for the ".rb" extension).
|
3802
3889
|
|
3803
|
-
For example, when an action of `
|
3890
|
+
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:
|
3804
3891
|
|
3805
3892
|
```ruby
|
3806
3893
|
def default_helper_module!
|
@@ -3814,4 +3901,4 @@ rescue NameError => e
|
|
3814
3901
|
end
|
3815
3902
|
```
|
3816
3903
|
|
3817
|
-
NOTE: Defined in `
|
3904
|
+
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
|
|
@@ -364,7 +366,7 @@ INFO. Options passed to fetch will be merged with the payload.
|
|
364
366
|
| ------ | --------------------- |
|
365
367
|
| `:key` | Key used in the store |
|
366
368
|
|
367
|
-
INFO. Cache stores
|
369
|
+
INFO. Cache stores may add their own keys
|
368
370
|
|
369
371
|
```ruby
|
370
372
|
{
|
@@ -457,6 +459,7 @@ Most times you only care about the data itself. Here is a shortcut to just get t
|
|
457
459
|
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
|
458
460
|
data = args.extract_options!
|
459
461
|
data # { extra: :information }
|
462
|
+
end
|
460
463
|
```
|
461
464
|
|
462
465
|
You may also subscribe to events matching a regular expression. This enables you to subscribe to
|