activesupport 5.1.7 → 5.2.4.3

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +401 -541
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_support.rb +5 -13
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +2 -0
  8. data/lib/active_support/backtrace_cleaner.rb +2 -0
  9. data/lib/active_support/benchmarkable.rb +2 -0
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache.rb +197 -83
  12. data/lib/active_support/cache/file_store.rb +5 -4
  13. data/lib/active_support/cache/mem_cache_store.rb +39 -39
  14. data/lib/active_support/cache/memory_store.rb +2 -0
  15. data/lib/active_support/cache/null_store.rb +2 -0
  16. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +33 -2
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  19. data/lib/active_support/callbacks.rb +28 -39
  20. data/lib/active_support/concern.rb +10 -4
  21. data/lib/active_support/concurrency/share_lock.rb +2 -0
  22. data/lib/active_support/configurable.rb +2 -0
  23. data/lib/active_support/core_ext.rb +3 -1
  24. data/lib/active_support/core_ext/array.rb +2 -0
  25. data/lib/active_support/core_ext/array/access.rb +4 -2
  26. data/lib/active_support/core_ext/array/conversions.rb +2 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +2 -0
  29. data/lib/active_support/core_ext/array/inquiry.rb +2 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -2
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/benchmark.rb +2 -0
  33. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
  35. data/lib/active_support/core_ext/class.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +34 -16
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +1 -2
  39. data/lib/active_support/core_ext/date.rb +2 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  41. data/lib/active_support/core_ext/date/blank.rb +2 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +2 -0
  43. data/lib/active_support/core_ext/date/conversions.rb +10 -9
  44. data/lib/active_support/core_ext/date/zones.rb +2 -0
  45. data/lib/active_support/core_ext/date_and_time/calculations.rb +50 -16
  46. data/lib/active_support/core_ext/date_and_time/compatibility.rb +3 -1
  47. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -0
  48. data/lib/active_support/core_ext/date_time.rb +2 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +2 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +2 -0
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  53. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/digest/uuid.rb +3 -1
  56. data/lib/active_support/core_ext/enumerable.rb +8 -1
  57. data/lib/active_support/core_ext/file.rb +2 -0
  58. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  59. data/lib/active_support/core_ext/hash.rb +2 -0
  60. data/lib/active_support/core_ext/hash/compact.rb +2 -0
  61. data/lib/active_support/core_ext/hash/conversions.rb +4 -2
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  63. data/lib/active_support/core_ext/hash/except.rb +2 -0
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
  65. data/lib/active_support/core_ext/hash/keys.rb +2 -0
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +4 -4
  68. data/lib/active_support/core_ext/hash/transform_values.rb +2 -0
  69. data/lib/active_support/core_ext/integer.rb +2 -0
  70. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +7 -14
  73. data/lib/active_support/core_ext/kernel.rb +2 -0
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +2 -7
  79. data/lib/active_support/core_ext/marshal.rb +2 -0
  80. data/lib/active_support/core_ext/module.rb +3 -0
  81. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  82. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  83. data/lib/active_support/core_ext/module/attr_internal.rb +2 -0
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +21 -24
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +2 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +7 -8
  87. data/lib/active_support/core_ext/module/delegation.rb +31 -29
  88. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +2 -0
  90. data/lib/active_support/core_ext/module/reachable.rb +3 -0
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  93. data/lib/active_support/core_ext/name_error.rb +7 -0
  94. data/lib/active_support/core_ext/numeric.rb +2 -0
  95. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +9 -7
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  99. data/lib/active_support/core_ext/object.rb +2 -0
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +12 -1
  102. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  103. data/lib/active_support/core_ext/object/deep_dup.rb +2 -0
  104. data/lib/active_support/core_ext/object/duplicable.rb +10 -8
  105. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  106. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  107. data/lib/active_support/core_ext/object/json.rb +8 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  109. data/lib/active_support/core_ext/object/to_query.rb +2 -0
  110. data/lib/active_support/core_ext/object/try.rb +2 -0
  111. data/lib/active_support/core_ext/object/with_options.rb +3 -1
  112. data/lib/active_support/core_ext/range.rb +4 -1
  113. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +9 -1
  115. data/lib/active_support/core_ext/range/each.rb +5 -1
  116. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/regexp.rb +2 -0
  120. data/lib/active_support/core_ext/securerandom.rb +2 -0
  121. data/lib/active_support/core_ext/string.rb +2 -0
  122. data/lib/active_support/core_ext/string/access.rb +2 -0
  123. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  124. data/lib/active_support/core_ext/string/conversions.rb +2 -0
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +2 -0
  127. data/lib/active_support/core_ext/string/indent.rb +2 -0
  128. data/lib/active_support/core_ext/string/inflections.rb +26 -12
  129. data/lib/active_support/core_ext/string/inquiry.rb +2 -0
  130. data/lib/active_support/core_ext/string/multibyte.rb +4 -0
  131. data/lib/active_support/core_ext/string/output_safety.rb +6 -7
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +2 -0
  134. data/lib/active_support/core_ext/string/zones.rb +2 -0
  135. data/lib/active_support/core_ext/time.rb +2 -0
  136. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  137. data/lib/active_support/core_ext/time/calculations.rb +23 -15
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  140. data/lib/active_support/core_ext/time/zones.rb +6 -4
  141. data/lib/active_support/core_ext/uri.rb +6 -6
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies.rb +25 -26
  144. data/lib/active_support/dependencies/autoload.rb +2 -0
  145. data/lib/active_support/dependencies/interlock.rb +2 -0
  146. data/lib/active_support/deprecation.rb +4 -2
  147. data/lib/active_support/deprecation/behaviors.rb +28 -9
  148. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  149. data/lib/active_support/deprecation/instance_delegator.rb +2 -0
  150. data/lib/active_support/deprecation/method_wrappers.rb +30 -17
  151. data/lib/active_support/deprecation/proxy_wrappers.rb +5 -2
  152. data/lib/active_support/deprecation/reporting.rb +5 -3
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  155. data/lib/active_support/duration.rb +11 -7
  156. data/lib/active_support/duration/iso8601_parser.rb +4 -2
  157. data/lib/active_support/duration/iso8601_serializer.rb +4 -2
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +2 -0
  161. data/lib/active_support/execution_wrapper.rb +2 -0
  162. data/lib/active_support/executor.rb +2 -0
  163. data/lib/active_support/file_update_checker.rb +2 -0
  164. data/lib/active_support/gem_version.rb +5 -3
  165. data/lib/active_support/gzip.rb +2 -0
  166. data/lib/active_support/hash_with_indifferent_access.rb +55 -1
  167. data/lib/active_support/i18n.rb +3 -1
  168. data/lib/active_support/i18n_railtie.rb +4 -6
  169. data/lib/active_support/inflections.rb +2 -0
  170. data/lib/active_support/inflector.rb +2 -0
  171. data/lib/active_support/inflector/inflections.rb +20 -4
  172. data/lib/active_support/inflector/methods.rb +43 -24
  173. data/lib/active_support/inflector/transliterate.rb +17 -8
  174. data/lib/active_support/json.rb +2 -0
  175. data/lib/active_support/json/decoding.rb +2 -0
  176. data/lib/active_support/json/encoding.rb +2 -0
  177. data/lib/active_support/key_generator.rb +3 -1
  178. data/lib/active_support/lazy_load_hooks.rb +2 -0
  179. data/lib/active_support/log_subscriber.rb +3 -2
  180. data/lib/active_support/log_subscriber/test_helper.rb +2 -0
  181. data/lib/active_support/logger.rb +2 -0
  182. data/lib/active_support/logger_silence.rb +3 -2
  183. data/lib/active_support/logger_thread_safe_level.rb +4 -1
  184. data/lib/active_support/message_encryptor.rb +95 -22
  185. data/lib/active_support/message_verifier.rb +78 -7
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +2 -0
  190. data/lib/active_support/multibyte/chars.rb +2 -0
  191. data/lib/active_support/multibyte/unicode.rb +4 -2
  192. data/lib/active_support/notifications.rb +2 -0
  193. data/lib/active_support/notifications/fanout.rb +4 -2
  194. data/lib/active_support/notifications/instrumenter.rb +2 -0
  195. data/lib/active_support/number_helper.rb +2 -0
  196. data/lib/active_support/number_helper/number_converter.rb +2 -0
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -0
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +2 -0
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +2 -0
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -0
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +2 -0
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -1
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -20
  204. data/lib/active_support/number_helper/rounding_helper.rb +6 -4
  205. data/lib/active_support/option_merger.rb +2 -0
  206. data/lib/active_support/ordered_hash.rb +2 -0
  207. data/lib/active_support/ordered_options.rb +5 -3
  208. data/lib/active_support/per_thread_registry.rb +2 -0
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +2 -0
  211. data/lib/active_support/railtie.rb +37 -8
  212. data/lib/active_support/reloader.rb +7 -5
  213. data/lib/active_support/rescuable.rb +3 -2
  214. data/lib/active_support/security_utils.rb +15 -11
  215. data/lib/active_support/string_inquirer.rb +2 -0
  216. data/lib/active_support/subscriber.rb +8 -2
  217. data/lib/active_support/tagged_logging.rb +2 -0
  218. data/lib/active_support/test_case.rb +3 -2
  219. data/lib/active_support/testing/assertions.rb +31 -14
  220. data/lib/active_support/testing/autorun.rb +2 -0
  221. data/lib/active_support/testing/constant_lookup.rb +2 -0
  222. data/lib/active_support/testing/declarative.rb +2 -0
  223. data/lib/active_support/testing/deprecation.rb +2 -0
  224. data/lib/active_support/testing/file_fixtures.rb +2 -0
  225. data/lib/active_support/testing/isolation.rb +3 -1
  226. data/lib/active_support/testing/method_call_assertions.rb +2 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  228. data/lib/active_support/testing/stream.rb +2 -0
  229. data/lib/active_support/testing/tagged_logging.rb +2 -0
  230. data/lib/active_support/testing/time_helpers.rb +33 -3
  231. data/lib/active_support/time.rb +2 -0
  232. data/lib/active_support/time_with_zone.rb +38 -0
  233. data/lib/active_support/values/time_zone.rb +20 -8
  234. data/lib/active_support/version.rb +2 -0
  235. data/lib/active_support/xml_mini.rb +4 -2
  236. data/lib/active_support/xml_mini/jdom.rb +4 -2
  237. data/lib/active_support/xml_mini/libxml.rb +3 -1
  238. data/lib/active_support/xml_mini/libxmlsax.rb +4 -2
  239. data/lib/active_support/xml_mini/nokogiri.rb +3 -1
  240. data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
  241. data/lib/active_support/xml_mini/rexml.rb +3 -1
  242. metadata +17 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ece0ba787f6df68f2378c0e387d18f2a56a00359a4885e0d155ba9e57811caa
