activesupport 5.2.1.1 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +416 -351
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -2
  5. data/lib/active_support.rb +2 -1
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +28 -1
  8. data/lib/active_support/cache.rb +45 -23
  9. data/lib/active_support/cache/file_store.rb +22 -22
  10. data/lib/active_support/cache/mem_cache_store.rb +5 -0
  11. data/lib/active_support/cache/memory_store.rb +9 -2
  12. data/lib/active_support/cache/null_store.rb +5 -0
  13. data/lib/active_support/cache/redis_cache_store.rb +37 -10
  14. data/lib/active_support/callbacks.rb +16 -5
  15. data/lib/active_support/concern.rb +31 -4
  16. data/lib/active_support/configurable.rb +7 -11
  17. data/lib/active_support/core_ext/array.rb +1 -1
  18. data/lib/active_support/core_ext/array/access.rb +18 -6
  19. data/lib/active_support/core_ext/array/extract.rb +21 -0
  20. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
  21. data/lib/active_support/core_ext/class/attribute.rb +11 -16
  22. data/lib/active_support/core_ext/class/subclasses.rb +1 -1
  23. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  24. data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
  25. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  26. data/lib/active_support/core_ext/digest.rb +3 -0
  27. data/lib/active_support/core_ext/enumerable.rb +97 -73
  28. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  29. data/lib/active_support/core_ext/hash.rb +1 -2
  30. data/lib/active_support/core_ext/hash/compact.rb +2 -26
  31. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  32. data/lib/active_support/core_ext/hash/except.rb +1 -1
  33. data/lib/active_support/core_ext/hash/keys.rb +0 -29
  34. data/lib/active_support/core_ext/hash/slice.rb +3 -25
  35. data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
  36. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  37. data/lib/active_support/core_ext/kernel.rb +0 -1
  38. data/lib/active_support/core_ext/load_error.rb +1 -1
  39. data/lib/active_support/core_ext/module.rb +0 -1
  40. data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
  41. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
  42. data/lib/active_support/core_ext/module/delegation.rb +33 -7
  43. data/lib/active_support/core_ext/module/introspection.rb +37 -13
  44. data/lib/active_support/core_ext/module/reachable.rb +1 -6
  45. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  46. data/lib/active_support/core_ext/numeric.rb +0 -1
  47. data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
  48. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
  49. data/lib/active_support/core_ext/object/blank.rb +1 -2
  50. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  51. data/lib/active_support/core_ext/object/json.rb +1 -0
  52. data/lib/active_support/core_ext/object/try.rb +15 -7
  53. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  54. data/lib/active_support/core_ext/range.rb +1 -1
  55. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  56. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  57. data/lib/active_support/core_ext/range/include_range.rb +6 -22
  58. data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
  59. data/lib/active_support/core_ext/regexp.rb +0 -4
  60. data/lib/active_support/core_ext/securerandom.rb +23 -3
  61. data/lib/active_support/core_ext/string/access.rb +8 -0
  62. data/lib/active_support/core_ext/string/filters.rb +42 -1
  63. data/lib/active_support/core_ext/string/inflections.rb +7 -2
  64. data/lib/active_support/core_ext/string/multibyte.rb +4 -3
  65. data/lib/active_support/core_ext/string/output_safety.rb +63 -5
  66. data/lib/active_support/core_ext/string/strip.rb +3 -1
  67. data/lib/active_support/core_ext/time/calculations.rb +31 -2
  68. data/lib/active_support/core_ext/uri.rb +2 -1
  69. data/lib/active_support/current_attributes.rb +8 -0
  70. data/lib/active_support/dependencies.rb +74 -17
  71. data/lib/active_support/dependencies/zeitwerk_integration.rb +118 -0
  72. data/lib/active_support/deprecation.rb +1 -1
  73. data/lib/active_support/deprecation/behaviors.rb +1 -1
  74. data/lib/active_support/deprecation/method_wrappers.rb +13 -12
  75. data/lib/active_support/deprecation/proxy_wrappers.rb +24 -5
  76. data/lib/active_support/descendants_tracker.rb +56 -9
  77. data/lib/active_support/duration.rb +6 -5
  78. data/lib/active_support/duration/iso8601_parser.rb +2 -3
  79. data/lib/active_support/duration/iso8601_serializer.rb +3 -4
  80. data/lib/active_support/encrypted_configuration.rb +1 -5
  81. data/lib/active_support/encrypted_file.rb +2 -1
  82. data/lib/active_support/evented_file_update_checker.rb +39 -9
  83. data/lib/active_support/execution_wrapper.rb +1 -0
  84. data/lib/active_support/gem_version.rb +3 -3
  85. data/lib/active_support/hash_with_indifferent_access.rb +36 -18
  86. data/lib/active_support/i18n.rb +1 -0
  87. data/lib/active_support/i18n_railtie.rb +14 -2
  88. data/lib/active_support/inflector/inflections.rb +1 -4
  89. data/lib/active_support/inflector/methods.rb +17 -27
  90. data/lib/active_support/inflector/transliterate.rb +47 -18
  91. data/lib/active_support/json/decoding.rb +23 -23
  92. data/lib/active_support/json/encoding.rb +6 -2
  93. data/lib/active_support/key_generator.rb +0 -32
  94. data/lib/active_support/lazy_load_hooks.rb +5 -1
  95. data/lib/active_support/locale/en.rb +31 -0
  96. data/lib/active_support/log_subscriber.rb +31 -8
  97. data/lib/active_support/logger.rb +0 -15
  98. data/lib/active_support/logger_silence.rb +28 -12
  99. data/lib/active_support/logger_thread_safe_level.rb +28 -5
  100. data/lib/active_support/message_encryptor.rb +3 -5
  101. data/lib/active_support/message_verifier.rb +3 -3
  102. data/lib/active_support/multibyte/chars.rb +29 -48
  103. data/lib/active_support/multibyte/unicode.rb +44 -281
  104. data/lib/active_support/notifications.rb +41 -4
  105. data/lib/active_support/notifications/fanout.rb +100 -15
  106. data/lib/active_support/notifications/instrumenter.rb +80 -8
  107. data/lib/active_support/number_helper.rb +7 -0
  108. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -2
  109. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
  110. data/lib/active_support/number_helper/number_to_human_converter.rb +3 -1
  111. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -1
  112. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  113. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -0
  114. data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -3
  115. data/lib/active_support/ordered_hash.rb +1 -1
  116. data/lib/active_support/ordered_options.rb +1 -1
  117. data/lib/active_support/parameter_filter.rb +129 -0
  118. data/lib/active_support/rails.rb +0 -6
  119. data/lib/active_support/reloader.rb +4 -5
  120. data/lib/active_support/security_utils.rb +1 -1
  121. data/lib/active_support/subscriber.rb +65 -22
  122. data/lib/active_support/tagged_logging.rb +13 -4
  123. data/lib/active_support/test_case.rb +91 -0
  124. data/lib/active_support/testing/assertions.rb +15 -1
  125. data/lib/active_support/testing/deprecation.rb +0 -1
  126. data/lib/active_support/testing/file_fixtures.rb +2 -0
  127. data/lib/active_support/testing/isolation.rb +2 -2
  128. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  129. data/lib/active_support/testing/parallelization.rb +128 -0
  130. data/lib/active_support/testing/stream.rb +1 -1
  131. data/lib/active_support/testing/time_helpers.rb +7 -7
  132. data/lib/active_support/time_with_zone.rb +15 -5
  133. data/lib/active_support/values/time_zone.rb +12 -7
  134. data/lib/active_support/xml_mini.rb +2 -9
  135. data/lib/active_support/xml_mini/jdom.rb +2 -2
  136. data/lib/active_support/xml_mini/libxml.rb +2 -2
  137. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  138. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  139. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  140. data/lib/active_support/xml_mini/rexml.rb +2 -2
  141. metadata +33 -10
  142. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  143. data/lib/active_support/values/unicode_tables.dat +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 012f11c548ca33d5985eb783e46a9d962b5cf3c22f007f74a39e8120da80b2d4
