activesupport 4.2.0 → 5.2.0

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 (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +54 -21
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  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 +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9a92aaed8c92253b60d615c68b681d0187185010
4
- data.tar.gz: 16a0f7761127de79598b4787717f1d90da9d64fd
2
+ SHA256:
3
+ metadata.gz: d0110a46a9c1dae01d77cdc50139933d40baaed4e3d4d2aa316253350239f090
4
+ data.tar.gz: ce05be98e3e753d72533c2002c42ab0ae9ce7bbcfd73b0a8a8a666c275fb4eb2
5
5
  SHA512:
6
- metadata.gz: 81470e00892e899e539f8791a1d6ba3a86d0a2e3760a0719c7922a987c92337d10dbffe9e157357d456c4aba6d64c6c71366db8b6772c19435ab64cd7c55894b
7
- data.tar.gz: 9e645639534174a986106a4a4df445c6c13498ef3e419dacab8b67870c088199412ed8db81a96a7a73e0c526d0971dc5368bbd8a2027252e632ba867c46be975
6
+ metadata.gz: b14730056fae2c1093e60f410cd2391fb18e590edcd7dee4e69a3c5493313154522edeb9e979fa038b3cdd897fb709c32719213e34c9fcaa3d2b8ab4f1c4a0cf
7
+ data.tar.gz: 1bad53bfb9ea8ba7ef6af4a2e4af0f5e272dc712e3c0f8ac2593cb91a35653871eaa6abb6f01ac46f8a946e256241b4a0e00640e5abe4ecac1a43ff06465aceb
data/CHANGELOG.md CHANGED
@@ -1,388 +1,522 @@
1
- * The decorated `load` and `require` methods are now kept private.
1
+ ## Rails 5.2.0 (April 09, 2018) ##
2
2
 
3
- Fixes #17553.
3
+ * Caching: MemCache and Redis `read_multi` and `fetch_multi` speedup.
4
+ Read from the local in-memory cache before consulting the backend.
4
5
 
5
- *Xavier Noria*
6
+ *Gabriel Sobrinho*
6
7
 
7
- * `String#remove` and `String#remove!` accept multiple arguments.
8
+ * Return all mappings for a timezone identifier in `country_zones`.
8
9
 
9
- *Pavel Pravosud*
10
+ Some timezones like `Europe/London` have multiple mappings in
11
+ `ActiveSupport::TimeZone::MAPPING` so return all of them instead
12
+ of the first one found by using `Hash#value`. e.g:
10
13
 
11
- * `TimeWithZone#strftime` now delegates every directive to `Time#strftime` except for '%Z',
12
- it also now correctly handles escaped '%' characters placed just before time zone related directives.
14
+ # Before
15
+ ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh"]
13
16
 
14
- *Pablo Herrero*
17
+ # After
18
+ ActiveSupport::TimeZone.country_zones("GB") # => ["Edinburgh", "London"]
15
19
 
16
- * Corrected `Inflector#underscore` handling of multiple successive acroynms.
20
+ Fixes #31668.
17
21
 
18
- *James Le Cuirot*
22
+ *Andrew White*
19
23
 
20
- * Delegation now works with ruby reserved words passed to `:to` option.
24
+ * Add support for connection pooling on RedisCacheStore.
21
25
 
22
- Fixes #16956.
26
+ *fatkodima*
23
27
 
24
- *Agis Anastasopoulos*
28
+ * Support hash as first argument in `assert_difference`. This allows to specify multiple
29
+ numeric differences in the same assertion.
25
30
 
26
- * Added method `#eql?` to `ActiveSupport::Duration`, in addition to `#==`.
31
+ assert_difference ->{ Article.count } => 1, ->{ Post.count } => 2
27
32
 
28
- Currently, the following returns `false`, contrary to expectation:
33
+ *Julien Meichelbeck*
29
34
 
30
- 1.minute.eql?(1.minute)
35
+ * Add missing instrumentation for `read_multi` in `ActiveSupport::Cache::Store`.
31
36
 
32
- Adding method `#eql?` will make this behave like expected. Method `#eql?` is
33
- just a bit stricter than `#==`, as it checks whether the argument is also a duration. Their
34
- parts may be different though.
37
+ *Ignatius Reza Lesmana*
35
38
 
36
- 1.minute.eql?(60.seconds) # => true
37
- 1.minute.eql?(60) # => false
39
+ * `assert_changes` will always assert that the expression changes,
40
+ regardless of `from:` and `to:` argument combinations.
38
41
 
39
- *Joost Lubach*
42
+ *Daniel Ma*
40
43
 
41
- * `Time#change` can now change nanoseconds (`:nsec`) as a higher-precision
42
- alternative to microseconds (`:usec`).
44
+ * Use SHA-1 to generate non-sensitive digests, such as the ETag header.
43
45
 
44
- *Agis Anastasooulos*
46
+ Enabled by default for new apps; upgrading apps can opt in by setting
47
+ `config.active_support.use_sha1_digests = true`.
45
48
 
46
- * `MessageVerifier.new` raises an appropriate exception if the secret is `nil`.
47
- This prevents `MessageVerifier#generate` from raising a cryptic error later on.
49
+ *Dmitri Dolguikh*, *Eugene Kenny*
48
50
 
49
- *Kostiantyn Kahanskyi*
51
+ * Changed default behaviour of `ActiveSupport::SecurityUtils.secure_compare`,
52
+ to make it not leak length information even for variable length string.
50
53
 
51
- * Introduced new configuration option `active_support.test_order` for
52
- specifying the order in which test cases are executed. This option currently defaults
53
- to `:sorted` but will be changed to `:random` in Rails 5.0.
54
+ Renamed old `ActiveSupport::SecurityUtils.secure_compare` to `fixed_length_secure_compare`,
55
+ and started raising `ArgumentError` in case of length mismatch of passed strings.
54
56
 
55
- *Akira Matsuda*, *Godfrey Chan*
57
+ *Vipul A M*
56
58
 
57
- * Fixed a bug in `Inflector#underscore` where acroynms in nested constant names
58
- are incorrectly parsed as camelCase.
59
+ * Make `ActiveSupport::TimeZone.all` return only time zones that are in
60
+ `ActiveSupport::TimeZone::MAPPING`.
59
61
 
60
- Fixes #8015.
62
+ Fixes #7245.
61
63
 
62
- *Fred Wu*, *Matthew Draper*
64
+ *Chris LaRose*
63
65
 
64
- * Make `Time#change` throw an exception if the `:usec` option is out of range and
65
- the time has an offset other than UTC or local.
66
+ * MemCacheStore: Support expiring counters.
66
67
 
67
- *Agis Anastasopoulos*
68
+ Pass `expires_in: [seconds]` to `#increment` and `#decrement` options
69
+ to set the Memcached TTL (time-to-live) if the counter doesn't exist.
70
+ If the counter exists, Memcached doesn't extend its expiry when it's
71
+ incremented or decremented.
68
72
 
69
- * `Method` objects now report themselves as not `duplicable?`. This allows
70
- hashes and arrays containing `Method` objects to be `deep_dup`ed.
73
+ ```
74
+ Rails.cache.increment("my_counter", 1, expires_in: 2.minutes)
75
+ ```
71
76
 
72
- *Peter Jaros*
77
+ *Takumasa Ochi*
73
78
 
74
- * `determine_constant_from_test_name` does no longer shadow `NameError`s
75
- which happens during constant autoloading.
79
+ * Handle `TZInfo::AmbiguousTime` errors.
76
80
 
77
- Fixes #9933.
81
+ Make `ActiveSupport::TimeWithZone` match Ruby's handling of ambiguous
82
+ times by choosing the later period, e.g.
78
83
 
79
- *Guo Xiang Tan*
84
+ Ruby:
85
+ ```
86
+ ENV["TZ"] = "Europe/Moscow"
87
+ Time.local(2014, 10, 26, 1, 0, 0) # => 2014-10-26 01:00:00 +0300
88
+ ```
80
89
 
81
- * Added instance_eval version to Object#try and Object#try!, so you can do this:
90
+ Before:
91
+ ```
92
+ >> "2014-10-26 01:00:00".in_time_zone("Moscow")
93
+ TZInfo::AmbiguousTime: 26/10/2014 01:00 is an ambiguous local time.
94
+ ```
82
95
 
83
- person.try { name.first }
96
+ After:
97
+ ```
98
+ >> "2014-10-26 01:00:00".in_time_zone("Moscow")
99
+ => Sun, 26 Oct 2014 01:00:00 MSK +03:00
100
+ ```
84
101
 
85
- instead of:
102
+ Fixes #17395.
86
103
 
87
- person.try { |person| person.name.first }
104
+ *Andrew White*
88
105
 
89
- *DHH*, *Ari Pollak*
106
+ * Redis cache store.
90
107
 
91
- * Fix the `ActiveSupport::Duration#instance_of?` method to return the right
92
- value with the class itself since it was previously delegated to the
93
- internal value.
108
+ ```
109
+ # Defaults to `redis://localhost:6379/0`. Only use for dev/test.
110
+ config.cache_store = :redis_cache_store
94
111
 
95
- *Robin Dupret*
112
+ # Supports all common cache store options (:namespace, :compress,
113
+ # :compress_threshold, :expires_in, :race_condition_ttl) and all
114
+ # Redis options.
115
+ cache_password = Rails.application.secrets.redis_cache_password
116
+ config.cache_store = :redis_cache_store, driver: :hiredis,
117
+ namespace: 'myapp-cache', compress: true, timeout: 1,
118
+ url: "redis://:#{cache_password}@myapp-cache-1:6379/0"
96
119
 
97
- * Fix rounding errors with `#travel_to` by resetting the usec on any passed time to zero, so we only travel
98
- with per-second precision, not anything deeper than that.
120
+ # Supports Redis::Distributed with multiple hosts
121
+ config.cache_store = :redis_cache_store, driver: :hiredis
122
+ namespace: 'myapp-cache', compress: true,
123
+ url: %w[
124
+ redis://myapp-cache-1:6379/0
125
+ redis://myapp-cache-1:6380/0
126
+ redis://myapp-cache-2:6379/0
127
+ redis://myapp-cache-2:6380/0
128
+ redis://myapp-cache-3:6379/0
129
+ redis://myapp-cache-3:6380/0
130
+ ]
99
131
 
100
- *DHH*
132
+ # Or pass a builder block
133
+ config.cache_store = :redis_cache_store,
134
+ namespace: 'myapp-cache', compress: true,
135
+ redis: -> { Redis.new … }
136
+ ```
101
137
 
102
- * Fix DateTime comparison with `DateTime::Infinity` object.
138
+ Deployment note: Take care to use a *dedicated Redis cache* rather
139
+ than pointing this at your existing Redis server. It won't cope well
140
+ with mixed usage patterns and it won't expire cache entries by default.
103
141
 
104
- *Rafael Mendonça França*
142
+ Redis cache server setup guide: https://redis.io/topics/lru-cache
105
143
 
106
- * Added Object#itself which returns the object itself. Useful when dealing with a chaining scenario, like Active Record scopes:
144
+ *Jeremy Daer*
107
145
 
108
- Event.public_send(state.presence_in([ :trashed, :drafted ]) || :itself).order(:created_at)
146
+ * Cache: Enable compression by default for values > 1kB.
109
147
 
110
- *DHH*
148
+ Compression has long been available, but opt-in and at a 16kB threshold.
149
+ It wasn't enabled by default due to CPU cost. Today it's cheap and typical
150
+ cache data is eminently compressible, such as HTML or JSON fragments.
151
+ Compression dramatically reduces Memcached/Redis mem usage, which means
152
+ the same cache servers can store more data, which means higher hit rates.
111
153
 
112
- * `Object#with_options` executes block in merging option context when
113
- explicit receiver in not passed.
154
+ To disable compression, pass `compress: false` to the initializer.
114
155
 
115
- *Pavel Pravosud*
156
+ *Jeremy Daer*
116
157
 
117
- * Fixed a compatibility issue with the `Oj` gem when cherry-picking the file
118
- `active_support/core_ext/object/json` without requiring `active_support/json`.
158
+ * Allow `Range#include?` on TWZ ranges.
119
159
 
120
- Fixes #16131.
160
+ In #11474 we prevented TWZ ranges being iterated over which matched
161
+ Ruby's handling of Time ranges and as a consequence `include?`
162
+ stopped working with both Time ranges and TWZ ranges. However in
163
+ ruby/ruby@b061634 support was added for `include?` to use `cover?`
164
+ for 'linear' objects. Since we have no way of making Ruby consider
165
+ TWZ instances as 'linear' we have to override `Range#include?`.
121
166
 
122
- *Godfrey Chan*
167
+ Fixes #30799.
123
168
 
124
- * Make `Hash#with_indifferent_access` copy the default proc too.
169
+ *Andrew White*
125
170
 
126
- *arthurnn*, *Xanders*
171
+ * Fix acronym support in `humanize`.
127
172
 
128
- * Add `String#truncate_words` to truncate a string by a number of words.
173
+ Acronym inflections are stored with lowercase keys in the hash but
174
+ the match wasn't being lowercased before being looked up in the hash.
175
+ This shouldn't have any performance impact because before it would
176
+ fail to find the acronym and perform the `downcase` operation anyway.
129
177
 
130
- *Mohamed Osama*
178
+ Fixes #31052.
131
179
 
132
- * Deprecate `capture` and `quietly`.
180
+ *Andrew White*
133
181
 
134
- These methods are not thread safe and may cause issues when used in threaded environments.
135
- To avoid problems we are deprecating them.
182
+ * Add same method signature for `Time#prev_year` and `Time#next_year`
183
+ in accordance with `Date#prev_year`, `Date#next_year`.
136
184
 
137
- *Tom Meier*
185
+ Allows pass argument for `Time#prev_year` and `Time#next_year`.
138
186
 
139
- * `DateTime#to_f` now preserves the fractional seconds instead of always
140
- rounding to `.0`.
187
+ Before:
188
+ ```
189
+ Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300
190
+ Time.new(2017, 9, 16, 17, 0).prev_year(1)
191
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
141
192
 
142
- Fixes #15994.
193
+ Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300
194
+ Time.new(2017, 9, 16, 17, 0).next_year(1)
195
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
196
+ ```
143
197
 
144
- *John Paul Ashenfelter*
198
+ After:
199
+ ```
200
+ Time.new(2017, 9, 16, 17, 0).prev_year # => 2016-09-16 17:00:00 +0300
201
+ Time.new(2017, 9, 16, 17, 0).prev_year(1) # => 2016-09-16 17:00:00 +0300
145
202
 
146
- * Add `Hash#transform_values` to simplify a common pattern where the values of a
147
- hash must change, but the keys are left the same.
203
+ Time.new(2017, 9, 16, 17, 0).next_year # => 2018-09-16 17:00:00 +0300
204
+ Time.new(2017, 9, 16, 17, 0).next_year(1) # => 2018-09-16 17:00:00 +0300
205
+ ```
148
206
 
149
- *Sean Griffin*
207
+ *bogdanvlviv*
150
208
 
151
- * Always instrument `ActiveSupport::Cache`.
209
+ * Add same method signature for `Time#prev_month` and `Time#next_month`
210
+ in accordance with `Date#prev_month`, `Date#next_month`.
152
211
 
153
- Since `ActiveSupport::Notifications` only instruments items when there
154
- are attached subscribers, we don't need to disable instrumentation.
212
+ Allows pass argument for `Time#prev_month` and `Time#next_month`.
155
213
 
156
- *Peter Wagenet*
214
+ Before:
215
+ ```
216
+ Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300
217
+ Time.new(2017, 9, 16, 17, 0).prev_month(1)
218
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
157
219
 
158
- * Make the `apply_inflections` method case-insensitive when checking
159
- whether a word is uncountable or not.
220
+ Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300
221
+ Time.new(2017, 9, 16, 17, 0).next_month(1)
222
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
223
+ ```
160
224
 
161
- *Robin Dupret*
225
+ After:
226
+ ```
227
+ Time.new(2017, 9, 16, 17, 0).prev_month # => 2017-08-16 17:00:00 +0300
228
+ Time.new(2017, 9, 16, 17, 0).prev_month(1) # => 2017-08-16 17:00:00 +0300
162
229
 
163
- * Make Dependencies pass a name to NameError error.
230
+ Time.new(2017, 9, 16, 17, 0).next_month # => 2017-10-16 17:00:00 +0300
231
+ Time.new(2017, 9, 16, 17, 0).next_month(1) # => 2017-10-16 17:00:00 +0300
232
+ ```
164
233
 
165
- *arthurnn*
234
+ *bogdanvlviv*
166
235
 
167
- * Fixed `ActiveSupport::Cache::FileStore` exploding with long paths.
236
+ * Add same method signature for `Time#prev_day` and `Time#next_day`
237
+ in accordance with `Date#prev_day`, `Date#next_day`.
168
238
 
169
- *Adam Panzer*, *Michael Grosser*
239
+ Allows pass argument for `Time#prev_day` and `Time#next_day`.
170
240
 
171
- * Fixed `ActiveSupport::TimeWithZone#-` so precision is not unnecessarily lost
172
- when working with objects with a nanosecond component.
241
+ Before:
242
+ ```
243
+ Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300
244
+ Time.new(2017, 9, 16, 17, 0).prev_day(1)
245
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
173
246
 
174
- `ActiveSupport::TimeWithZone#-` should return the same result as if we were
175
- using `Time#-`:
247
+ Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300
248
+ Time.new(2017, 9, 16, 17, 0).next_day(1)
249
+ # => ArgumentError: wrong number of arguments (given 1, expected 0)
250
+ ```
176
251
 
177
- Time.now.end_of_day - Time.now.beginning_of_day # => 86399.999999999
252
+ After:
253
+ ```
254
+ Time.new(2017, 9, 16, 17, 0).prev_day # => 2017-09-15 17:00:00 +0300
255
+ Time.new(2017, 9, 16, 17, 0).prev_day(1) # => 2017-09-15 17:00:00 +0300
178
256
 
179
- Before:
257
+ Time.new(2017, 9, 16, 17, 0).next_day # => 2017-09-17 17:00:00 +0300
258
+ Time.new(2017, 9, 16, 17, 0).next_day(1) # => 2017-09-17 17:00:00 +0300
259
+ ```
180
260
 
181
- Time.zone.now.end_of_day.nsec # => 999999999
182
- Time.zone.now.end_of_day - Time.zone.now.beginning_of_day # => 86400.0
261
+ *bogdanvlviv*
183
262
 
184
- After:
263
+ * `IO#to_json` now returns the `to_s` representation, rather than
264
+ attempting to convert to an array. This fixes a bug where `IO#to_json`
265
+ would raise an `IOError` when called on an unreadable object.
185
266
 
186
- Time.zone.now.end_of_day - Time.zone.now.beginning_of_day
187
- # => 86399.999999999
267
+ Fixes #26132.
188
268
 
189
- *Gordon Chan*
269
+ *Paul Kuruvilla*
190
270
 
191
- * Fixed precision error in NumberHelper when using Rationals.
271
+ * Remove deprecated `halt_callback_chains_on_return_false` option.
192
272
 
193
- Before:
273
+ *Rafael Mendonça França*
194
274
 
195
- ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2
196
- # => "330.00"
275
+ * Remove deprecated `:if` and `:unless` string filter for callbacks.
197
276
 
198
- After:
277
+ *Rafael Mendonça França*
199
278
 
200
- ActiveSupport::NumberHelper.number_to_rounded Rational(1000, 3), precision: 2
201
- # => "333.33"
279
+ * `Hash#slice` now falls back to Ruby 2.5+'s built-in definition if defined.
202
280
 
203
- See #15379.
281
+ *Akira Matsuda*
204
282
 
205
- *Juanjo Bazán*
283
+ * Deprecate `secrets.secret_token`.
206
284
 
207
- * Removed deprecated `Numeric#ago` and friends
285
+ The architecture for secrets had a big upgrade between Rails 3 and Rails 4,
286
+ when the default changed from using `secret_token` to `secret_key_base`.
208
287
 
209
- Replacements:
288
+ `secret_token` has been soft deprecated in documentation for four years
289
+ but is still in place to support apps created before Rails 4.
290
+ Deprecation warnings have been added to help developers upgrade their
291
+ applications to `secret_key_base`.
210
292
 
211
- 5.ago => 5.seconds.ago
212
- 5.until => 5.seconds.until
213
- 5.since => 5.seconds.since
214
- 5.from_now => 5.seconds.from_now
293
+ *claudiob*, *Kasper Timm Hansen*
215
294
 
216
- See #12389 for the history and rationale behind this.
295
+ * Return an instance of `HashWithIndifferentAccess` from `HashWithIndifferentAccess#transform_keys`.
217
296
 
218
- *Godfrey Chan*
297
+ *Yuji Yaginuma*
219
298
 
220
- * DateTime `advance` now supports partial days.
299
+ * Add key rotation support to `MessageEncryptor` and `MessageVerifier`.
221
300
 
222
- Before:
301
+ This change introduces a `rotate` method to both the `MessageEncryptor` and
302
+ `MessageVerifier` classes. This method accepts the same arguments and
303
+ options as the given classes' constructor. The `encrypt_and_verify` method
304
+ for `MessageEncryptor` and the `verified` method for `MessageVerifier` also
305
+ accept an optional keyword argument `:on_rotation` block which is called
306
+ when a rotated instance is used to decrypt or verify the message.
223
307
 
224
- DateTime.now.advance(days: 1, hours: 12)
308
+ *Michael J Coyne*
225
309
 
226
- After:
310
+ * Deprecate `Module#reachable?` method.
227
311
 
228
- DateTime.now.advance(days: 1.5)
312
+ *bogdanvlviv*
229
313
 
230
- Fixes #12005.
314
+ * Add `config/credentials.yml.enc` to store production app secrets.
231
315
 
232
- *Shay Davidson*
316
+ Allows saving any authentication credentials for third party services
317
+ directly in repo encrypted with `config/master.key` or `ENV["RAILS_MASTER_KEY"]`.
233
318
 
234
- * `Hash#deep_transform_keys` and `Hash#deep_transform_keys!` now transform hashes
235
- in nested arrays. This change also applies to `Hash#deep_stringify_keys`,
236
- `Hash#deep_stringify_keys!`, `Hash#deep_symbolize_keys` and
237
- `Hash#deep_symbolize_keys!`.
319
+ This will eventually replace `Rails.application.secrets` and the encrypted
320
+ secrets introduced in Rails 5.1.
238
321
 
239
- *OZAWA Sakuro*
322
+ *DHH*, *Kasper Timm Hansen*
240
323
 
241
- * Fixed confusing `DelegationError` in `Module#delegate`.
324
+ * Add `ActiveSupport::EncryptedFile` and `ActiveSupport::EncryptedConfiguration`.
242
325
 
243
- See #15186.
326
+ Allows for stashing encrypted files or configuration directly in repo by
327
+ encrypting it with a key.
244
328
 
245
- *Vladimir Yarotsky*
329
+ Backs the new credentials setup above, but can also be used independently.
246
330
 
247
- * Fixed `ActiveSupport::Subscriber` so that no duplicate subscriber is created
248
- when a subscriber method is redefined.
331
+ *DHH*, *Kasper Timm Hansen*
249
332
 
250
- *Dennis Schön*
333
+ * `Module#delegate_missing_to` now raises `DelegationError` if target is nil,
334
+ similar to `Module#delegate`.
251
335
 
252
- * Remove deprecated string based terminators for `ActiveSupport::Callbacks`.
336
+ *Anton Khamets*
253
337
 
254
- *Eileen M. Uchitelle*
338
+ * Update `String#camelize` to provide feedback when wrong option is passed.
255
339
 
256
- * Fixed an issue when using
257
- `ActiveSupport::NumberHelper::NumberToDelimitedConverter` to
258
- convert a value that is an `ActiveSupport::SafeBuffer` introduced
259
- in 2da9d67.
340
+ `String#camelize` was returning nil without any feedback when an
341
+ invalid option was passed as a parameter.
260
342
 
261
- See #15064.
343
+ Previously:
262
344
 
263
- *Mark J. Titorenko*
345
+ 'one_two'.camelize(true)
346
+ # => nil
264
347
 
265
- * `TimeZone#parse` defaults the day of the month to '1' if any other date
266
- components are specified. This is more consistent with the behavior of
267
- `Time#parse`.
348
+ Now:
268
349
 
269
- *Ulysse Carion*
350
+ 'one_two'.camelize(true)
351
+ # => ArgumentError: Invalid option, use either :upper or :lower.
270
352
 
271
- * `humanize` strips leading underscores, if any.
353
+ *Ricardo Díaz*
272
354
 
273
- Before:
355
+ * Fix modulo operations involving durations.
274
356
 
275
- '_id'.humanize # => ""
357
+ Rails 5.1 introduced `ActiveSupport::Duration::Scalar` as a wrapper
358
+ around numeric values as a way of ensuring a duration was the outcome of
359
+ an expression. However, the implementation was missing support for modulo
360
+ operations. This support has now been added and should result in a duration
361
+ being returned from expressions involving modulo operations.
276
362
 
277
- After:
363
+ Prior to Rails 5.1:
364
+
365
+ 5.minutes % 2.minutes
366
+ # => 60
367
+
368
+ Now:
369
+
370
+ 5.minutes % 2.minutes
371
+ # => 1 minute
372
+
373
+ Fixes #29603 and #29743.
374
+
375
+ *Sayan Chakraborty*, *Andrew White*
376
+
377
+ * Fix division where a duration is the denominator.
278
378
 
279
- '_id'.humanize # => "Id"
379
+ PR #29163 introduced a change in behavior when a duration was the denominator
380
+ in a calculation - this was incorrect as dividing by a duration should always
381
+ return a `Numeric`. The behavior of previous versions of Rails has been restored.
280
382
 
281
- *Xavier Noria*
383
+ Fixes #29592.
282
384
 
283
- * Fixed backward compatibility issues introduced in 326e652.
385
+ *Andrew White*
284
386
 
285
- Empty Hash or Array should not be present in serialization result.
387
+ * Add purpose and expiry support to `ActiveSupport::MessageVerifier` and
388
+ `ActiveSupport::MessageEncryptor`.
286
389
 
287
- {a: []}.to_query # => ""
288
- {a: {}}.to_query # => ""
390
+ For instance, to ensure a message is only usable for one intended purpose:
289
391
 
290
- For more info see #14948.
392
+ token = @verifier.generate("x", purpose: :shipping)
291
393
 
292
- *Bogdan Gusiev*
394
+ @verifier.verified(token, purpose: :shipping) # => "x"
395
+ @verifier.verified(token) # => nil
293
396
 
294
- * Add `Digest::UUID::uuid_v3` and `Digest::UUID::uuid_v5` to support stable
295
- UUID fixtures on PostgreSQL.
397
+ Or make it expire after a set time:
296
398
 
297
- *Roderick van Domburg*
399
+ @verifier.generate("x", expires_in: 1.month)
400
+ @verifier.generate("y", expires_at: Time.now.end_of_year)
298
401
 
299
- * Fixed `ActiveSupport::Duration#eql?` so that `1.second.eql?(1.second)` is
300
- true.
402
+ Showcased with `ActiveSupport::MessageVerifier`, but works the same for
403
+ `ActiveSupport::MessageEncryptor`'s `encrypt_and_sign` and `decrypt_and_verify`.
301
404
 
302
- This fixes the current situation of:
405
+ Pull requests: #29599, #29854
303
406
 
304
- 1.second.eql?(1.second) # => false
407
+ *Assain Jaleel*
305
408
 
306
- `eql?` also requires that the other object is an `ActiveSupport::Duration`.
307
- This requirement makes `ActiveSupport::Duration`'s behavior consistent with
308
- the behavior of Ruby's numeric types:
409
+ * Make the order of `Hash#reverse_merge!` consistent with `HashWithIndifferentAccess`.
309
410
 
310
- 1.eql?(1.0) # => false
311
- 1.0.eql?(1) # => false
411
+ *Erol Fornoles*
312
412
 
313
- 1.second.eql?(1) # => false (was true)
314
- 1.eql?(1.second) # => false
413
+ * Add `freeze_time` helper which freezes time to `Time.now` in tests.
315
414
 
316
- { 1 => "foo", 1.0 => "bar" }
317
- # => { 1 => "foo", 1.0 => "bar" }
415
+ *Prathamesh Sonpatki*
318
416
 
319
- { 1 => "foo", 1.second => "bar" }
320
- # now => { 1 => "foo", 1.second => "bar" }
321
- # was => { 1 => "bar" }
417
+ * Default `ActiveSupport::MessageEncryptor` to use AES 256 GCM encryption.
322
418
 
323
- And though the behavior of these hasn't changed, for reference:
419
+ On for new Rails 5.2 apps. Upgrading apps can find the config as a new
420
+ framework default.
324
421
 
325
- 1 == 1.0 # => true
326
- 1.0 == 1 # => true
422
+ *Assain Jaleel*
327
423
 
328
- 1 == 1.second # => true
329
- 1.second == 1 # => true
424
+ * Cache: `write_multi`.
330
425
 
331
- *Emily Dobervich*
426
+ Rails.cache.write_multi foo: 'bar', baz: 'qux'
332
427
 
333
- * `ActiveSupport::SafeBuffer#prepend` acts like `String#prepend` and modifies
334
- instance in-place, returning self. `ActiveSupport::SafeBuffer#prepend!` is
335
- deprecated.
428
+ Plus faster fetch_multi with stores that implement `write_multi_entries`.
429
+ Keys that aren't found may be written to the cache store in one shot
430
+ instead of separate writes.
336
431
 
337
- *Pavel Pravosud*
432
+ The default implementation simply calls `write_entry` for each entry.
433
+ Stores may override if they're capable of one-shot bulk writes, like
434
+ Redis `MSET`.
338
435
 
339
- * `HashWithIndifferentAccess` better respects `#to_hash` on objects it
340
- receives. In particular, `.new`, `#update`, `#merge`, and `#replace` accept
341
- objects which respond to `#to_hash`, even if those objects are not hashes
342
- directly.
436
+ *Jeremy Daer*
343
437
 
344
- *Peter Jaros*
438
+ * Add default option to module and class attribute accessors.
345
439
 
346
- * Deprecate `Class#superclass_delegating_accessor`, use `Class#class_attribute` instead.
440
+ mattr_accessor :settings, default: {}
441
+
442
+ Works for `mattr_reader`, `mattr_writer`, `cattr_accessor`, `cattr_reader`,
443
+ and `cattr_writer` as well.
444
+
445
+ *Genadi Samokovarov*
446
+
447
+ * Add `Date#prev_occurring` and `Date#next_occurring` to return specified next/previous occurring day of week.
448
+
449
+ *Shota Iguchi*
450
+
451
+ * Add default option to `class_attribute`.
452
+
453
+ Before:
454
+
455
+ class_attribute :settings
456
+ self.settings = {}
457
+
458
+ Now:
459
+
460
+ class_attribute :settings, default: {}
461
+
462
+ *DHH*
463
+
464
+ * `#singularize` and `#pluralize` now respect uncountables for the specified locale.
465
+
466
+ *Eilis Hamilton*
467
+
468
+ * Add `ActiveSupport::CurrentAttributes` to provide a thread-isolated attributes singleton.
469
+ Primary use case is keeping all the per-request attributes easily available to the whole system.
470
+
471
+ *DHH*
472
+
473
+ * Fix implicit coercion calculations with scalars and durations.
474
+
475
+ Previously, calculations where the scalar is first would be converted to a duration
476
+ of seconds, but this causes issues with dates being converted to times, e.g:
477
+
478
+ Time.zone = "Beijing" # => Asia/Shanghai
479
+ date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
480
+ 2 * 1.day # => 172800 seconds
481
+ date + 2 * 1.day # => Mon, 22 May 2017 00:00:00 CST +08:00
482
+
483
+ Now, the `ActiveSupport::Duration::Scalar` calculation methods will try to maintain
484
+ the part structure of the duration where possible, e.g:
485
+
486
+ Time.zone = "Beijing" # => Asia/Shanghai
487
+ date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
488
+ 2 * 1.day # => 2 days
489
+ date + 2 * 1.day # => Mon, 22 May 2017
490
+
491
+ Fixes #29160, #28970.
492
+
493
+ *Andrew White*
494
+
495
+ * Add support for versioned cache entries. This enables the cache stores to recycle cache keys, greatly saving
496
+ on storage in cases with frequent churn. Works together with the separation of `#cache_key` and `#cache_version`
497
+ in Active Record and its use in Action Pack's fragment caching.
498
+
499
+ *DHH*
347
500
 
348
- *Akshay Vishnoi*
501
+ * Pass gem name and deprecation horizon to deprecation notifications.
349
502
 
350
- * Ensure classes which `include Enumerable` get `#to_json` in addition to
351
- `#as_json`.
503
+ *Willem van Bergen*
352
504
 
353
- *Sammy Larbi*
505
+ * Add support for `:offset` and `:zone` to `ActiveSupport::TimeWithZone#change`.
354
506
 
355
- * Change the signature of `fetch_multi` to return a hash rather than an
356
- array. This makes it consistent with the output of `read_multi`.
507
+ *Andrew White*
357
508
 
358
- *Parker Selbert*
509
+ * Add support for `:offset` to `Time#change`.
359
510
 
360
- * Introduce `Concern#class_methods` as a sleek alternative to clunky
361
- `module ClassMethods`. Add `Kernel#concern` to define at the toplevel
362
- without chunky `module Foo; extend ActiveSupport::Concern` boilerplate.
511
+ Fixes #28723.
363
512
 
364
- # app/models/concerns/authentication.rb
365
- concern :Authentication do
366
- included do
367
- after_create :generate_private_key
368
- end
513
+ *Andrew White*
369
514
 
370
- class_methods do
371
- def authenticate(credentials)
372
- # ...
373
- end
374
- end
515
+ * Add `fetch_values` for `HashWithIndifferentAccess`.
375
516
 
376
- def generate_private_key
377
- # ...
378
- end
379
- end
517
+ The method was originally added to `Hash` in Ruby 2.3.0.
380
518
 
381
- # app/models/user.rb
382
- class User < ActiveRecord::Base
383
- include Authentication
384
- end
519
+ *Josh Pencheon*
385
520
 
386
- *Jeremy Kemper*
387
521
 
388
- Please check [4-1-stable](https://github.com/rails/rails/blob/4-1-stable/activesupport/CHANGELOG.md) for previous changes.
522
+ Please check [5-1-stable](https://github.com/rails/rails/blob/5-1-stable/activesupport/CHANGELOG.md) for previous changes.