4
- data.tar.gz: 4fc1a1e4b58d382f0fd49539f28707234d7828c46a79c9bca397c1d327ca25b4
3
+ metadata.gz: 52200cba1081f52ab46b0fbb797549ec4f37ec724232511041c17279af00c23a
4
+ data.tar.gz: 8f67df12d04d8a83698d73ba5c961058156000fc77f344f2c10bbdc0bb5d1bd3
5
5
  SHA512:
6
- metadata.gz: 78703452ca309f7344f0e8d544bbe093147dba9cbd09917ed4aa72f2e1121ff3cf1835cd062a169d680dd2d7457d892a771d2947f7ce9b1729199a48dd745947
7
- data.tar.gz: ac4bdb64bfd7815044ec53ccd8008f6c62733c525437069d466a33f1af0d0566ded8017daa872269d4921bf777f67662edb0043d68dee271e0defe25b3c42ec7
6
+ metadata.gz: cb196f7b65d12c1a5be5178772fc9f449dd6408614bfa3020862e18ba32ed163597f4647202fdb792ab38a451dc04e5846072dc948e2a83505b2c7ccac4ee2d0
7
+ data.tar.gz: cfdf86850d1f2a9529d135756a23861b3bbb23c063b1446cbc994fb2372dfb2f79217eda99b0dc021d5cbfbd4f75f79a6e5385531f5dd48f1e78a1e55298459a
@@ -1,788 +1,648 @@
1
- ## Rails 5.1.7 (March 27, 2019) ##
1
+ ## Rails 5.2.4.3 (May 18, 2020) ##
2
2
 
3
- * No changes.
3
+ * [CVE-2020-8165] Deprecate Marshal.load on raw cache read in RedisCacheStore
4
4
 
5
+ * [CVE-2020-8165] Avoid Marshal.load on raw cache value in MemCacheStore
5
6
 
6
- ## Rails 5.1.6.2 (March 11, 2019) ##
7
+ ## Rails 5.2.4.1 (December 18, 2019) ##
7
8
 
8
9
  * No changes.
9
10
 
10
11
 
11
- ## Rails 5.1.6.1 (November 27, 2018) ##
12
+ ## Rails 5.2.4 (November 27, 2019) ##
12
13
 
13
- * No changes.
14
+ * Make ActiveSupport::Logger Fiber-safe. Fixes #36752.
14
15
 
16
+ Use `Fiber.current.__id__` in `ActiveSupport::Logger#local_level=` in order
17
+ to make log level local to Ruby Fibers in addition to Threads.
15
18
 
16
- ## Rails 5.1.6 (March 29, 2018) ##
19
+ Example:
17
20
 
18
- * Return all mappings for a timezone identifier in `country_zones`
21
+ logger = ActiveSupport::Logger.new(STDOUT)
22
+ logger.level = 1
23
+ p "Main is debug? #{logger.debug?}"
19
24
 
20
- Some timezones like `Europe/London` have multiple mappings in
21
- `ActiveSupport::TimeZone::MAPPING` so return all of them instead
22
- of the first one found by using `Hash#value`. e.g:
25
+ Fiber.new {
26
+ logger.local_level = 0
27
+ p "Thread is debug? #{logger.debug?}"
28
+ }.resume
23
29
 
24
- # Before
25
- ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh"]
30
+ p "Main is debug? #{logger.debug?}"
26
31
 
27
- # After
28
- ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh", "London"]
32
+ Before:
29
33
 
30
- Fixes #31668.
34
+ Main is debug? false
35
+ Thread is debug? true
36
+ Main is debug? true
31
37
 
32
- *Andrew White*
38
+ After:
33
39
 
40
+ Main is debug? false
41
+ Thread is debug? true
42
+ Main is debug? false
34
43
 
35
- ## Rails 5.1.5 (February 14, 2018) ##
44
+ *Alexander Varnin*
36
45
 
37
- * No changes.
38
46
 
47
+ ## Rails 5.2.3 (March 27, 2019) ##
39
48
 
40
- ## Rails 5.1.4 (September 07, 2017) ##
49
+ * Add `ActiveSupport::HashWithIndifferentAccess#assoc`.
41
50
 
42
- * No changes.
51
+ `assoc` can now be called with either a string or a symbol.
43
52
 
53
+ *Stefan Schüßler*
44
54
 
45
- ## Rails 5.1.4.rc1 (August 24, 2017) ##
55
+ * Fix `String#safe_constantize` throwing a `LoadError` for incorrectly cased constant references.
46
56
 
47
- * No changes.
57
+ *Keenan Brock*
48
58
 
59
+ * Allow Range#=== and Range#cover? on Range
49
60
 
50
- ## Rails 5.1.3 (August 03, 2017) ##
61
+ `Range#cover?` can now accept a range argument like `Range#include?` and
62
+ `Range#===`. `Range#===` works correctly on Ruby 2.6. `Range#include?` is moved
63
+ into a new file, with these two methods.
51
64
 
52
- * No changes.
65
+ *utilum*
53
66
 
67
+ * If the same block is `included` multiple times for a Concern, an exception is no longer raised.
54
68
 