4
- data.tar.gz: 1157743e77c0a3dceff1f24dfe39adf5c06654b522b13c999ff04d37888f85b5
3
+ metadata.gz: 89999be252d7cdb9b27994ea4a149baabf876606a5899e8c7dfe5309278bf57a
4
+ data.tar.gz: c79f2634e9a995e6c0ad95ca68f3a04905153502560e2a25de871cb4c4782e4f
5
5
  SHA512:
6
- metadata.gz: 3cd090a071824b4ec714de532134d06bb89e9c70d99d3e7acb0c6bf5b32019a5b3f5cf1c51b12855edb4617f484c4610b4398c212ef6d1bb32d16931b1537b9f
7
- data.tar.gz: 014f671c9490e3c856519bc4d87a220a9998a658c09fe1d842cd616ca320ef2ca522fe0a2edbcbee8dc227b593ba12dea6a29b64e1a4ee9aabf7a56a337446e9
6
+ metadata.gz: 9aed32dcff5ff2bbeaeb386f289292c3a18d8bf3dde6d5a72eff792f41216041853fbbbefe01aa35aef16330f13a54bca4744235bdee5a90783e34bc8b48c1f6
7
+ data.tar.gz: 6ceefce5d0753a5a91df29b365579b8e84be9b252b5abe5c7e3f5183dad8a9389a0de2fc50f6668147d6b9def2efe9e6dc1dc48e221dda19767586a37a9d3d3f
@@ -1,552 +1,617 @@
1
- ## Rails 5.2.1.1 (November 27, 2018) ##
1
+ ## Rails 6.0.1 (November 5, 2019) ##
2
2
 
3
- * No changes.
3
+ * `ActiveSupport::SafeBuffer` supports `Enumerator` methods.
4
4
 
5
+ *Shugo Maeda*
5
6
 
6
- ## Rails 5.2.1 (August 07, 2018) ##
7
+ * The Redis cache store fails gracefully when the server returns a "max number
8
+ of clients reached" error.
7
9
 
8
- * Redis cache store: `delete_matched` no longer blocks the Redis server.
9
- (Switches from evaled Lua to a batched SCAN + DEL loop.)
10
+ *Brandon Medenwald*
10
11
 
11
- *Gleb Mazovetskiy*
12
+ * Fixed that mutating a value returned by a memory cache store would
13
+ unexpectedly change the cached value.
12
14
 
13
- * Fix bug where `ActiveSupport::Timezone.all` would fail when tzinfo data for
14
- any timezone defined in `ActiveSupport::TimeZone::MAPPING` is missing.
15
+ *Jonathan Hyman*
15
16
 
16
- *Dominik Sander*
17
+ * The default inflectors in `zeitwerk` mode support overrides:
17
18
 
18
- * Fix bug where `ActiveSupport::Cache` will massively inflate the storage
19
- size when compression is enabled (which is true by default). This patch
20
- does not attempt to repair existing data: please manually flush the cache
21
- to clear out the problematic entries.
19
+ ```ruby
20
+ # config/initializers/zeitwerk.rb
21
+ Rails.autoloaders.each do |autoloader|
22
+ autoloader.inflector.inflect(
23
+ "html_parser" => "HTMLParser",
24
+ "ssl_error" => "SSLError"
25
+ )
26
+ end
27
+ ```
22
28
 
23
- *Godfrey Chan*
29
+ That way, you can tweak how individual basenames are inflected without touching Active Support inflection rules, which are global. These inflectors fallback to `String#camelize`, so existing inflection rules are still taken into account for non-overridden basenames.
24
30
 