55
- ## Rails 5.1.3.rc3 (July 31, 2017) ##
69
+ *Mark J. Titorenko*, *Vlad Bokov*
56
70
 
57
- * Fix modulo operations involving durations
58
71
 
59
- Rails 5.1 introduce an `ActiveSupport::Duration::Scalar` class as a wrapper
60
- around a numeric value as a way of ensuring a duration was the outcome of
61
- an expression. However the implementation was missing support for modulo
62
- operations. This support has now been added and should result in a duration
63
- being returned from expressions involving modulo operations.
72
+ ## Rails 5.2.2.1 (March 11, 2019) ##
64
73
 
65
- Prior to Rails 5.1:
74
+ * No changes.
66
75
 
67
- 5.minutes % 2.minutes
68
- => 60
69
76
 
70
- Now:
77
+ ## Rails 5.2.2 (December 04, 2018) ##
71
78
 
72
- 5.minutes % 2.minutes
73
- => 1 minute
79
+ * Fix bug where `#to_options` for `ActiveSupport::HashWithIndifferentAccess`
80
+ would not act as alias for `#symbolize_keys`.
74
81
 
75
- Fixes #29603 and #29743.
82
+ *Nick Weiland*
76
83
 
77
- *Sayan Chakraborty*, *Andrew White*
84
+ * Improve the logic that detects non-autoloaded constants.
78
85
 
79
- * Fix division where a duration is the denominator
86
+ *Jan Habermann*, *Xavier Noria*
80
87
 
81
- PR #29163 introduced a change in behavior when a duration was the denominator
82
- in a calculation - this was incorrect as dividing by a duration should always
83
- return a `Numeric`. The behavior of previous versions of Rails has been restored.
88
+ * Fix bug where `URI.unescape` would fail with mixed Unicode/escaped character input:
84
89
 
85
- Fixes #29592.
90
+ URI.unescape("\xe3\x83\x90") # => "バ"
91
+ URI.unescape("%E3%83%90") # => "バ"
92
+ URI.unescape("\xe3\x83\x90%E3%83%90") # => Encoding::CompatibilityError
86
93
 
87
- *Andrew White*
94
+ *Ashe Connor*, *Aaron Patterson*
88
95
 
89
96
 
90
- ## Rails 5.1.3.rc2 (July 25, 2017) ##
97
+ ## Rails 5.2.1.1 (November 27, 2018) ##
91
98
 
92
99
  * No changes.
93
100
 
94
101
 
95
- ## Rails 5.1.3.rc1 (July 19, 2017) ##
102
+ ## Rails 5.2.1 (August 07, 2018) ##
96
103
 
97
- * No changes.
104
+ * Redis cache store: `delete_matched` no longer blocks the Redis server.
105
+ (Switches from evaled Lua to a batched SCAN + DEL loop.)
98
106
 
107
+ *Gleb Mazovetskiy*
99
108
 
100
- ## Rails 5.1.2 (June 26, 2017) ##
109
+ * Fix bug where `ActiveSupport::Timezone.all` would fail when tzinfo data for
110
+ any timezone defined in `ActiveSupport::TimeZone::MAPPING` is missing.
101
111
 
102
- * Cache: Restore the `options = nil` argument for `LocalStore#clear`
103
- that was removed in 5.1.0. Restores compatibility with backends that
104
- take an options argument and use the local cache strategy.
112
+ *Dominik Sander*
105
113
 
106
- *Jeremy Daer*
114
+ * Fix bug where `ActiveSupport::Cache` will massively inflate the storage
115
+ size when compression is enabled (which is true by default). This patch
116
+ does not attempt to repair existing data: please manually flush the cache
117
+ to clear out the problematic entries.
107
118
 
108
- * Fix implicit coercion calculations with scalars and durations
119
+ *Godfrey Chan*
109
120
 
110
- Previously calculations where the scalar is first would be converted to a duration
111
- of seconds but this causes issues with dates being converted to times, e.g:
121
+ * Fix `ActiveSupport::Cache#read_multi` bug with local cache enabled that was
122
+ returning instances of `ActiveSupport::Cache::Entry` instead of the raw values.
112
123
 
113
- Time.zone = "Beijing" # => Asia/Shanghai
114
- date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
115
- 2 * 1.day # => 172800 seconds
116
- date + 2 * 1.day # => Mon, 22 May 2017 00:00:00 CST +08:00
124
+ *Jason Lee*
117
125
 
118
- Now the `ActiveSupport::Duration::Scalar` calculation methods will try to maintain
119
- the part structure of the duration where possible, e.g:
120
126
 
121
- Time.zone = "Beijing" # => Asia/Shanghai
122
- date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
123
- 2 * 1.day # => 2 days
124
- date + 2 * 1.day # => Mon, 22 May 2017
127
+ ## Rails 5.2.0 (April 09, 2018) ##
125
128
 
126
- Fixes #29160, #28970.
129
+ * Caching: MemCache and Redis `read_multi` and `fetch_multi` speedup.
130
+ Read from the local in-memory cache before consulting the backend.
127
131
 
128
- *Andrew White*
132
+ *Gabriel Sobrinho*
129
133
 
134
+ * Return all mappings for a timezone identifier in `country_zones`.
130
135
 
131
- ## Rails 5.1.1 (May 12, 2017) ##
132
-
133
- * No changes.
134
-
135
-
136
- ## Rails 5.1.0 (April 27, 2017) ##
137
-
138
- * `ActiveSupport::EventedFileUpdateChecker` no longer listens to
139
- directories outside of the application directory.
140
-
141
- *radiospiel*
136
+ Some timezones like `Europe/London` have multiple mappings in
137
+ `ActiveSupport::TimeZone::MAPPING` so return all of them instead
138
+ of the first one found by using `Hash#value`. e.g:
142
139
 
143
- * Return unmapped timezones from `country_zones`
140
+ # Before
141
+ ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh"]
144
142
 
145
- If a country doesn't exist in the MAPPINGS hash then create a new
146
- `ActiveSupport::Timezone` instance using the supplied timezone id.
143
+ # After
144
+ ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh", "London"]
147
145
 
148
- Fixes #28431.
146
+ Fixes #31668.
149
147
 
150
148
  *Andrew White*
151
149
 
152
- * Add ActiveSupport::Deprecation::DeprecatedConstantAccessor
150
+ * Add support for connection pooling on RedisCacheStore.
153
151
 
154
- Provides transparent deprecation of constants, compatible with exceptions.
155
- Example usage:
152
+ *fatkodima*
156
153
 
157
- module Example
158
- include ActiveSupport::Deprecation::DeprecatedConstantAccessor
159
- deprecate_constant 'OldException', 'Elsewhere::NewException'
160
- end
154
+ * Support hash as first argument in `assert_difference`. This allows to specify multiple
155
+ numeric differences in the same assertion.
161
156
 
162
- *Dominic Cleal*
157
+ assert_difference ->{ Article.count } => 1, ->{ Post.count } => 2
163
158
 
164
- * Fixed bug in `DateAndTime::Compatibility#to_time` that caused it to
165
- raise `RuntimeError: can't modify frozen Time` when called on any frozen `Time`.
166
- Properly pass through the frozen `Time` or `ActiveSupport::TimeWithZone` object
167
- when calling `#to_time`.
159
+ *Julien Meichelbeck*
168
160
 
169
- *Kevin McPhillips* & *Andrew White*
161
+ * Add missing instrumentation for `read_multi` in `ActiveSupport::Cache::Store`.
170
162
 
171
- * Remove implicit coercion deprecation of durations
163
+ *Ignatius Reza Lesmana*
172
164
 
173
- In #28204 we deprecated implicit conversion of durations to a numeric which
174
- represented the number of seconds in the duration because of unwanted side
175
- effects with calculations on durations and dates. This unfortunately had
176
- the side effect of forcing a explicit cast when configuring third-party
177
- libraries like expiration in Redis, e.g:
165
+ * `assert_changes` will always assert that the expression changes,
166
+ regardless of `from:` and `to:` argument combinations.
178
167
 
179
- redis.expire("foo", 5.minutes)
168
+ *Daniel Ma*
180
169
 
181
- To work around this we've removed the deprecation and added a private class
182
- that wraps the numeric and can perform calculation involving durations and
183
- ensure that they remain a duration irrespective of the order of operations.
170
+ * Use SHA-1 to generate non-sensitive digests, such as the ETag header.
184
171
 
185
- *Andrew White*
186
-
187
- * Update `titleize` regex to allow apostrophes
172
+ Enabled by default for new apps; upgrading apps can opt in by setting
173
+ `config.active_support.use_sha1_digests = true`.
188
174
 
189
- In 4b685aa the regex in `titleize` was updated to not match apostrophes to
190
- better reflect the nature of the transformation. Unfortunately, this had the
191
- side effect of breaking capitalization on the first word of a sub-string, e.g:
175
+ *Dmitri Dolguikh*, *Eugene Kenny*
192
176
 
193
- >> "This was 'fake news'".titleize
194
- => "This Was 'fake News'"
177
+ * Changed default behaviour of `ActiveSupport::SecurityUtils.secure_compare`,
178
+ to make it not leak length information even for variable length string.
195
179
 
196
- This is fixed by extending the look-behind to also check for a word
197
- character on the other side of the apostrophe.
180
+ Renamed old `ActiveSupport::SecurityUtils.secure_compare` to `fixed_length_secure_compare`,
181
+ and started raising `ArgumentError` in case of length mismatch of passed strings.
198
182
 
199
- Fixes #28312.
183
+ *Vipul A M*
200
184
 
201
- *Andrew White*
185
+ * Make `ActiveSupport::TimeZone.all` return only time zones that are in
186
+ `ActiveSupport::TimeZone::MAPPING`.
202
187
 
203
- * Add `rfc3339` aliases to `xmlschema` for `Time` and `ActiveSupport::TimeWithZone`
188
+ Fixes #7245.
204
189
 
205
- For naming consistency when using the RFC 3339 profile of ISO 8601 in applications.
190
+ *Chris LaRose*
206
191
 
207
- *Andrew White*
192
+ * MemCacheStore: Support expiring counters.
208
193
 
209
- * Add `Time.rfc3339` parsing method
194
+ Pass `expires_in: [seconds]` to `#increment` and `#decrement` options
195
+ to set the Memcached TTL (time-to-live) if the counter doesn't exist.
196
+ If the counter exists, Memcached doesn't extend its expiry when it's
197
+ incremented or decremented.
210
198
 
211
- `Time.xmlschema` and consequently its alias `iso8601` accepts timestamps
212
- without a offset in contravention of the RFC 3339 standard. This method
213
- enforces that constraint and raises an `ArgumentError` if it doesn't.
199
+ ```
200
+ Rails.cache.increment("my_counter", 1, expires_in: 2.minutes)
201
+ ```
214
202
 
215
- *Andrew White*
203
+ *Takumasa Ochi*
216
204
 
217
- * Add `ActiveSupport::TimeZone.rfc3339` parsing method
205
+ * Handle `TZInfo::AmbiguousTime` errors.
218
206
 
219
- Previously, there was no way to get a RFC 3339 timestamp into a specific
220
- timezone without either using `parse` or chaining methods. The new method
221
- allows parsing directly into the timezone, e.g:
207
+ Make `ActiveSupport::TimeWithZone` match Ruby's handling of ambiguous
208
+ times by choosing the later period, e.g.
222
209
 
223
- >> Time.zone = "Hawaii"
224
- => "Hawaii"
225
- >> Time.zone.rfc3339("1999-12-31T14:00:00Z")
226
- => Fri, 31 Dec 1999 14:00:00 HST -10:00
210
+ Ruby:
211
+ ```
212
+ ENV["TZ"] = "Europe/Moscow"
213
+ Time.local(2014, 10, 26, 1, 0, 0) # => 2014-10-26 01:00:00 +0300
214
+ ```
227
215
 
228
- This new method has stricter semantics than the current `parse` method,
229
- and will raise an `ArgumentError` instead of returning nil, e.g:
230
-
231
- >> Time.zone = "Hawaii"
232
- => "Hawaii"
233
- >> Time.zone.rfc3339("foobar")
234
- ArgumentError: invalid date
235
- >> Time.zone.parse("foobar")
236
- => nil
216
+ Before:
217
+ ```
218
+ >> "2014-10-26 01:00:00".in_time_zone("Moscow")
219
+ TZInfo::AmbiguousTime: 26/10/2014 01:00 is an ambiguous local time.
220
+ ```
237
221
 
238
- It will also raise an `ArgumentError` when either the time or offset
239
- components are missing, e.g:
222
+ After:
223
+ ```
224
+ >> "2014-10-26 01:00:00".in_time_zone("Moscow")
225
+ => Sun, 26 Oct 2014 01:00:00 MSK +03:00
226
+ ```
240
227
 
241
- >> Time.zone = "Hawaii"
242
- => "Hawaii"
243
- >> Time.zone.rfc3339("1999-12-31")
244
- ArgumentError: invalid date
245
- >> Time.zone.rfc3339("1999-12-31T14:00:00")
246
- ArgumentError: invalid date
228
+ Fixes #17395.
247
229
 
248
230
  *Andrew White*
249
231
 
250
- * Add `ActiveSupport::TimeZone.iso8601` parsing method
232
+ * Redis cache store.
233
+
234
+ ```
235
+ # Defaults to `redis://localhost:6379/0`. Only use for dev/test.
236
+ config.cache_store = :redis_cache_store
237
+
238
+ # Supports all common cache store options (:namespace, :compress,
239
+ # :compress_threshold, :expires_in, :race_condition_ttl) and all
240
+ # Redis options.
241
+ cache_password = Rails.application.secrets.redis_cache_password
242
+ config.cache_store = :redis_cache_store, driver: :hiredis,
243
+ namespace: 'myapp-cache', compress: true, timeout: 1,
244
+ url: "redis://:#{cache_password}@myapp-cache-1:6379/0"
245
+
246
+ # Supports Redis::Distributed with multiple hosts
247
+ config.cache_store = :redis_cache_store, driver: :hiredis
248
+ namespace: 'myapp-cache', compress: true,
249
+ url: %w[
250
+ redis://myapp-cache-1:6379/0
251
+ redis://myapp-cache-1:6380/0
252
+ redis://myapp-cache-2:6379/0
253
+ redis://myapp-cache-2:6380/0
254
+ redis://myapp-cache-3:6379/0
255
+ redis://myapp-cache-3:6380/0
256
+ ]
257
+
258
+ # Or pass a builder block
259
+ config.cache_store = :redis_cache_store,
260
+ namespace: 'myapp-cache', compress: true,
261
+ redis: -> { Redis.new … }
262
+ ```
263
+
264
+ Deployment note: Take care to use a *dedicated Redis cache* rather
265
+ than pointing this at your existing Redis server. It won't cope well
266
+ with mixed usage patterns and it won't expire cache entries by default.
267
+
268
+ Redis cache server setup guide: https://redis.io/topics/lru-cache
251
269
 
252
- Previously, there was no way to get a ISO 8601 timestamp into a specific
253
- timezone without either using `parse` or chaining methods. The new method
254
- allows parsing directly into the timezone, e.g:
270
+ *Jeremy Daer*
255
271
 
256
- >> Time.zone = "Hawaii"
257
- => "Hawaii"
258
- >> Time.zone.iso8601("1999-12-31T14:00:00Z")
259
- => Fri, 31 Dec 1999 14:00:00 HST -10:00
272
+ * Cache: Enable compression by default for values > 1kB.
260
273
 
261
- If the timestamp is a ISO 8601 date (YYYY-MM-DD), then the time is set
262
- to midnight, e.g:
274
+ Compression has long been available, but opt-in and at a 16kB threshold.
275
+ It wasn't enabled by default due to CPU cost. Today it's cheap and typical
276
+ cache data is eminently compressible, such as HTML or JSON fragments.
277
+ Compression dramatically reduces Memcached/Redis mem usage, which means
278
+ the same cache servers can store more data, which means higher hit rates.
263
279
 
264
- >> Time.zone = "Hawaii"
265
- => "Hawaii"
266
- >> Time.zone.iso8601("1999-12-31")
267
- => Fri, 31 Dec 1999 00:00:00 HST -10:00
280
+ To disable compression, pass `compress: false` to the initializer.
268
281
 
269
- This new method has stricter semantics than the current `parse` method,
270
- and will raise an `ArgumentError` instead of returning nil, e.g:
282
+ *Jeremy Daer*
271
283
 
272
- >> Time.zone = "Hawaii"
273
- => "Hawaii"
274
- >> Time.zone.iso8601("foobar")
275
- ArgumentError: invalid date
276
- >> Time.zone.parse("foobar")
277
- => nil
284
+ * Allow `Range#include?` on TWZ ranges.
278
285
 