25
- * Fix `ActiveSupport::Cache#read_multi` bug with local cache enabled that was
26
- returning instances of `ActiveSupport::Cache::Entry` instead of the raw values.
31
+ Please, check the [autoloading guide for `zeitwerk` mode](https://guides.rubyonrails.org/v6.0/autoloading_and_reloading_constants.html#customizing-inflections) if you prefer not to depend on `String#camelize` at all.
27
32
 
28
- *Jason Lee*
33
+ *Xavier Noria*
29
34
 
35
+ * Improve `Range#===`, `Range#include?`, and `Range#cover?` to work with beginless (startless)
36
+ and endless range targets.
30
37
 
31
- ## Rails 5.2.0 (April 09, 2018) ##
38
+ *Allen Hsu*, *Andrew Hodgkinson*
32
39
 
33
- * Caching: MemCache and Redis `read_multi` and `fetch_multi` speedup.
34
- Read from the local in-memory cache before consulting the backend.
40
+ * Don't use `Process#clock_gettime(CLOCK_PROCESS_CPUTIME_ID)` on Solaris
35
41
 
36
- *Gabriel Sobrinho*
42
+ *Iain Beeston*
37
43
 
38
- * Return all mappings for a timezone identifier in `country_zones`.
39
44
 
40
- Some timezones like `Europe/London` have multiple mappings in
41
- `ActiveSupport::TimeZone::MAPPING` so return all of them instead
42
- of the first one found by using `Hash#value`. e.g:
45
+ ## Rails 6.0.0 (August 16, 2019) ##
43
46
 
44
- # Before
45
- ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh"]
47
+ * Let `require_dependency` in `zeitwerk` mode look the autoload paths up for
48
+ better backwards compatibility.
46
49
 
47
- # After
48
- ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh", "London"]
50
+ *Xavier Noria*
49
51
 
50
- Fixes #31668.
52
+ * Let `require_dependency` in `zeitwerk` mode support arguments that respond
53
+ to `to_path` for better backwards compatibility.
51
54
 
52
- *Andrew White*
55
+ *Xavier Noria*
53
56
 
54
- * Add support for connection pooling on RedisCacheStore.
57
+ * Make ActiveSupport::Logger Fiber-safe. Fixes #36752.
55
58
 
56
- *fatkodima*
59
+ Use `Fiber.current.__id__` in `ActiveSupport::Logger#local_level=` in order
60
+ to make log level local to Ruby Fibers in addition to Threads.
57
61
 
58
- * Support hash as first argument in `assert_difference`. This allows to specify multiple
59
- numeric differences in the same assertion.
62
+ Example:
60
63
 
61
- assert_difference ->{ Article.count } => 1, ->{ Post.count } => 2
64
+ logger = ActiveSupport::Logger.new(STDOUT)
65
+ logger.level = 1
66
+ p "Main is debug? #{logger.debug?}"
62
67
 
63
- *Julien Meichelbeck*
68
+ Fiber.new {
69
+ logger.local_level = 0
70
+ p "Thread is debug? #{logger.debug?}"
71
+ }.resume
64
72
 
65
- * Add missing instrumentation for `read_multi` in `ActiveSupport::Cache::Store`.
73
+ p "Main is debug? #{logger.debug?}"
66
74
 
67
- *Ignatius Reza Lesmana*
75
+ Before:
68
76
 
69
- * `assert_changes` will always assert that the expression changes,
70
- regardless of `from:` and `to:` argument combinations.
77
+ Main is debug? false
78
+ Thread is debug? true
79
+ Main is debug? true
71
80
 
72
- *Daniel Ma*
81
+ After:
73
82
 
74
- * Use SHA-1 to generate non-sensitive digests, such as the ETag header.
83
+ Main is debug? false
84
+ Thread is debug? true
85
+ Main is debug? false
75
86
 
76
- Enabled by default for new apps; upgrading apps can opt in by setting
77
- `config.active_support.use_sha1_digests = true`.
87
+ *Alexander Varnin*
78
88
 
79
- *Dmitri Dolguikh*, *Eugene Kenny*
89
+ * Do not delegate missing `marshal_dump` and `_dump` methods via the
90
+ `delegate_missing_to` extension. This avoids unintentionally adding instance
91
+ variables when calling `Marshal.dump(object)`, should the delegation target of
92
+ `object` be a method which would otherwise add them. Fixes #36522.
80
93
 
81
- * Changed default behaviour of `ActiveSupport::SecurityUtils.secure_compare`,
82
- to make it not leak length information even for variable length string.
94
+ *Aaron Lipman*
83
95
 
84
- Renamed old `ActiveSupport::SecurityUtils.secure_compare` to `fixed_length_secure_compare`,
85
- and started raising `ArgumentError` in case of length mismatch of passed strings.
86
96
 
87
- *Vipul A M*
97
+ ## Rails 6.0.0.rc2 (July 22, 2019) ##
88
98
 
89
- * Make `ActiveSupport::TimeZone.all` return only time zones that are in
90
- `ActiveSupport::TimeZone::MAPPING`.
99
+ * `truncate` would return the original string if it was too short to be truncated
100
+ and a frozen string if it were long enough to be truncated. Now truncate will
101
+ consistently return an unfrozen string regardless. This behavior is consistent
102
+ with `gsub` and `strip`.
91
103
 
92
- Fixes #7245.
104
+ Before:
93
105
 
94
- *Chris LaRose*
106
+ 'foobar'.truncate(5).frozen?
107
+ # => true
108
+ 'foobar'.truncate(6).frozen?
109
+ # => false
95
110
 
96
- * MemCacheStore: Support expiring counters.
111
+ After:
97
112
 
98
- Pass `expires_in: [seconds]` to `#increment` and `#decrement` options
99
- to set the Memcached TTL (time-to-live) if the counter doesn't exist.
100
- If the counter exists, Memcached doesn't extend its expiry when it's
101
- incremented or decremented.
113
+ 'foobar'.truncate(5).frozen?
114
+ # => false
115
+ 'foobar'.truncate(6).frozen?
116
+ # => false
102
117
 
103
- ```
104
- Rails.cache.increment("my_counter", 1, expires_in: 2.minutes)
105
- ```
118
+ *Jordan Thomas*
106
119
 
107
- *Takumasa Ochi*
108
120
 
109
- * Handle `TZInfo::AmbiguousTime` errors.
121
+ ## Rails 6.0.0.rc1 (April 24, 2019) ##
110
122
 
111
- Make `ActiveSupport::TimeWithZone` match Ruby's handling of ambiguous
112
- times by choosing the later period, e.g.
123
+ * Introduce `ActiveSupport::ActionableError`.
113
124
 
114
- Ruby:
115
- ```
116
- ENV["TZ"] = "Europe/Moscow"
117
- Time.local(2014, 10, 26, 1, 0, 0) # => 2014-10-26 01:00:00 +0300
125
+ Actionable errors let's you dispatch actions from Rails' error pages. This
126
+ can help you save time if you have a clear action for the resolution of
127
+ common development errors.
128
+
129
+ The de-facto example are pending migrations. Every time pending migrations
130
+ are found, a middleware raises an error. With actionable errors, you can
131
+ run the migrations right from the error page. Other examples include Rails
132
+ plugins that need to run a rake task to setup themselves. They can now
133
+ raise actionable errors to run the setup straight from the error pages.
134
+
135
+ Here is how to define an actionable error:
136
+
137
+ ```ruby
138
+ class PendingMigrationError < MigrationError #:nodoc:
139
+ include ActiveSupport::ActionableError
140
+
141
+ action "Run pending migrations" do
142
+ ActiveRecord::Tasks::DatabaseTasks.migrate
143
+ end
144
+ end
118
145
  ```
119
146
 
147
+ To make an error actionable, include the `ActiveSupport::ActionableError`
148
+ module and invoke the `action` class macro to define the action. An action
149
+ needs a name and a procedure to execute. The name is shown as the name of a
150
+ button on the error pages. Once clicked, it will invoke the given
151
+ procedure.
152
+
153
+ *Vipul A M*, *Yao Jie*, *Genadi Samokovarov*
154
+
155
+ * Preserve `html_safe?` status on `ActiveSupport::SafeBuffer#*`.
156
+
120
157
  Before:
121
- ```
122
- >> "2014-10-26 01:00:00".in_time_zone("Moscow")
123
- TZInfo::AmbiguousTime: 26/10/2014 01:00 is an ambiguous local time.
124
- ```
158
+
159
+ ("<br />".html_safe * 2).html_safe? #=> nil
125
160
 
126
161
  After:
127
- ```
128
- >> "2014-10-26 01:00:00".in_time_zone("Moscow")
129
- => Sun, 26 Oct 2014 01:00:00 MSK +03:00
130
- ```
131
162
 
132
- Fixes #17395.
163
+ ("<br />".html_safe * 2).html_safe? #=> true
133
164
 
134
- *Andrew White*
165
+ *Ryo Nakamura*
135
166
 
136
- * Redis cache store.
167
+ * Calling test methods with `with_info_handler` method to allow minitest-hooks
168
+ plugin to work.
137
169
 
138
- ```
139
- # Defaults to `redis://localhost:6379/0`. Only use for dev/test.
140
- config.cache_store = :redis_cache_store
141
-
142
- # Supports all common cache store options (:namespace, :compress,
143
- # :compress_threshold, :expires_in, :race_condition_ttl) and all
144
- # Redis options.
145
- cache_password = Rails.application.secrets.redis_cache_password
146
- config.cache_store = :redis_cache_store, driver: :hiredis,
147
- namespace: 'myapp-cache', compress: true, timeout: 1,
148
- url: "redis://:#{cache_password}@myapp-cache-1:6379/0"
149
-
150
- # Supports Redis::Distributed with multiple hosts
151
- config.cache_store = :redis_cache_store, driver: :hiredis
152
- namespace: 'myapp-cache', compress: true,
153
- url: %w[
154
- redis://myapp-cache-1:6379/0
155
- redis://myapp-cache-1:6380/0
156
- redis://myapp-cache-2:6379/0
157
- redis://myapp-cache-2:6380/0
158
- redis://myapp-cache-3:6379/0
159
- redis://myapp-cache-3:6380/0
160
- ]
161
-
162
- # Or pass a builder block
163
- config.cache_store = :redis_cache_store,
164
- namespace: 'myapp-cache', compress: true,
165
- redis: -> { Redis.new … }
166
- ```
170
+ *Mauri Mustonen*
167
171
 
168
- Deployment note: Take care to use a *dedicated Redis cache* rather
169
- than pointing this at your existing Redis server. It won't cope well
170
- with mixed usage patterns and it won't expire cache entries by default.
172
+ * The Zeitwerk compatibility interface for `ActiveSupport::Dependencies` no
173
+ longer implements `autoloaded_constants` or `autoloaded?` (undocumented,
174
+ anyway). Experience shows introspection does not have many use cases, and
175
+ troubleshooting is done by logging. With this design trade-off we are able
176
+ to use even less memory in all environments.
171
177
 
172
- Redis cache server setup guide: https://redis.io/topics/lru-cache
178
+ *Xavier Noria*
173
179
 
174
- *Jeremy Daer*
180
+ * Depends on Zeitwerk 2, which stores less metadata if reloading is disabled
181
+ and hence uses less memory when `config.cache_classes` is `true`, a standard
182
+ setup in production.
175
183
 
176
- * Cache: Enable compression by default for values > 1kB.
184
+ *Xavier Noria*
177
185
 
178
- Compression has long been available, but opt-in and at a 16kB threshold.
179
- It wasn't enabled by default due to CPU cost. Today it's cheap and typical
180
- cache data is eminently compressible, such as HTML or JSON fragments.
181
- Compression dramatically reduces Memcached/Redis mem usage, which means
182
- the same cache servers can store more data, which means higher hit rates.
186
+ * In `:zeitwerk` mode, eager load directories in engines and applications only
187
+ if present in their respective `config.eager_load_paths`.
183
188
 
184
- To disable compression, pass `compress: false` to the initializer.
189
+ A common use case for this is adding `lib` to `config.autoload_paths`, but
190
+ not to `config.eager_load_paths`. In that configuration, for example, files
191
+ in the `lib` directory should not be eager loaded.
185
192
 
186
- *Jeremy Daer*
193
+ *Xavier Noria*
187
194
 
188
- * Allow `Range#include?` on TWZ ranges.
195
+ * Fix bug in Range comparisons when comparing to an excluded-end Range
189
196
 
190
- In #11474 we prevented TWZ ranges being iterated over which matched
191
- Ruby's handling of Time ranges and as a consequence `include?`
192
- stopped working with both Time ranges and TWZ ranges. However in
193
- ruby/ruby@b061634 support was added for `include?` to use `cover?`
194
- for 'linear' objects. Since we have no way of making Ruby consider
195
- TWZ instances as 'linear' we have to override `Range#include?`.
197
+ Before:
196
198
 
197
- Fixes #30799.
199
+ (1..10).cover?(1...11) # => false
198
200
 
199
- *Andrew White*
201
+ After:
200
202
 
201
- * Fix acronym support in `humanize`.
203
+ (1..10).cover?(1...11) # => true
202
204
 
203
- Acronym inflections are stored with lowercase keys in the hash but
204
- the match wasn't being lowercased before being looked up in the hash.
205
- This shouldn't have any performance impact because before it would
206
- fail to find the acronym and perform the `downcase` operation anyway.
205
+ With the same change for `Range#include?` and `Range#===`.
207
206
 
208
- Fixes #31052.
207
+ *Owen Stephens*
209
208
 
210
- *Andrew White*
209
+ * Use weak references in descendants tracker to allow anonymous subclasses to
210
+ be garbage collected.
211
+
212
+ *Edgars Beigarts*
211
213
 
212
- * Add same method signature for `Time#prev_year` and `Time#next_year`
213
- in accordance with `Date#prev_year`, `Date#next_year`.
214
+ * Update `ActiveSupport::Notifications::Instrumenter#instrument` to make
215
+ passing a block optional. This will let users use
216
+ `ActiveSupport::Notifications` messaging features outside of
217
+ instrumentation.
214
218
 
215
- Allows pass argument for `Time#prev_year` and `Time#next_year`.
219
+ *Ali Ibrahim*
220
+
221
+ * Fix `Time#advance` to work with dates before 1001-03-07
216
222
 
217
223
  Before:
218
- ```
219
- Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300
220
- Time.new(2017, 9, 16, 17, 0).prev_year(1)
221
- # => ArgumentError: wrong number of arguments (given 1, expected 0)
222
224
 
223
- Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300
224
- Time.new(2017, 9, 16, 17, 0).next_year(1)
225
- # => ArgumentError: wrong number of arguments (given 1, expected 0)
226
- ```
225
+ Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-05 00:00:00 UTC
227
226
 
228
- After:
229
- ```
230
- Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300
231
- Time.new(2017, 9, 16, 17, 0).prev_year(1) # => 2016-09-16 17:00:00 +0300
227
+ After
232
228
 
233
- Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300
234
- Time.new(2017, 9, 16, 17, 0).next_year(1) # => 2018-09-16 17:00:00 +0300
235
- ```
229
+ Time.utc(1001, 3, 6).advance(years: -1) # => 1000-03-06 00:00:00 UTC
236
230
 
237
- *bogdanvlviv*
231
+ Note that this doesn't affect `DateTime#advance` as that doesn't use a proleptic calendar.
238
232
 
239
- * Add same method signature for `Time#prev_month` and `Time#next_month`
240
- in accordance with `Date#prev_month`, `Date#next_month`.
233
+ *Andrew White*
241
234
 
242
- Allows pass argument for `Time#prev_month` and `Time#next_month`.
235
+ * In Zeitwerk mode, engines are now managed by the `main` autoloader. Engines may reference application constants, if the application is reloaded and we do not reload engines, they won't use the reloaded application code.
243
236
 
244
- Before:
245
- ```
246
- Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300
247
- Time.new(2017, 9, 16, 17, 0).prev_month(1)
248
- # => ArgumentError: wrong number of arguments (given 1, expected 0)
237
+ *Xavier Noria*
249
238
 
250
- Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300
251
- Time.new(2017, 9, 16, 17, 0).next_month(1)
252
- # => ArgumentError: wrong number of arguments (given 1, expected 0)
253
- ```
239
+ * Add support for supplying `locale` to `transliterate` and `parameterize`.
254
240
 
255
- After:
256
- ```
257
- Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300
258
- Time.new(2017, 9, 16, 17, 0).prev_month(1) # => 2017-08-16 17:00:00 +0300
241
+ I18n.backend.store_translations(:de, i18n: { transliterate: { rule: { "ü" => "ue" } } })
259
242
 
260
- Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300
261
- Time.new(2017, 9, 16, 17, 0).next_month(1) # => 2017-10-16 17:00:00 +0300
262
- ```
243
+ ActiveSupport::Inflector.transliterate("ü", locale: :de) # => "ue"
244
+ "Fünf autos".parameterize(locale: :de) # => "fuenf-autos"
245
+ ActiveSupport::Inflector.parameterize("Fünf autos", locale: :de) # => "fuenf-autos"
263
246
 
264
- *bogdanvlviv*
247
+ *Kaan Ozkan*, *Sharang Dashputre*
265
248
 
266
- * Add same method signature for `Time#prev_day` and `Time#next_day`
267
- in accordance with `Date#prev_day`, `Date#next_day`.
249
+ * Allow `Array#excluding` and `Enumerable#excluding` to deal with a passed array gracefully.
268
250
 
269
- Allows pass argument for `Time#prev_day` and `Time#next_day`.
251
+ [ 1, 2, 3, 4, 5 ].excluding([4, 5]) # => [ 1, 2, 3 ]
270
252
 
271
- Before:
272
- ```
273
- Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300
274
- Time.new(2017, 9, 16, 17, 0).prev_day(1)
275
- # => ArgumentError: wrong number of arguments (given 1, expected 0)
253
+ *DHH*
276
254
 
277
- Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300
278
- Time.new(2017, 9, 16, 17, 0).next_day(1)
279
- # => ArgumentError: wrong number of arguments (given 1, expected 0)
280
- ```
255
+ * Renamed `Array#without` and `Enumerable#without` to `Array#excluding` and `Enumerable#excluding`, to create parity with
256
+ `Array#including` and `Enumerable#including`. Retained the old names as aliases.
281
257
 
282
- After:
283
- ```
284
- Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300
285
- Time.new(2017, 9, 16, 17, 0).prev_day(1) # => 2017-09-15 17:00:00 +0300
258
+ *DHH*
286
259
 
287
- Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300
288
- Time.new(2017, 9, 16, 17, 0).next_day(1) # => 2017-09-17 17:00:00 +0300
289
- ```
260
+ * Added `Array#including` and `Enumerable#including` to conveniently enlarge a collection with more members using a method rather than an operator:
290
261
 
291
- *bogdanvlviv*
262
+ [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
263
+ post.authors.including(Current.person) # => All the authors plus the current person!
264
+
265
+ *DHH*
266
+
267
+
268
+ ## Rails 6.0.0.beta3 (March 11, 2019) ##
269
+
270
+ * No changes.
271
+
272
+
273
+ ## Rails 6.0.0.beta2 (February 25, 2019) ##
274
+
275
+ * New autoloading based on [Zeitwerk](https://github.com/fxn/zeitwerk).
276
+
277
+ *Xavier Noria*
278
+
279
+ * Revise `ActiveSupport::Notifications.unsubscribe` to correctly handle Regex or other multiple-pattern subscribers.
280
+
281
+ *Zach Kemp*
282
+
283
+ * Add `before_reset` callback to `CurrentAttributes` and define `after_reset` as an alias of `resets` for symmetry.
284
+
285
+ *Rosa Gutierrez*
286
+
287
+ * Remove the `` Kernel#` `` override that suppresses ENOENT and accidentally returns nil on Unix systems.
292
288
 
293
- * `IO#to_json` now returns the `to_s` representation, rather than
294
- attempting to convert to an array. This fixes a bug where `IO#to_json`
295
- would raise an `IOError` when called on an unreadable object.
289
+ *Akinori Musha*
296
290
 
297
- Fixes #26132.
291
+ * Add `ActiveSupport::HashWithIndifferentAccess#assoc`.
298
292
 
299
- *Paul Kuruvilla*
293
+ `assoc` can now be called with either a string or a symbol.
300
294
 
301
- * Remove deprecated `halt_callback_chains_on_return_false` option.
295
+ *Stefan Schüßler*
296
+
297
+ * Add `Hash#deep_transform_values`, and `Hash#deep_transform_values!`.
298
+
299
+ *Guillermo Iguaran*
300
+
301
+
302
+ ## Rails 6.0.0.beta1 (January 18, 2019) ##
303
+
304
+ * Remove deprecated `Module#reachable?` method.
302
305
 
303
306
  *Rafael Mendonça França*
304
307
 
305
- * Remove deprecated `:if` and `:unless` string filter for callbacks.
308
+ * Remove deprecated `#acronym_regex` method from `Inflections`.
306
309
 
307
310
  *Rafael Mendonça França*
308
311
 
309
- * `Hash#slice` now falls back to Ruby 2.5+'s built-in definition if defined.
312
+ * Fix `String#safe_constantize` throwing a `LoadError` for incorrectly cased constant references.
310
313
 
311
- *Akira Matsuda*
314
+ *Keenan Brock*
312
315
 
313
- * Deprecate `secrets.secret_token`.
316
+ * Preserve key order passed to `ActiveSupport::CacheStore#fetch_multi`.
314
317
 
315
- The architecture for secrets had a big upgrade between Rails 3 and Rails 4,
316
- when the default changed from using `secret_token` to `secret_key_base`.
318
+ `fetch_multi(*names)` now returns its results in the same order as the `*names` requested, rather than returning cache hits followed by cache misses.
317
319
 
318
- `secret_token` has been soft deprecated in documentation for four years
319
- but is still in place to support apps created before Rails 4.
320
- Deprecation warnings have been added to help developers upgrade their
321
- applications to `secret_key_base`.
320
+ *Gannon McGibbon*
322
321
 
323
- *claudiob*, *Kasper Timm Hansen*
322
+ * If the same block is `included` multiple times for a Concern, an exception is no longer raised.
324
323
 
325
- * Return an instance of `HashWithIndifferentAccess` from `HashWithIndifferentAccess#transform_keys`.
324
+ *Mark J. Titorenko*, *Vlad Bokov*
326
325
 
327
- *Yuji Yaginuma*
326
+ * Fix bug where `#to_options` for `ActiveSupport::HashWithIndifferentAccess`
327
+ would not act as alias for `#symbolize_keys`.
328
328
 
329
- * Add key rotation support to `MessageEncryptor` and `MessageVerifier`.
329
+ *Nick Weiland*
330
330
 
331
- This change introduces a `rotate` method to both the `MessageEncryptor` and
332
- `MessageVerifier` classes. This method accepts the same arguments and
333
- options as the given classes' constructor. The `encrypt_and_verify` method
334
- for `MessageEncryptor` and the `verified` method for `MessageVerifier` also
335
- accept an optional keyword argument `:on_rotation` block which is called
336
- when a rotated instance is used to decrypt or verify the message.
331
+ * Improve the logic that detects non-autoloaded constants.
337
332
 
338
- *Michael J Coyne*
333
+ *Jan Habermann*, *Xavier Noria*
339
334
 
340
- * Deprecate `Module#reachable?` method.
335
+ * Deprecate `ActiveSupport::Multibyte::Unicode#pack_graphemes(array)` and `ActiveSuppport::Multibyte::Unicode#unpack_graphemes(string)`
336
+ in favor of `array.flatten.pack("U*")` and `string.scan(/\X/).map(&:codepoints)`, respectively.
341
337
 
342
- *bogdanvlviv*
338
+ *Francesco Rodríguez*
343
339
 
344
- * Add `config/credentials.yml.enc` to store production app secrets.
340
+ * Deprecate `ActiveSupport::Multibyte::Chars.consumes?` in favor of `String#is_utf8?`.
345
341
 
346
- Allows saving any authentication credentials for third party services
347
- directly in repo encrypted with `config/master.key` or `ENV["RAILS_MASTER_KEY"]`.
342
+ *Francesco Rodríguez*
348
343
 
349
- This will eventually replace `Rails.application.secrets` and the encrypted
350
- secrets introduced in Rails 5.1.
344
+ * Fix duration being rounded to a full second.
345
+ ```
346
+ time = DateTime.parse("2018-1-1")
347
+ time += 0.51.seconds
348
+ ```
349
+ Will now correctly add 0.51 second and not 1 full second.
351
350
 
352
- *DHH*, *Kasper Timm Hansen*
351
+ *Edouard Chin*
353
352
 
354
- * Add `ActiveSupport::EncryptedFile` and `ActiveSupport::EncryptedConfiguration`.
353
+ * Deprecate `ActiveSupport::Multibyte::Unicode#normalize` and `ActiveSuppport::Multibyte::Chars#normalize`
354
+ in favor of `String#unicode_normalize`
355
355
 
356
- Allows for stashing encrypted files or configuration directly in repo by
357
- encrypting it with a key.
356
+ *Francesco Rodríguez*
358
357
 
359
- Backs the new credentials setup above, but can also be used independently.
358
+ * Deprecate `ActiveSupport::Multibyte::Unicode#downcase/upcase/swapcase` in favor of
359
+ `String#downcase/upcase/swapcase`.
360
360
 
361
- *DHH*, *Kasper Timm Hansen*
361
+ *Francesco Rodríguez*
362
362
 
363
- * `Module#delegate_missing_to` now raises `DelegationError` if target is nil,
364
- similar to `Module#delegate`.
363
+ * Add `ActiveSupport::ParameterFilter`.
365
364
 
366
- *Anton Khamets*
365
+ *Yoshiyuki Kinjo*
367
366
 
368
- * Update `String#camelize` to provide feedback when wrong option is passed.
367
+ * Rename `Module#parent`, `Module#parents`, and `Module#parent_name` to
368
+ `module_parent`, `module_parents`, and `module_parent_name`.
369
369
 
370
- `String#camelize` was returning nil without any feedback when an
371
- invalid option was passed as a parameter.
370
+ *Gannon McGibbon*
372
371
 
373
- Previously:
372
+ * Deprecate the use of `LoggerSilence` in favor of `ActiveSupport::LoggerSilence`
374
373
 
375
- 'one_two'.camelize(true)
376
- # => nil
374
+ *Edouard Chin*
377
375
 
378
- Now:
376
+ * Deprecate using negative limits in `String#first` and `String#last`.
379
377
 
380
- 'one_two'.camelize(true)
381
- # => ArgumentError: Invalid option, use either :upper or :lower.
378
+ *Gannon McGibbon*, *Eric Turner*
382
379
 
383
- *Ricardo Díaz*
380
+ * Fix bug where `#without` for `ActiveSupport::HashWithIndifferentAccess` would fail
381
+ with symbol arguments
384
382
 
385
- * Fix modulo operations involving durations.
383
+ *Abraham Chan*
386
384
 
387
- Rails 5.1 introduced `ActiveSupport::Duration::Scalar` as a wrapper
388
- around numeric values as a way of ensuring a duration was the outcome of
389
- an expression. However, the implementation was missing support for modulo
390
- operations. This support has now been added and should result in a duration
391
- being returned from expressions involving modulo operations.
385
+ * Treat `#delete_prefix`, `#delete_suffix` and `#unicode_normalize` results as non-`html_safe`.
386
+ Ensure safety of arguments for `#insert`, `#[]=` and `#replace` calls on `html_safe` Strings.
392
387
 
393
- Prior to Rails 5.1:
388
+ *Janosch Müller*
394
389
 
395
- 5.minutes % 2.minutes
396
- # => 60
390
+ * Changed `ActiveSupport::TaggedLogging.new` to return a new logger instance instead
391
+ of mutating the one received as parameter.
397
392
 
398
- Now:
393
+ *Thierry Joyal*
399
394
 
400
- 5.minutes % 2.minutes
401
- # => 1 minute
395
+ * Define `unfreeze_time` as an alias of `travel_back` in `ActiveSupport::Testing::TimeHelpers`.
402
396
 
403
- Fixes #29603 and #29743.
397
+ The alias is provided for symmetry with `freeze_time`.
404
398
 
405
- *Sayan Chakraborty*, *Andrew White*
399
+ *Ryan Davidson*
406
400
 
407
- * Fix division where a duration is the denominator.
401
+ * Add support for tracing constant autoloads. Just throw
408
402
 
409
- PR #29163 introduced a change in behavior when a duration was the denominator
410
- in a calculation - this was incorrect as dividing by a duration should always
411
- return a `Numeric`. The behavior of previous versions of Rails has been restored.
403
+ ActiveSupport::Dependencies.logger = Rails.logger
404
+ ActiveSupport::Dependencies.verbose = true
412
405
 
413
- Fixes #29592.
406
+ in an initializer.
414
407
 
415
- *Andrew White*
408
+ *Xavier Noria*
416
409
 
417
- * Add purpose and expiry support to `ActiveSupport::MessageVerifier` and
418
- `ActiveSupport::MessageEncryptor`.
410
+ * Maintain `html_safe?` on html_safe strings when sliced.
419
411
 
420
- For instance, to ensure a message is only usable for one intended purpose:
412
+ string = "<div>test</div>".html_safe
413
+ string[-1..1].html_safe? # => true
421
414
 
422
- token = @verifier.generate("x", purpose: :shipping)
415
+ *Elom Gomez*, *Yumin Wong*
423
416
 
424
- @verifier.verified(token, purpose: :shipping) # => "x"
425
- @verifier.verified(token) # => nil
417
+ * Add `Array#extract!`.
426
418
 
427
- Or make it expire after a set time:
419
+ The method removes and returns the elements for which the block returns a true value.
420
+ If no block is given, an Enumerator is returned instead.
428
421
 
429
- @verifier.generate("x", expires_in: 1.month)
430
- @verifier.generate("y", expires_at: Time.now.end_of_year)
422
+ numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
423
+ odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
424
+ numbers # => [0, 2, 4, 6, 8]
431
425
 
432
- Showcased with `ActiveSupport::MessageVerifier`, but works the same for
433
- `ActiveSupport::MessageEncryptor`'s `encrypt_and_sign` and `decrypt_and_verify`.
426
+ *bogdanvlviv*
434
427
 
435
- Pull requests: #29599, #29854
428
+ * Support not to cache `nil` for `ActiveSupport::Cache#fetch`.
436
429
 
437
- *Assain Jaleel*
430
+ cache.fetch('bar', skip_nil: true) { nil }
431
+ cache.exist?('bar') # => false
438
432
 
439
- * Make the order of `Hash#reverse_merge!` consistent with `HashWithIndifferentAccess`.
433
+ *Martin Hong*
440
434
 
441
- *Erol Fornoles*
435
+ * Add "event object" support to the notification system.
436
+ Before this change, end users were forced to create hand made artisanal
437
+ event objects on their own, like this:
442
438
 
443
- * Add `freeze_time` helper which freezes time to `Time.now` in tests.
439
+ ActiveSupport::Notifications.subscribe('wait') do |*args|
440
+ @event = ActiveSupport::Notifications::Event.new(*args)
441
+ end
444
442
 
445
- *Prathamesh Sonpatki*
443
+ ActiveSupport::Notifications.instrument('wait') do
444
+ sleep 1
445
+ end
446
446
 
447
- * Default `ActiveSupport::MessageEncryptor` to use AES 256 GCM encryption.
447
+ @event.duration # => 1000.138
448
448
 
449
- On for new Rails 5.2 apps. Upgrading apps can find the config as a new
450
- framework default.
449
+ After this change, if the block passed to `subscribe` only takes one
450
+ parameter, the framework will yield an event object to the block. Now
451
+ end users are no longer required to make their own:
451
452
 
452
- *Assain Jaleel*
453
+ ActiveSupport::Notifications.subscribe('wait') do |event|
454
+ @event = event
455
+ end
453
456
 
454
- * Cache: `write_multi`.
457
+ ActiveSupport::Notifications.instrument('wait') do
458
+ sleep 1
459
+ end
455
460
 
456
- Rails.cache.write_multi foo: 'bar', baz: 'qux'
461
+ p @event.allocations # => 7
462
+ p @event.cpu_time # => 0.256
463
+ p @event.idle_time # => 1003.2399
457
464
 
458
- Plus faster fetch_multi with stores that implement `write_multi_entries`.
459
- Keys that aren't found may be written to the cache store in one shot
460
- instead of separate writes.
465
+ Now you can enjoy event objects without making them yourself. Neat!
461
466
 
462
- The default implementation simply calls `write_entry` for each entry.
463
- Stores may override if they're capable of one-shot bulk writes, like
464
- Redis `MSET`.
467
+ *Aaron "t.lo" Patterson*
465
468
 
466
- *Jeremy Daer*
469
+ * Add cpu_time, idle_time, and allocations to Event.
467
470
 
468
- * Add default option to module and class attribute accessors.
471
+ *Eileen M. Uchitelle*, *Aaron Patterson*
469
472
 
470
- mattr_accessor :settings, default: {}
473
+ * RedisCacheStore: support key expiry in increment/decrement.
471
474
 
472
- Works for `mattr_reader`, `mattr_writer`, `cattr_accessor`, `cattr_reader`,
473
- and `cattr_writer` as well.
475
+ Pass `:expires_in` to `#increment` and `#decrement` to set a Redis EXPIRE on the key.
474
476
 
475
- *Genadi Samokovarov*
477
+ If the key is already set to expire, RedisCacheStore won't extend its expiry.
476
478
 
477
- * Add `Date#prev_occurring` and `Date#next_occurring` to return specified next/previous occurring day of week.
479
+ Rails.cache.increment("some_key", 1, expires_in: 2.minutes)
478
480
 
479
- *Shota Iguchi*
481
+ *Jason Lee*
480
482
 
481
- * Add default option to `class_attribute`.
483
+ * Allow `Range#===` and `Range#cover?` on Range.
482
484
 
483
- Before:
485
+ `Range#cover?` can now accept a range argument like `Range#include?` and
486
+ `Range#===`. `Range#===` works correctly on Ruby 2.6. `Range#include?` is moved
487
+ into a new file, with these two methods.
484
488
 
485
- class_attribute :settings
486
- self.settings = {}
489
+ *Requiring active_support/core_ext/range/include_range is now deprecated.*
490
+ *Use `require "active_support/core_ext/range/compare_range"` instead.*
487
491
 
488
- Now:
492
+ *utilum*
489
493
 
490
- class_attribute :settings, default: {}
494
+ * Add `index_with` to Enumerable.
491
495
 
492
- *DHH*
496
+ Allows creating a hash from an enumerable with the value from a passed block
497
+ or a default argument.
493
498
 
494
- * `#singularize` and `#pluralize` now respect uncountables for the specified locale.
499
+ %i( title body ).index_with { |attr| post.public_send(attr) }
500
+ # => { title: "hey", body: "what's up?" }
495
501
 
496
- *Eilis Hamilton*
502
+ %i( title body ).index_with(nil)
503
+ # => { title: nil, body: nil }
497
504
 
498
- * Add `ActiveSupport::CurrentAttributes` to provide a thread-isolated attributes singleton.
499
- Primary use case is keeping all the per-request attributes easily available to the whole system.
505
+ Closely linked with `index_by`, which creates a hash where the keys are extracted from a block.
500
506
 
501
- *DHH*
507
+ *Kasper Timm Hansen*
502
508
 
503
- * Fix implicit coercion calculations with scalars and durations.
509
+ * Fix bug where `ActiveSupport::TimeZone.all` would fail when tzinfo data for
510
+ any timezone defined in `ActiveSupport::TimeZone::MAPPING` is missing.
504
511
 
505
- Previously, calculations where the scalar is first would be converted to a duration
506
- of seconds, but this causes issues with dates being converted to times, e.g:
512
+ *Dominik Sander*
513
+
514
+ * Redis cache store: `delete_matched` no longer blocks the Redis server.
515
+ (Switches from evaled Lua to a batched SCAN + DEL loop.)
516
+
517
+ *Gleb Mazovetskiy*
518
+
519
+ * Fix bug where `ActiveSupport::Cache` will massively inflate the storage
520
+ size when compression is enabled (which is true by default). This patch
521
+ does not attempt to repair existing data: please manually flush the cache
522
+ to clear out the problematic entries.
507
523
 
508
- Time.zone = "Beijing" # => Asia/Shanghai
509
- date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
510
- 2 * 1.day # => 172800 seconds
511
- date + 2 * 1.day # => Mon, 22 May 2017 00:00:00 CST +08:00
524
+ *Godfrey Chan*
512
525
 
513
- Now, the `ActiveSupport::Duration::Scalar` calculation methods will try to maintain
514
- the part structure of the duration where possible, e.g:
526
+ * Fix bug where `URI.unescape` would fail with mixed Unicode/escaped character input:
515
527
 
516
- Time.zone = "Beijing" # => Asia/Shanghai
517
- date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
518
- 2 * 1.day # => 2 days
519
- date + 2 * 1.day # => Mon, 22 May 2017
528
+ URI.unescape("\xe3\x83\x90") # => "バ"
529
+ URI.unescape("%E3%83%90") # => "バ"
530
+ URI.unescape("\xe3\x83\x90%E3%83%90") # => Encoding::CompatibilityError
520
531
 
521
- Fixes #29160, #28970.
532
+ *Ashe Connor*, *Aaron Patterson*
522
533
 
523
- *Andrew White*
534
+ * Add `before?` and `after?` methods to `Date`, `DateTime`,
535
+ `Time`, and `TimeWithZone`.
524
536
 
525
- * Add support for versioned cache entries. This enables the cache stores to recycle cache keys, greatly saving
526
- on storage in cases with frequent churn. Works together with the separation of `#cache_key` and `#cache_version`
527
- in Active Record and its use in Action Pack's fragment caching.
537
+ *Nick Holden*
528
538
 
529
- *DHH*
539
+ * `ActiveSupport::Inflector#ordinal` and `ActiveSupport::Inflector#ordinalize` now support
540
+ translations through I18n.
530
541
 
531
- * Pass gem name and deprecation horizon to deprecation notifications.
542
+ # locale/fr.rb
532
543
 
533
- *Willem van Bergen*
544
+ {
545
+ fr: {
546
+ number: {
547
+ nth: {
548
+ ordinals: lambda do |_key, number:, **_options|
549
+ if number.to_i.abs == 1
550
+ 'er'
551
+ else
552
+ 'e'
553
+ end
554
+ end,
534
555
 
535
- * Add support for `:offset` and `:zone` to `ActiveSupport::TimeWithZone#change`.
556
+ ordinalized: lambda do |_key, number:, **_options|
557
+ "#{number}#{ActiveSupport::Inflector.ordinal(number)}"
558
+ end
559
+ }
560
+ }
561
+ }
562
+ }
536
563
 
537
- *Andrew White*
538
564
 
539
- * Add support for `:offset` to `Time#change`.
565
+ *Christian Blais*
540
566
 
541
- Fixes #28723.
567
+ * Add `:private` option to ActiveSupport's `Module#delegate`
568
+ in order to delegate methods as private:
542
569
 
543
- *Andrew White*
570
+ class User < ActiveRecord::Base
571
+ has_one :profile
572
+ delegate :date_of_birth, to: :profile, private: true
573
+
574
+ def age
575
+ Date.today.year - date_of_birth.year
576
+ end
577
+ end
578
+
579
+ # User.new.age # => 29
580
+ # User.new.date_of_birth
581
+ # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>
582
+
583
+ *Tomas Valent*
584
+
585
+ * `String#truncate_bytes` to truncate a string to a maximum bytesize without
586
+ breaking multibyte characters or grapheme clusters like 👩‍👩‍👦‍👦.
587
+
588
+ *Jeremy Daer*
589
+
590
+ * `String#strip_heredoc` preserves frozenness.
591
+
592
+ "foo".freeze.strip_heredoc.frozen? # => true
593
+
594
+ Fixes that frozen string literals would inadvertently become unfrozen:
595
+
596
+ # frozen_string_literal: true
597
+
598
+ foo = <<-MSG.strip_heredoc
599
+ la la la
600
+ MSG
601
+
602
+ foo.frozen? # => false !??
603
+
604
+ *Jeremy Daer*
605
+
606
+ * Rails 6 requires Ruby 2.5.0 or newer.
607
+
608
+ *Jeremy Daer*, *Kasper Timm Hansen*
544
609
 
545
- * Add `fetch_values` for `HashWithIndifferentAccess`.
610
+ * Adds parallel testing to Rails.
546
611
 
547
- The method was originally added to `Hash` in Ruby 2.3.0.
612
+ Parallelize your test suite with forked processes or threads.
548
613
 
549
- *Josh Pencheon*
614
+ *Eileen M. Uchitelle*, *Aaron Patterson*
550
615
 
551
616
 
552
- Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activesupport/CHANGELOG.md) for previous changes.
617
+ Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activesupport/CHANGELOG.md) for previous changes.