279
- *Andrew White*
286
+ In #11474 we prevented TWZ ranges being iterated over which matched
287
+ Ruby's handling of Time ranges and as a consequence `include?`
288
+ stopped working with both Time ranges and TWZ ranges. However in
289
+ ruby/ruby@b061634 support was added for `include?` to use `cover?`
290
+ for 'linear' objects. Since we have no way of making Ruby consider
291
+ TWZ instances as 'linear' we have to override `Range#include?`.
280
292
 
281
- * Deprecate implicit coercion of `ActiveSupport::Duration`
293
+ Fixes #30799.
282
294
 
283
- Currently `ActiveSupport::Duration` implicitly converts to a seconds
284
- value when used in a calculation except for the explicit examples of
285
- addition and subtraction where the duration is the receiver, e.g:
295
+ *Andrew White*
286
296
 
287
- >> 2 * 1.day
288
- => 172800
297
+ * Fix acronym support in `humanize`.
289
298
 
290
- This results in lots of confusion especially when using durations
291
- with dates because adding/subtracting a value from a date treats
292
- integers as a day and not a second, e.g:
299
+ Acronym inflections are stored with lowercase keys in the hash but
300
+ the match wasn't being lowercased before being looked up in the hash.
301
+ This shouldn't have any performance impact because before it would
302
+ fail to find the acronym and perform the `downcase` operation anyway.
293
303
 
294
- >> Date.today
295
- => Wed, 01 Mar 2017
296
- >> Date.today + 2 * 1.day
297
- => Mon, 10 Apr 2490
304
+ Fixes #31052.
298
305
 
299
- To fix this we're implementing `coerce` so that we can provide a
300
- deprecation warning with the intent of removing the implicit coercion
301
- in Rails 5.2, e.g:
306
+ *Andrew White*
302
307
 
303
- >> 2 * 1.day
304
- DEPRECATION WARNING: Implicit coercion of ActiveSupport::Duration
305
- to a Numeric is deprecated and will raise a TypeError in Rails 5.2.
306
- => 172800
308
+ * Add same method signature for `Time#prev_year` and `Time#next_year`
309
+ in accordance with `Date#prev_year`, `Date#next_year`.
307
310
 
308
- In Rails 5.2 it will raise `TypeError`, e.g:
311
+ Allows pass argument for `Time#prev_year` and `Time#next_year`.
309
312
 
310
- >> 2 * 1.day
311
- TypeError: ActiveSupport::Duration can't be coerced into Integer
313
+ Before:
314
+ ```
315
+ Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300
316
+ Time.new(2017, 9, 16, 17, 0).prev_year(1)
317
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
312
318
 
313
- This is the same behavior as with other types in Ruby, e.g:
319
+ Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300
320
+ Time.new(2017, 9, 16, 17, 0).next_year(1)
321
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
322
+ ```
314
323
 
315
- >> 2 * "foo"
316
- TypeError: String can't be coerced into Integer
317
- >> "foo" * 2
318
- => "foofoo"
324
+ After:
325
+ ```
326
+ Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300
327
+ Time.new(2017, 9, 16, 17, 0).prev_year(1) # => 2016-09-16 17:00:00 +0300
319
328
 
320
- As part of this deprecation add `*` and `/` methods to `AS::Duration`
321
- so that calculations that keep the duration as the receiver work
322
- correctly whether the final receiver is a `Date` or `Time`, e.g:
329
+ Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300
330
+ Time.new(2017, 9, 16, 17, 0).next_year(1) # => 2018-09-16 17:00:00 +0300
331
+ ```
323
332
 
324
- >> Date.today
325
- => Wed, 01 Mar 2017
326
- >> Date.today + 1.day * 2
327
- => Fri, 03 Mar 2017
333
+ *bogdanvlviv*
328
334
 
329
- Fixes #27457.
335
+ * Add same method signature for `Time#prev_month` and `Time#next_month`
336
+ in accordance with `Date#prev_month`, `Date#next_month`.
330
337
 
331
- *Andrew White*
338
+ Allows pass argument for `Time#prev_month` and `Time#next_month`.
332
339
 
333
- * Update `DateTime#change` to support `:usec` and `:nsec` options.
340
+ Before:
341
+ ```
342
+ Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300
343
+ Time.new(2017, 9, 16, 17, 0).prev_month(1)
344
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
334
345
 
335
- Adding support for these options now allows us to update the `DateTime#end_of`
336
- methods to match the equivalent `Time#end_of` methods, e.g:
346
+ Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300
347
+ Time.new(2017, 9, 16, 17, 0).next_month(1)
348
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
349
+ ```
337
350
 
338
- datetime = DateTime.now.end_of_day
339
- datetime.nsec == 999999999 # => true
351
+ After:
352
+ ```
353
+ Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300
354
+ Time.new(2017, 9, 16, 17, 0).prev_month(1) # => 2017-08-16 17:00:00 +0300
340
355
 
341
- Fixes #21424.
356
+ Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300
357
+ Time.new(2017, 9, 16, 17, 0).next_month(1) # => 2017-10-16 17:00:00 +0300
358
+ ```
342
359
 
343
- *Dan Moore*, *Andrew White*
360
+ *bogdanvlviv*
344
361
 
345
- * Add `ActiveSupport::Duration#before` and `#after` as aliases for `#until` and `#since`
362
+ * Add same method signature for `Time#prev_day` and `Time#next_day`
363
+ in accordance with `Date#prev_day`, `Date#next_day`.
346
364
 
347
- These read more like English and require less mental gymnastics to read and write.
365
+ Allows pass argument for `Time#prev_day` and `Time#next_day`.
348
366
 
349
367
  Before:
368
+ ```
369
+ Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300
370
+ Time.new(2017, 9, 16, 17, 0).prev_day(1)
371
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
350
372
 
351
- 2.weeks.since(customer_start_date)
352
- 5.days.until(today)
373
+ Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300
374
+ Time.new(2017, 9, 16, 17, 0).next_day(1)
375
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
376
+ ```
353
377
 
354
378
  After:
379
+ ```
380
+ Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300
381
+ Time.new(2017, 9, 16, 17, 0).prev_day(1) # => 2017-09-15 17:00:00 +0300
355
382
 
356
- 2.weeks.after(customer_start_date)
357
- 5.days.before(today)
358
-
359
- *Nick Johnstone*
360
-
361
- * Soft-deprecated the top-level `HashWithIndifferentAccess` constant.
362
- `ActiveSupport::HashWithIndifferentAccess` should be used instead.
363
-
364
- Fixes #28157.
365
-
366
- *Robin Dupret*
383
+ Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300
384
+ Time.new(2017, 9, 16, 17, 0).next_day(1) # => 2017-09-17 17:00:00 +0300
385
+ ```
367
386
 
368
- * In Core Extensions, make `MarshalWithAutoloading#load` pass through the second, optional
369
- argument for `Marshal#load( source [, proc] )`. This way we don't have to do
370
- `Marshal.method(:load).super_method.call(source, proc)` just to be able to pass a proc.
387
+ *bogdanvlviv*
371
388
 
372
- *Jeff Latz*
389
+ * `IO#to_json` now returns the `to_s` representation, rather than
390
+ attempting to convert to an array. This fixes a bug where `IO#to_json`
391
+ would raise an `IOError` when called on an unreadable object.
373
392
 
374
- * `ActiveSupport::Gzip.decompress` now checks checksum and length in footer.
393
+ Fixes #26132.
375
394
 
376
- *Dylan Thacker-Smith*
395
+ *Paul Kuruvilla*
377
396
 
378
- * Cache `ActiveSupport::TimeWithZone#to_datetime` before freezing.
379
-
380
- *Adam Rice*
381
-
382
- * Deprecate `ActiveSupport.halt_callback_chains_on_return_false`.
397
+ * Remove deprecated `halt_callback_chains_on_return_false` option.
383
398
 
384
399
  *Rafael Mendonça França*
385
400
 
386
- * Remove deprecated behavior that halts callbacks when the return is false.
401
+ * Remove deprecated `:if` and `:unless` string filter for callbacks.
387
402
 
388
403
  *Rafael Mendonça França*
389
404
 
390
- * Deprecate passing string to `:if` and `:unless` conditional options
391
- on `set_callback` and `skip_callback`.
392
-
393
- *Ryuta Kamizono*
394
-
395
- * Raise `ArgumentError` when passing string to define callback.
396
-
397
- *Ryuta Kamizono*
398
-
399
- * Updated Unicode version to 9.0.0
400
-
401
- Now we can handle new emojis such like "👩‍👩‍👧‍👦" ("\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}").
402
-
403
- version 8.0.0
404
-
405
- "👩‍👩‍👧‍👦".mb_chars.grapheme_length # => 4
406
- "👩‍👩‍👧‍👦".mb_chars.reverse # => "👦👧‍👩‍👩‍"
407
-
408
- version 9.0.0
409
-
410
- "👩‍👩‍👧‍👦".mb_chars.grapheme_length # => 1
411
- "👩‍👩‍👧‍👦".mb_chars.reverse # => "👩‍👩‍👧‍👦"
412
-
413
- *Fumiaki MATSUSHIMA*
414
-
415
- * Changed `ActiveSupport::Inflector#transliterate` to raise `ArgumentError` when it receives
416
- anything except a string.
417
-
418
- *Kevin McPhillips*
419
-
420
- * Fixed bugs that `StringInquirer#respond_to_missing?` and
421
- `ArrayInquirer#respond_to_missing?` do not fallback to `super`.
405
+ * `Hash#slice` now falls back to Ruby 2.5+'s built-in definition if defined.
422
406
 
423
407
  *Akira Matsuda*
424
408
 
425
- * Fix inconsistent results when parsing large durations and constructing durations from code
426
-
427
- ActiveSupport::Duration.parse('P3Y') == 3.years # It should be true
428
-
429
- Duration parsing made independent from any moment of time:
430
- Fixed length in seconds is assigned to each duration part during parsing.
409
+ * Deprecate `secrets.secret_token`.
431
410
 
432
- Changed duration of months and years in seconds to more accurate and logical:
411
+ The architecture for secrets had a big upgrade between Rails 3 and Rails 4,
412
+ when the default changed from using `secret_token` to `secret_key_base`.
433
413
 
434
- 1. The value of 365.2425 days in Gregorian year is more accurate
435
- as it accounts for every 400th non-leap year.
414
+ `secret_token` has been soft deprecated in documentation for four years
415
+ but is still in place to support apps created before Rails 4.
416
+ Deprecation warnings have been added to help developers upgrade their
417
+ applications to `secret_key_base`.
436
418
 
437
- 2. Month's length is bound to year's duration, which makes
438
- sensible comparisons like `12.months == 1.year` to be `true`
439
- and nonsensical ones like `30.days == 1.month` to be `false`.
440
-
441
- Calculations on times and dates with durations shouldn't be affected as
442
- duration's numeric value isn't used in calculations, only parts are used.
443
-
444
- Methods on `Numeric` like `2.days` now use these predefined durations
445
- to avoid duplication of duration constants through the codebase and
446
- eliminate creation of intermediate durations.
447
-
448
- *Andrey Novikov*, *Andrew White*
449
-
450
- * Change return value of `Rational#duplicable?`, `ComplexClass#duplicable?`
451
- to false.
452
-
453
- *utilum*
419
+ *claudiob*, *Kasper Timm Hansen*
454
420
 
455
- * Change return value of `NilClass#duplicable?`, `FalseClass#duplicable?`,
456
- `TrueClass#duplicable?`, `Symbol#duplicable?` and `Numeric#duplicable?`
457
- to true with Ruby 2.4+. These classes can dup with Ruby 2.4+.
421
+ * Return an instance of `HashWithIndifferentAccess` from `HashWithIndifferentAccess#transform_keys`.
458
422
 
459
423
  *Yuji Yaginuma*
460
424
 
461
- * Remove deprecated class `ActiveSupport::Concurrency::Latch`.
425
+ * Add key rotation support to `MessageEncryptor` and `MessageVerifier`.
462
426
 
463
- *Andrew White*
464
-
465
- * Remove deprecated separator argument from `parameterize`.
466
-
467
- *Andrew White*
468
-
469
- * Remove deprecated method `Numeric#to_formatted_s`.
427
+ This change introduces a `rotate` method to both the `MessageEncryptor` and
428
+ `MessageVerifier` classes. This method accepts the same arguments and
429
+ options as the given classes' constructor. The `encrypt_and_verify` method
430
+ for `MessageEncryptor` and the `verified` method for `MessageVerifier` also
431
+ accept an optional keyword argument `:on_rotation` block which is called
432
+ when a rotated instance is used to decrypt or verify the message.
470
433
 
471
- *Andrew White*
434
+ *Michael J Coyne*
472
435
 
473
- * Remove deprecated method `alias_method_chain`.
474
-
475
- *Andrew White*
476
-
477
- * Remove deprecated constant `MissingSourceFile`.
478
-
479
- *Andrew White*
436
+ * Deprecate `Module#reachable?` method.
480
437
 
481
- * Remove deprecated methods `Module.qualified_const_defined?`,
482
- `Module.qualified_const_get` and `Module.qualified_const_set`.
438
+ *bogdanvlviv*
483
439
 
484
- *Andrew White*
440
+ * Add `config/credentials.yml.enc` to store production app secrets.
485
441
 
486
- * Remove deprecated `:prefix` option from `number_to_human_size`.
442
+ Allows saving any authentication credentials for third party services
443
+ directly in repo encrypted with `config/master.key` or `ENV["RAILS_MASTER_KEY"]`.
487
444
 
488
- *Andrew White*
445
+ This will eventually replace `Rails.application.secrets` and the encrypted
446
+ secrets introduced in Rails 5.1.
489
447
 
490
- * Remove deprecated method `ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default`.
448
+ *DHH*, *Kasper Timm Hansen*
491
449
 
492
- *Andrew White*
450
+ * Add `ActiveSupport::EncryptedFile` and `ActiveSupport::EncryptedConfiguration`.
493
451
 
494
- * Remove deprecated file `active_support/core_ext/time/marshal.rb`.
452
+ Allows for stashing encrypted files or configuration directly in repo by
453
+ encrypting it with a key.
495
454
 
496
- *Andrew White*
455
+ Backs the new credentials setup above, but can also be used independently.
497
456
 
498
- * Remove deprecated file `active_support/core_ext/struct.rb`.
457
+ *DHH*, *Kasper Timm Hansen*
499
458
 
500
- *Andrew White*
459
+ * `Module#delegate_missing_to` now raises `DelegationError` if target is nil,
460
+ similar to `Module#delegate`.
501
461
 
502
- * Remove deprecated file `active_support/core_ext/module/method_transplanting.rb`.
462
+ *Anton Khamets*
503
463
 
504
- *Andrew White*
464
+ * Update `String#camelize` to provide feedback when wrong option is passed.
505
465
 
506
- * Remove deprecated method `Module.local_constants`.
466
+ `String#camelize` was returning nil without any feedback when an
467
+ invalid option was passed as a parameter.
507
468
 
508
- *Andrew White*
469
+ Previously:
509
470
 
510
- * Remove deprecated file `active_support/core_ext/kernel/debugger.rb`.
471
+ 'one_two'.camelize(true)
472
+ # => nil
511
473
 
512
- *Andrew White*
474
+ Now:
513
475
 
514
- * Remove deprecated method `ActiveSupport::Cache::Store#namespaced_key`.
476
+ 'one_two'.camelize(true)
477
+ # => ArgumentError: Invalid option, use either :upper or :lower.
515
478
 
516
- *Andrew White*
479
+ *Ricardo Díaz*
517
480
 
518
- * Remove deprecated method `ActiveSupport::Cache::Strategy::LocalCache::LocalStore#set_cache_value`.
481
+ * Fix modulo operations involving durations.
519
482
 
520
- *Andrew White*
483
+ Rails 5.1 introduced `ActiveSupport::Duration::Scalar` as a wrapper
484
+ around numeric values as a way of ensuring a duration was the outcome of
485
+ an expression. However, the implementation was missing support for modulo
486
+ operations. This support has now been added and should result in a duration
487
+ being returned from expressions involving modulo operations.
521
488
 
522
- * Remove deprecated method `ActiveSupport::Cache::MemCacheStore#escape_key`.
489
+ Prior to Rails 5.1:
523
490
 
524
- *Andrew White*
491
+ 5.minutes % 2.minutes
492
+ # => 60
525
493
 
526
- * Remove deprecated method `ActiveSupport::Cache::FileStore#key_file_path`.
494
+ Now:
527
495
 
528
- *Andrew White*
496
+ 5.minutes % 2.minutes
497
+ # => 1 minute
529
498
 
530
- * Ensure duration parsing is consistent across DST changes.
499
+ Fixes #29603 and #29743.
531
500
 
532
- Previously `ActiveSupport::Duration.parse` used `Time.current` and
533
- `Time#advance` to calculate the number of seconds in the duration
534
- from an arbitrary collection of parts. However as `advance` tries to
535
- be consistent across DST boundaries this meant that either the
536
- duration was shorter or longer depending on the time of year.
501
+ *Sayan Chakraborty*, *Andrew White*
537
502
 
538
- This was fixed by using an absolute reference point in UTC which
539
- isn't subject to DST transitions. An arbitrary date of Jan 1st, 2000
540
- was chosen for no other reason that it seemed appropriate.
503
+ * Fix division where a duration is the denominator.
541
504
 
542
- Additionally, duration parsing should now be marginally faster as we
543
- are no longer creating instances of `ActiveSupport::TimeWithZone`
544
- every time we parse a duration string.
505
+ PR #29163 introduced a change in behavior when a duration was the denominator
506
+ in a calculation - this was incorrect as dividing by a duration should always
507
+ return a `Numeric`. The behavior of previous versions of Rails has been restored.
545
508
 
546
- Fixes #26941.
509
+ Fixes #29592.
547
510
 
548
511
  *Andrew White*
549
512
 
550
- * Use `Hash#compact` and `Hash#compact!` from Ruby 2.4. Old Ruby versions
551
- will continue to get these methods from Active Support as before.
552
-
553
- *Prathamesh Sonpatki*
554
-
555
- * Fix `ActiveSupport::TimeZone#strptime`.
556
- Support for timestamps in format of seconds (%s) and milliseconds (%Q).
557
-
558
- Fixes #26840.
559
-
560
- *Lev Denisov*
561
-
562
- * Fix `DateAndTime::Calculations#copy_time_to`. Copy `nsec` instead of `usec`.
563
-
564
- Jumping forward or backward between weeks now preserves nanosecond digits.
565
-
566
- *Josua Schmid*
567
-
568
- * Fix `ActiveSupport::TimeWithZone#in` across DST boundaries.
569
-
570
- Previously calls to `in` were being sent to the non-DST aware
571
- method `Time#since` via `method_missing`. It is now aliased to
572
- the DST aware `ActiveSupport::TimeWithZone#+` which handles
573
- transitions across DST boundaries, e.g:
574
-
575
- Time.zone = "US/Eastern"
576
-
577
- t = Time.zone.local(2016,11,6,1)
578
- # => Sun, 06 Nov 2016 01:00:00 EDT -05:00
579
-
580
- t.in(1.hour)
581
- # => Sun, 06 Nov 2016 01:00:00 EST -05:00
582
-
583
- Fixes #26580.
584
-
585
- *Thomas Balthazar*
586
-
587
- * Remove unused parameter `options = nil` for `#clear` of
588
- `ActiveSupport::Cache::Strategy::LocalCache::LocalStore` and
589
- `ActiveSupport::Cache::Strategy::LocalCache`.
590
-
591
- *Yosuke Kabuto*
592
-
593
- * Fix `thread_mattr_accessor` subclass no longer overwrites parent.
594
-
595
- Assigning a value to a subclass using `thread_mattr_accessor` no
596
- longer changes the value of the parent class. This brings the
597
- behavior inline with the documentation.
598
-
599
- Given:
600
-
601
- class Account
602
- thread_mattr_accessor :user
603
- end
513
+ * Add purpose and expiry support to `ActiveSupport::MessageVerifier` and
514
+ `ActiveSupport::MessageEncryptor`.
604
515
 
605
- class Customer < Account
606
- end
516
+ For instance, to ensure a message is only usable for one intended purpose:
607
517
 
608
- Account.user = "DHH"
609
- Customer.user = "Rafael"
518
+ token = @verifier.generate("x", purpose: :shipping)
610
519
 
611
- Before:
612
-
613
- Account.user # => "Rafael"
520
+ @verifier.verified(token, purpose: :shipping) # => "x"
521
+ @verifier.verified(token) # => nil
614
522
 
615
- After:
523
+ Or make it expire after a set time:
616
524
 
617
- Account.user # => "DHH"
525
+ @verifier.generate("x", expires_in: 1.month)
526
+ @verifier.generate("y", expires_at: Time.now.end_of_year)
618
527
 
619
- *Shinichi Maeshima*
528
+ Showcased with `ActiveSupport::MessageVerifier`, but works the same for
529
+ `ActiveSupport::MessageEncryptor`'s `encrypt_and_sign` and `decrypt_and_verify`.
620
530
 
621
- * Since weeks are no longer converted to days, add `:weeks` to the list of
622
- parts that `ActiveSupport::TimeWithZone` will recognize as possibly being
623
- of variable duration to take account of DST transitions.
531
+ Pull requests: #29599, #29854
624
532
 
625
- Fixes #26039.
533
+ *Assain Jaleel*
626
534
 
627
- *Andrew White*
535
+ * Make the order of `Hash#reverse_merge!` consistent with `HashWithIndifferentAccess`.
628
536
 
629
- * Defines `Regexp.match?` for Ruby versions prior to 2.4. The predicate
630
- has the same interface, but it does not have the performance boost. Its
631
- purpose is to be able to write 2.4 compatible code.
537
+ *Erol Fornoles*
632
538
 
633
- *Xavier Noria*
539
+ * Add `freeze_time` helper which freezes time to `Time.now` in tests.
634
540
 
635
- * Allow `MessageEncryptor` to take advantage of authenticated encryption modes.
541
+ *Prathamesh Sonpatki*
636
542
 
637
- AEAD modes like `aes-256-gcm` provide both confidentiality and data
638
- authenticity, eliminating the need to use `MessageVerifier` to check if the
639
- encrypted data has been tampered with. This speeds up encryption/decryption
640
- and results in shorter cipher text.
543
+ * Default `ActiveSupport::MessageEncryptor` to use AES 256 GCM encryption.
641
544
 
642
- *Bart de Water*
545
+ On for new Rails 5.2 apps. Upgrading apps can find the config as a new
546
+ framework default.
643
547
 
644
- * Introduce `assert_changes` and `assert_no_changes`.
548
+ *Assain Jaleel*
645
549
 
646
- `assert_changes` is a more general `assert_difference` that works with any
647
- value.
550
+ * Cache: `write_multi`.
648
551
 
649
- assert_changes 'Error.current', from: nil, to: 'ERR' do
650
- expected_bad_operation
651
- end
552
+ Rails.cache.write_multi foo: 'bar', baz: 'qux'
652
553
 
653
- Can be called with strings, to be evaluated in the binding (context) of
654
- the block given to the assertion, or a lambda.
554
+ Plus faster fetch_multi with stores that implement `write_multi_entries`.
555
+ Keys that aren't found may be written to the cache store in one shot
556
+ instead of separate writes.
655
557
 
656
- assert_changes -> { Error.current }, from: nil, to: 'ERR' do
657
- expected_bad_operation
658
- end
558
+ The default implementation simply calls `write_entry` for each entry.
559
+ Stores may override if they're capable of one-shot bulk writes, like
560
+ Redis `MSET`.
659
561
 
660
- The `from` and `to` arguments are compared with the case operator (`===`).
562
+ *Jeremy Daer*
661
563
 
662
- assert_changes 'Error.current', from: nil, to: Error do
663
- expected_bad_operation
664
- end
564
+ * Add default option to module and class attribute accessors.
665
565
 
666
- This is pretty useful, if you need to loosely compare a value. For example,
667
- you need to test a token has been generated and it has that many random
668
- characters.
566
+ mattr_accessor :settings, default: {}
669
567
 
670
- user = User.start_registration
671
- assert_changes 'user.token', to: /\w{32}/ do
672
- user.finish_registration
673
- end
568
+ Works for `mattr_reader`, `mattr_writer`, `cattr_accessor`, `cattr_reader`,
569
+ and `cattr_writer` as well.
674
570
 
675
571
  *Genadi Samokovarov*
676
572
 
677
- * Fix `ActiveSupport::TimeZone#strptime`. Now raises `ArgumentError` when the
678
- given time doesn't match the format. The error is the same as the one given
679
- by Ruby's `Date.strptime`. Previously it raised
680
- `NoMethodError: undefined method empty? for nil:NilClass.` due to a bug.
573
+ * Add `Date#prev_occurring` and `Date#next_occurring` to return specified next/previous occurring day of week.
681
574
 
682
- Fixes #25701.
575
+ *Shota Iguchi*
683
576
 
684
- *John Gesimondo*
577
+ * Add default option to `class_attribute`.
685
578
 
686
- * `travel/travel_to` travel time helpers, now raise on nested calls,
687
- as this can lead to confusing time stubbing.
579
+ Before:
688
580
 
689
- Instead of:
581
+ class_attribute :settings
582
+ self.settings = {}
690
583
 
691
- travel_to 2.days.from_now do
692
- # 2 days from today
693
- travel_to 3.days.from_now do
694
- # 5 days from today
695
- end
696
- end
584
+ Now:
697
585
 
698
- preferred way to achieve above is:
586
+ class_attribute :settings, default: {}
699
587
 
700
- travel 2.days do
701
- # 2 days from today
702
- end
588
+ *DHH*
703
589
 
704
- travel 5.days do
705
- # 5 days from today
706
- end
590
+ * `#singularize` and `#pluralize` now respect uncountables for the specified locale.
707
591
 
708
- *Vipul A M*
592
+ *Eilis Hamilton*
709
593
 
710
- * Support parsing JSON time in ISO8601 local time strings in
711
- `ActiveSupport::JSON.decode` when `parse_json_times` is enabled.
712
- Strings in the format of `YYYY-MM-DD hh:mm:ss` (without a `Z` at
713
- the end) will be parsed in the local timezone (`Time.zone`). In
714
- addition, date strings (`YYYY-MM-DD`) are now parsed into `Date`
715
- objects.
594
+ * Add `ActiveSupport::CurrentAttributes` to provide a thread-isolated attributes singleton.
595
+ Primary use case is keeping all the per-request attributes easily available to the whole system.
716
596
 
717
- *Grzegorz Witek*
597
+ *DHH*
718
598
 
719
- * Fixed `ActiveSupport::Logger.broadcast` so that calls to `#silence` now
720
- properly delegate to all loggers. Silencing now properly suppresses logging
721
- to both the log and the console.
599
+ * Fix implicit coercion calculations with scalars and durations.
722
600
 
723
- *Kevin McPhillips*
601
+ Previously, calculations where the scalar is first would be converted to a duration
602
+ of seconds, but this causes issues with dates being converted to times, e.g:
724
603
 
725
- * Remove deprecated arguments in `assert_nothing_raised`.
604
+ Time.zone = "Beijing" # => Asia/Shanghai
605
+ date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
606
+ 2 * 1.day # => 172800 seconds
607
+ date + 2 * 1.day # => Mon, 22 May 2017 00:00:00 CST +08:00
726
608
 
727
- *Rafel Mendonça França*
609
+ Now, the `ActiveSupport::Duration::Scalar` calculation methods will try to maintain
610
+ the part structure of the duration where possible, e.g:
728
611
 
729
- * `Date.to_s` doesn't produce too many spaces. For example, `to_s(:short)`
730
- will now produce `01 Feb` instead of ` 1 Feb`.
612
+ Time.zone = "Beijing" # => Asia/Shanghai
613
+ date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
614
+ 2 * 1.day # => 2 days
615
+ date + 2 * 1.day # => Mon, 22 May 2017
731
616
 
732
- Fixes #25251.
617
+ Fixes #29160, #28970.
733
618
 
734
- *Sean Griffin*
619
+ *Andrew White*
735
620
 
736
- * Introduce `Module#delegate_missing_to`.
621
+ * Add support for versioned cache entries. This enables the cache stores to recycle cache keys, greatly saving
622
+ on storage in cases with frequent churn. Works together with the separation of `#cache_key` and `#cache_version`
623
+ in Active Record and its use in Action Pack's fragment caching.
737
624
 
738
- When building a decorator, a common pattern emerges:
625
+ *DHH*
739
626
 
740
- class Partition
741
- def initialize(first_event)
742
- @events = [ first_event ]
743
- end
627
+ * Pass gem name and deprecation horizon to deprecation notifications.
744
628
 
745
- def people
746
- if @events.first.detail.people.any?
747
- @events.collect { |e| Array(e.detail.people) }.flatten.uniq
748
- else
749
- @events.collect(&:creator).uniq
750
- end
751
- end
629
+ *Willem van Bergen*
752
630
 
753
- private
754
- def respond_to_missing?(name, include_private = false)
755
- @events.respond_to?(name, include_private)
756
- end
631
+ * Add support for `:offset` and `:zone` to `ActiveSupport::TimeWithZone#change`.
757
632
 
758
- def method_missing(method, *args, &block)
759
- @events.send(method, *args, &block)
760
- end
761
- end
633
+ *Andrew White*
762
634
 
763
- With `Module#delegate_missing_to`, the above is condensed to:
635
+ * Add support for `:offset` to `Time#change`.
764
636
 
765
- class Partition
766
- delegate_missing_to :@events
637
+ Fixes #28723.
767
638
 
768
- def initialize(first_event)
769
- @events = [ first_event ]
770
- end
639
+ *Andrew White*
771
640
 
772
- def people
773
- if @events.first.detail.people.any?
774
- @events.collect { |e| Array(e.detail.people) }.flatten.uniq
775
- else
776
- @events.collect(&:creator).uniq
777
- end
778
- end
779
- end
641
+ * Add `fetch_values` for `HashWithIndifferentAccess`.
780
642
 
781
- *Genadi Samokovarov*, *DHH*
643
+ The method was originally added to `Hash` in Ruby 2.3.0.
782
644
 
783
- * Rescuable: If a handler doesn't match the exception, check for handlers
784
- matching the exception's cause.
645
+ *Josh Pencheon*
785
646
 
786
- *Jeremy Daer*
787
647
 
788
- Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/activesupport/CHANGELOG.md) for previous changes.
648
+ Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activesupport/CHANGELOG.md) for previous changes.