activesupport 6.0.6.1 → 7.1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +865 -438
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +4 -2
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +30 -10
  8. data/lib/active_support/benchmarkable.rb +4 -3
  9. data/lib/active_support/broadcast_logger.rb +250 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +53 -20
  14. data/lib/active_support/cache/mem_cache_store.rb +208 -63
  15. data/lib/active_support/cache/memory_store.rb +120 -38
  16. data/lib/active_support/cache/null_store.rb +16 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +201 -208
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +73 -66
  20. data/lib/active_support/cache.rb +539 -261
  21. data/lib/active_support/callbacks.rb +273 -142
  22. data/lib/active_support/code_generator.rb +65 -0
  23. data/lib/active_support/concern.rb +53 -7
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/concurrency/share_lock.rb +2 -2
  27. data/lib/active_support/configurable.rb +19 -6
  28. data/lib/active_support/configuration_file.rb +51 -0
  29. data/lib/active_support/core_ext/array/access.rb +1 -5
  30. data/lib/active_support/core_ext/array/conversions.rb +15 -13
  31. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  33. data/lib/active_support/core_ext/benchmark.rb +2 -2
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  35. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  36. data/lib/active_support/core_ext/class/subclasses.rb +19 -29
  37. data/lib/active_support/core_ext/date/blank.rb +1 -1
  38. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  39. data/lib/active_support/core_ext/date/conversions.rb +18 -16
  40. data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -4
  41. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  42. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  43. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  44. data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
  45. data/lib/active_support/core_ext/digest/uuid.rb +30 -13
  46. data/lib/active_support/core_ext/enumerable.rb +146 -72
  47. data/lib/active_support/core_ext/erb/util.rb +196 -0
  48. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  49. data/lib/active_support/core_ext/hash/conversions.rb +3 -4
  50. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  51. data/lib/active_support/core_ext/hash/deep_transform_values.rb +4 -4
  52. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  53. data/lib/active_support/core_ext/hash/keys.rb +5 -5
  54. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  55. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  56. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  58. data/lib/active_support/core_ext/load_error.rb +1 -1
  59. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  60. data/lib/active_support/core_ext/module/attribute_accessors.rb +31 -29
  61. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +51 -20
  62. data/lib/active_support/core_ext/module/concerning.rb +14 -8
  63. data/lib/active_support/core_ext/module/delegation.rb +75 -42
  64. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  65. data/lib/active_support/core_ext/module/introspection.rb +1 -26
  66. data/lib/active_support/core_ext/name_error.rb +23 -2
  67. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  68. data/lib/active_support/core_ext/numeric/conversions.rb +82 -73
  69. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  70. data/lib/active_support/core_ext/object/blank.rb +2 -2
  71. data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
  72. data/lib/active_support/core_ext/object/duplicable.rb +15 -4
  73. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  74. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  75. data/lib/active_support/core_ext/object/json.rb +52 -28
  76. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  77. data/lib/active_support/core_ext/object/try.rb +20 -20
  78. data/lib/active_support/core_ext/object/with.rb +44 -0
  79. data/lib/active_support/core_ext/object/with_options.rb +25 -6
  80. data/lib/active_support/core_ext/object.rb +1 -0
  81. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  82. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  83. data/lib/active_support/core_ext/pathname.rb +4 -0
  84. data/lib/active_support/core_ext/range/compare_range.rb +6 -25
  85. data/lib/active_support/core_ext/range/conversions.rb +34 -13
  86. data/lib/active_support/core_ext/range/each.rb +1 -1
  87. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  88. data/lib/active_support/core_ext/range.rb +1 -2
  89. data/lib/active_support/core_ext/regexp.rb +8 -1
  90. data/lib/active_support/core_ext/securerandom.rb +25 -13
  91. data/lib/active_support/core_ext/string/access.rb +5 -24
  92. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  93. data/lib/active_support/core_ext/string/filters.rb +21 -15
  94. data/lib/active_support/core_ext/string/indent.rb +1 -1
  95. data/lib/active_support/core_ext/string/inflections.rb +51 -10
  96. data/lib/active_support/core_ext/string/inquiry.rb +2 -1
  97. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  98. data/lib/active_support/core_ext/string/output_safety.rb +85 -194
  99. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  100. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  101. data/lib/active_support/core_ext/symbol.rb +3 -0
  102. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  103. data/lib/active_support/core_ext/time/calculations.rb +46 -8
  104. data/lib/active_support/core_ext/time/conversions.rb +16 -13
  105. data/lib/active_support/core_ext/time/zones.rb +12 -28
  106. data/lib/active_support/core_ext.rb +2 -1
  107. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  108. data/lib/active_support/current_attributes.rb +54 -22
  109. data/lib/active_support/deep_mergeable.rb +53 -0
  110. data/lib/active_support/dependencies/autoload.rb +17 -12
  111. data/lib/active_support/dependencies/interlock.rb +10 -18
  112. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  113. data/lib/active_support/dependencies.rb +58 -769
  114. data/lib/active_support/deprecation/behaviors.rb +77 -38
  115. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  116. data/lib/active_support/deprecation/deprecators.rb +104 -0
  117. data/lib/active_support/deprecation/disallowed.rb +54 -0
  118. data/lib/active_support/deprecation/instance_delegator.rb +31 -5
  119. data/lib/active_support/deprecation/method_wrappers.rb +12 -28
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +40 -25
  121. data/lib/active_support/deprecation/reporting.rb +76 -16
  122. data/lib/active_support/deprecation.rb +36 -4
  123. data/lib/active_support/deprecator.rb +7 -0
  124. data/lib/active_support/descendants_tracker.rb +150 -68
  125. data/lib/active_support/digest.rb +5 -3
  126. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  127. data/lib/active_support/duration/iso8601_serializer.rb +24 -12
  128. data/lib/active_support/duration.rb +136 -56
  129. data/lib/active_support/encrypted_configuration.rb +72 -9
  130. data/lib/active_support/encrypted_file.rb +46 -13
  131. data/lib/active_support/environment_inquirer.rb +40 -0
  132. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  133. data/lib/active_support/error_reporter.rb +203 -0
  134. data/lib/active_support/evented_file_update_checker.rb +86 -137
  135. data/lib/active_support/execution_context/test_helper.rb +13 -0
  136. data/lib/active_support/execution_context.rb +53 -0
  137. data/lib/active_support/execution_wrapper.rb +31 -12
  138. data/lib/active_support/executor/test_helper.rb +7 -0
  139. data/lib/active_support/file_update_checker.rb +4 -2
  140. data/lib/active_support/fork_tracker.rb +79 -0
  141. data/lib/active_support/gem_version.rb +5 -5
  142. data/lib/active_support/gzip.rb +2 -0
  143. data/lib/active_support/hash_with_indifferent_access.rb +86 -42
  144. data/lib/active_support/html_safe_translation.rb +53 -0
  145. data/lib/active_support/i18n.rb +2 -1
  146. data/lib/active_support/i18n_railtie.rb +29 -27
  147. data/lib/active_support/inflector/inflections.rb +26 -9
  148. data/lib/active_support/inflector/methods.rb +54 -64
  149. data/lib/active_support/inflector/transliterate.rb +7 -5
  150. data/lib/active_support/isolated_execution_state.rb +76 -0
  151. data/lib/active_support/json/decoding.rb +6 -5
  152. data/lib/active_support/json/encoding.rb +31 -45
  153. data/lib/active_support/key_generator.rb +32 -7
  154. data/lib/active_support/lazy_load_hooks.rb +33 -7
  155. data/lib/active_support/locale/en.yml +10 -4
  156. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  157. data/lib/active_support/log_subscriber.rb +101 -32
  158. data/lib/active_support/logger.rb +9 -60
  159. data/lib/active_support/logger_silence.rb +2 -26
  160. data/lib/active_support/logger_thread_safe_level.rb +24 -25
  161. data/lib/active_support/message_encryptor.rb +205 -58
  162. data/lib/active_support/message_encryptors.rb +141 -0
  163. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  164. data/lib/active_support/message_pack/extensions.rb +292 -0
  165. data/lib/active_support/message_pack/serializer.rb +63 -0
  166. data/lib/active_support/message_pack.rb +50 -0
  167. data/lib/active_support/message_verifier.rb +237 -86
  168. data/lib/active_support/message_verifiers.rb +135 -0
  169. data/lib/active_support/messages/codec.rb +65 -0
  170. data/lib/active_support/messages/metadata.rb +112 -46
  171. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  172. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  173. data/lib/active_support/messages/rotator.rb +35 -32
  174. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  175. data/lib/active_support/multibyte/chars.rb +15 -52
  176. data/lib/active_support/multibyte/unicode.rb +8 -122
  177. data/lib/active_support/multibyte.rb +1 -1
  178. data/lib/active_support/notifications/fanout.rb +310 -105
  179. data/lib/active_support/notifications/instrumenter.rb +113 -48
  180. data/lib/active_support/notifications.rb +56 -29
  181. data/lib/active_support/number_helper/number_converter.rb +15 -8
  182. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  183. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  184. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  185. data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -5
  186. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  187. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  188. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  189. data/lib/active_support/number_helper.rb +379 -304
  190. data/lib/active_support/option_merger.rb +11 -18
  191. data/lib/active_support/ordered_hash.rb +4 -4
  192. data/lib/active_support/ordered_options.rb +23 -3
  193. data/lib/active_support/parameter_filter.rb +104 -75
  194. data/lib/active_support/proxy_object.rb +2 -0
  195. data/lib/active_support/rails.rb +1 -4
  196. data/lib/active_support/railtie.rb +90 -6
  197. data/lib/active_support/reloader.rb +12 -4
  198. data/lib/active_support/rescuable.rb +18 -16
  199. data/lib/active_support/ruby_features.rb +7 -0
  200. data/lib/active_support/secure_compare_rotator.rb +58 -0
  201. data/lib/active_support/security_utils.rb +19 -12
  202. data/lib/active_support/string_inquirer.rb +5 -3
  203. data/lib/active_support/subscriber.rb +23 -47
  204. data/lib/active_support/syntax_error_proxy.rb +70 -0
  205. data/lib/active_support/tagged_logging.rb +84 -23
  206. data/lib/active_support/test_case.rb +166 -27
  207. data/lib/active_support/testing/assertions.rb +73 -20
  208. data/lib/active_support/testing/autorun.rb +0 -2
  209. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  210. data/lib/active_support/testing/deprecation.rb +53 -2
  211. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  212. data/lib/active_support/testing/isolation.rb +30 -29
  213. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  214. data/lib/active_support/testing/parallelization/server.rb +82 -0
  215. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  216. data/lib/active_support/testing/parallelization.rb +16 -95
  217. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  218. data/lib/active_support/testing/stream.rb +4 -6
  219. data/lib/active_support/testing/strict_warnings.rb +39 -0
  220. data/lib/active_support/testing/tagged_logging.rb +1 -1
  221. data/lib/active_support/testing/time_helpers.rb +89 -19
  222. data/lib/active_support/time_with_zone.rb +105 -70
  223. data/lib/active_support/values/time_zone.rb +59 -26
  224. data/lib/active_support/version.rb +1 -1
  225. data/lib/active_support/xml_mini/jdom.rb +4 -11
  226. data/lib/active_support/xml_mini/libxml.rb +5 -5
  227. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  228. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  229. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  230. data/lib/active_support/xml_mini/rexml.rb +9 -2
  231. data/lib/active_support/xml_mini.rb +7 -6
  232. data/lib/active_support.rb +40 -1
  233. metadata +127 -40
  234. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  235. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  236. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  237. data/lib/active_support/core_ext/marshal.rb +0 -24
  238. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  239. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  240. data/lib/active_support/core_ext/range/include_range.rb +0 -9
  241. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -23
  242. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  243. data/lib/active_support/core_ext/uri.rb +0 -25
  244. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
  245. data/lib/active_support/per_thread_registry.rb +0 -60
@@ -3,9 +3,9 @@
3
3
  require "active_support/core_ext/hash/deep_merge"
4
4
 
5
5
  module ActiveSupport
6
- class OptionMerger #:nodoc:
6
+ class OptionMerger # :nodoc:
7
7
  instance_methods.each do |method|
8
- undef_method(method) if !/^(__|instance_eval|class|object_id)/.match?(method)
8
+ undef_method(method) unless method.start_with?("__", "instance_eval", "class", "object_id")
9
9
  end
10
10
 
11
11
  def initialize(context, options)
@@ -15,8 +15,8 @@ module ActiveSupport
15
15
  private
16
16
  def method_missing(method, *arguments, &block)
17
17
  options = nil
18
- if arguments.first.is_a?(Proc)
19
- proc = arguments.pop
18
+ if arguments.size == 1 && arguments.first.is_a?(Proc)
19
+ proc = arguments.shift
20
20
  arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
21
21
  elsif arguments.last.respond_to?(:to_hash)
22
22
  options = @options.deep_merge(arguments.pop)
@@ -24,22 +24,15 @@ module ActiveSupport
24
24
  options = @options
25
25
  end
26
26
 
27
- invoke_method(method, arguments, options, &block)
28
- end
29
-
30
- if RUBY_VERSION >= "2.7"
31
- def invoke_method(method, arguments, options, &block)
32
- if options
33
- @context.__send__(method, *arguments, **options, &block)
34
- else
35
- @context.__send__(method, *arguments, &block)
36
- end
37
- end
38
- else
39
- def invoke_method(method, arguments, options, &block)
40
- arguments << options.dup if options
27
+ if options
28
+ @context.__send__(method, *arguments, **options, &block)
29
+ else
41
30
  @context.__send__(method, *arguments, &block)
42
31
  end
43
32
  end
33
+
34
+ def respond_to_missing?(*arguments)
35
+ @context.respond_to?(*arguments)
36
+ end
44
37
  end
45
38
  end
@@ -7,7 +7,7 @@ YAML.add_builtin_type("omap") do |type, val|
7
7
  end
8
8
 
9
9
  module ActiveSupport
10
- # DEPRECATED: <tt>ActiveSupport::OrderedHash</tt> implements a hash that preserves
10
+ # DEPRECATED: +ActiveSupport::OrderedHash+ implements a hash that preserves
11
11
  # insertion order.
12
12
  #
13
13
  # oh = ActiveSupport::OrderedHash.new
@@ -17,11 +17,11 @@ module ActiveSupport
17
17
  #
18
18
  # Also, maps the +omap+ feature for YAML files
19
19
  # (See https://yaml.org/type/omap.html) to support ordered items
20
- # when loading from yaml.
20
+ # when loading from YAML.
21
21
  #
22
- # <tt>ActiveSupport::OrderedHash</tt> is namespaced to prevent conflicts
22
+ # +ActiveSupport::OrderedHash+ is namespaced to prevent conflicts
23
23
  # with other implementations.
24
- class OrderedHash < ::Hash
24
+ class OrderedHash < ::Hash # :nodoc:
25
25
  def to_yaml_type
26
26
  "!tag:yaml.org,2002:omap"
27
27
  end
@@ -3,7 +3,11 @@
3
3
  require "active_support/core_ext/object/blank"
4
4
 
5
5
  module ActiveSupport
6
- # Usually key value pairs are handled something like this:
6
+ # = Ordered Options
7
+ #
8
+ # +OrderedOptions+ inherits from +Hash+ and provides dynamic accessor methods.
9
+ #
10
+ # With a +Hash+, key-value pairs are typically managed like this:
7
11
  #
8
12
  # h = {}
9
13
  # h[:boy] = 'John'
@@ -12,7 +16,7 @@ module ActiveSupport
12
16
  # h[:girl] # => 'Mary'
13
17
  # h[:dog] # => nil
14
18
  #
15
- # Using +OrderedOptions+, the above code could be reduced to:
19
+ # Using +OrderedOptions+, the above code can be written as:
16
20
  #
17
21
  # h = ActiveSupport::OrderedOptions.new
18
22
  # h.boy = 'John'
@@ -38,6 +42,10 @@ module ActiveSupport
38
42
  super(key.to_sym)
39
43
  end
40
44
 
45
+ def dig(key, *identifiers)
46
+ super(key.to_sym, *identifiers)
47
+ end
48
+
41
49
  def method_missing(name, *args)
42
50
  name_string = +name.to_s
43
51
  if name_string.chomp!("=")
@@ -60,9 +68,15 @@ module ActiveSupport
60
68
  def extractable_options?
61
69
  true
62
70
  end
71
+
72
+ def inspect
73
+ "#<#{self.class.name} #{super}>"
74
+ end
63
75
  end
64
76
 
65
- # +InheritableOptions+ provides a constructor to build an +OrderedOptions+
77
+ # = Inheritable Options
78
+ #
79
+ # +InheritableOptions+ provides a constructor to build an OrderedOptions
66
80
  # hash inherited from another hash.
67
81
  #
68
82
  # Use this if you already have some hash and you want to create a new one based on it.
@@ -70,6 +84,12 @@ module ActiveSupport
70
84
  # h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
71
85
  # h.girl # => 'Mary'
72
86
  # h.boy # => 'John'
87
+ #
88
+ # If the existing hash has string keys, call Hash#symbolize_keys on it.
89
+ #
90
+ # h = ActiveSupport::InheritableOptions.new({ 'girl' => 'Mary', 'boy' => 'John' }.symbolize_keys)
91
+ # h.girl # => 'Mary'
92
+ # h.boy # => 'John'
73
93
  class InheritableOptions < OrderedOptions
74
94
  def initialize(parent = nil)
75
95
  if parent.kind_of?(OrderedOptions)
@@ -4,125 +4,154 @@ require "active_support/core_ext/object/duplicable"
4
4
  require "active_support/core_ext/array/extract"
5
5
 
6
6
  module ActiveSupport
7
- # +ParameterFilter+ allows you to specify keys for sensitive data from
8
- # hash-like object and replace corresponding value. Filtering only certain
9
- # sub-keys from a hash is possible by using the dot notation:
10
- # 'credit_card.number'. If a proc is given, each key and value of a hash and
11
- # all sub-hashes are passed to it, where the value or the key can be replaced
12
- # using String#replace or similar methods.
7
+ # = Active Support Parameter Filter
13
8
  #
9
+ # +ParameterFilter+ replaces values in a <tt>Hash</tt>-like object if their
10
+ # keys match one of the specified filters.
11
+ #
12
+ # Matching based on nested keys is possible by using dot notation, e.g.
13
+ # <tt>"credit_card.number"</tt>.
14
+ #
15
+ # If a proc is given as a filter, each key and value of the <tt>Hash</tt>-like
16
+ # and of any nested <tt>Hash</tt>es will be passed to it. The value or key can
17
+ # then be mutated as desired using methods such as <tt>String#replace</tt>.
18
+ #
19
+ # # Replaces values with "[FILTERED]" for keys that match /password/i.
14
20
  # ActiveSupport::ParameterFilter.new([:password])
15
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
16
21
  #
22
+ # # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
17
23
  # ActiveSupport::ParameterFilter.new([:foo, "bar"])
18
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
19
24
  #
25
+ # # Replaces values for the exact key "pin" and for keys that begin with
26
+ # # "pin_". Does not match keys that otherwise include "pin" as a
27
+ # # substring, such as "shipping_id".
28
+ # ActiveSupport::ParameterFilter.new([/\Apin\z/, /\Apin_/])
29
+ #
30
+ # # Replaces the value for :code in `{ credit_card: { code: "xxxx" } }`.
31
+ # # Does not change `{ file: { code: "xxxx" } }`.
20
32
  # ActiveSupport::ParameterFilter.new(["credit_card.code"])
21
- # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
22
- # change { file: { code: "xxxx"} }
23
33
  #
34
+ # # Reverses values for keys that match /secret/i.
24
35
  # ActiveSupport::ParameterFilter.new([-> (k, v) do
25
- # v.reverse! if k =~ /secret/i
36
+ # v.reverse! if /secret/i.match?(k)
26
37
  # end])
27
- # => reverses the value to all keys matching /secret/i
38
+ #
28
39
  class ParameterFilter
29
40
  FILTERED = "[FILTERED]" # :nodoc:
30
41
 
42
+ # Precompiles an array of filters that otherwise would be passed directly to
43
+ # #initialize. Depending on the quantity and types of filters,
44
+ # precompilation can improve filtering performance, especially in the case
45
+ # where the ParameterFilter instance itself cannot be retained (but the
46
+ # precompiled filters can be retained).
47
+ #
48
+ # filters = [/foo/, :bar, "nested.baz", /nested\.qux/]
49
+ #
50
+ # precompiled = ActiveSupport::ParameterFilter.precompile_filters(filters)
51
+ # # => [/(?-mix:foo)|(?i:bar)/, /(?i:nested\.baz)|(?-mix:nested\.qux)/]
52
+ #
53
+ # ActiveSupport::ParameterFilter.new(precompiled)
54
+ #
55
+ def self.precompile_filters(filters)
56
+ filters, patterns = filters.partition { |filter| filter.is_a?(Proc) }
57
+
58
+ patterns.map! do |pattern|
59
+ pattern.is_a?(Regexp) ? pattern : "(?i:#{Regexp.escape pattern.to_s})"
60
+ end
61
+
62
+ deep_patterns = patterns.extract! { |pattern| pattern.to_s.include?("\\.") }
63
+
64
+ filters << Regexp.new(patterns.join("|")) if patterns.any?
65
+ filters << Regexp.new(deep_patterns.join("|")) if deep_patterns.any?
66
+
67
+ filters
68
+ end
69
+
31
70
  # Create instance with given filters. Supported type of filters are +String+, +Regexp+, and +Proc+.
32
71
  # Other types of filters are treated as +String+ using +to_s+.
33
72
  # For +Proc+ filters, key, value, and optional original hash is passed to block arguments.
34
73
  #
35
74
  # ==== Options
36
75
  #
37
- # * <tt>:mask</tt> - A replaced object when filtered. Defaults to +"[FILTERED]"+
76
+ # * <tt>:mask</tt> - A replaced object when filtered. Defaults to <tt>"[FILTERED]"</tt>.
38
77
  def initialize(filters = [], mask: FILTERED)
39
- @filters = filters
40
78
  @mask = mask
79
+ compile_filters!(filters)
41
80
  end
42
81
 
43
82
  # Mask value of +params+ if key matches one of filters.
44
83
  def filter(params)
45
- compiled_filter.call(params)
84
+ @no_filters ? params.dup : call(params)
46
85
  end
47
86
 
48
87
  # Returns filtered value for given key. For +Proc+ filters, third block argument is not populated.
49
88
  def filter_param(key, value)
50
- @filters.empty? ? value : compiled_filter.value_for_key(key, value)
89
+ @no_filters ? value : value_for_key(key, value)
51
90
  end
52
91
 
53
92
  private
54
- def compiled_filter
55
- @compiled_filter ||= CompiledFilter.compile(@filters, mask: @mask)
56
- end
57
-
58
- class CompiledFilter # :nodoc:
59
- def self.compile(filters, mask:)
60
- return lambda { |params| params.dup } if filters.empty?
61
-
62
- strings, regexps, blocks = [], [], []
63
-
64
- filters.each do |item|
65
- case item
66
- when Proc
67
- blocks << item
68
- when Regexp
69
- regexps << item
93
+ def compile_filters!(filters)
94
+ @no_filters = filters.empty?
95
+ return if @no_filters
96
+
97
+ @regexps, strings = [], []
98
+ @deep_regexps, deep_strings = nil, nil
99
+ @blocks = nil
100
+
101
+ filters.each do |item|
102
+ case item
103
+ when Proc
104
+ (@blocks ||= []) << item
105
+ when Regexp
106
+ if item.to_s.include?("\\.")
107
+ (@deep_regexps ||= []) << item
108
+ else
109
+ @regexps << item
110
+ end
111
+ else
112
+ s = Regexp.escape(item.to_s)
113
+ if s.include?("\\.")
114
+ (deep_strings ||= []) << s
70
115
  else
71
- strings << Regexp.escape(item.to_s)
116
+ strings << s
72
117
  end
73
118
  end
119
+ end
74
120
 
75
- deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.") }
76
- deep_strings = strings.extract! { |s| s.include?("\\.") }
121
+ @regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
122
+ (@deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings
123
+ end
77
124
 
78
- regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
79
- deep_regexps << Regexp.new(deep_strings.join("|"), true) unless deep_strings.empty?
125
+ def call(params, full_parent_key = nil, original_params = params)
126
+ filtered_params = params.class.new
80
127
 
81
- new regexps, deep_regexps, blocks, mask: mask
128
+ params.each do |key, value|
129
+ filtered_params[key] = value_for_key(key, value, full_parent_key, original_params)
82
130
  end
83
131
 
84
- attr_reader :regexps, :deep_regexps, :blocks
132
+ filtered_params
133
+ end
85
134
 
86
- def initialize(regexps, deep_regexps, blocks, mask:)
87
- @regexps = regexps
88
- @deep_regexps = deep_regexps.any? ? deep_regexps : nil
89
- @blocks = blocks
90
- @mask = mask
135
+ def value_for_key(key, value, full_parent_key = nil, original_params = nil)
136
+ if @deep_regexps
137
+ full_key = full_parent_key ? "#{full_parent_key}.#{key}" : key.to_s
91
138
  end
92
139
 
93
- def call(params, parents = [], original_params = params)
94
- filtered_params = params.class.new
95
-
96
- params.each do |key, value|
97
- filtered_params[key] = value_for_key(key, value, parents, original_params)
98
- end
99
-
100
- filtered_params
140
+ if @regexps.any? { |r| r.match?(key.to_s) }
141
+ value = @mask
142
+ elsif @deep_regexps&.any? { |r| r.match?(full_key) }
143
+ value = @mask
144
+ elsif value.is_a?(Hash)
145
+ value = call(value, full_key, original_params)
146
+ elsif value.is_a?(Array)
147
+ value = value.map { |v| value_for_key(key, v, full_parent_key, original_params) }
148
+ elsif @blocks
149
+ key = key.dup if key.duplicable?
150
+ value = value.dup if value.duplicable?
151
+ @blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
101
152
  end
102
153
 
103
- def value_for_key(key, value, parents = [], original_params = nil)
104
- parents.push(key) if deep_regexps
105
- if regexps.any? { |r| r.match?(key.to_s) }
106
- value = @mask
107
- elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| r.match?(joined) }
108
- value = @mask
109
- elsif value.is_a?(Hash)
110
- value = call(value, parents, original_params)
111
- elsif value.is_a?(Array)
112
- # If we don't pop the current parent it will be duplicated as we
113
- # process each array value.
114
- parents.pop if deep_regexps
115
- value = value.map { |v| value_for_key(key, v, parents, original_params) }
116
- # Restore the parent stack after processing the array.
117
- parents.push(key) if deep_regexps
118
- elsif blocks.any?
119
- key = key.dup if key.duplicable?
120
- value = value.dup if value.duplicable?
121
- blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
122
- end
123
- parents.pop if deep_regexps
124
- value
125
- end
154
+ value
126
155
  end
127
156
  end
128
157
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = Active Support Proxy \Object
5
+ #
4
6
  # A class with no predefined methods that behaves similarly to Builder's
5
7
  # BlankSlate. Used for proxy classes.
6
8
  class ProxyObject < ::BasicObject
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This is private interface.
3
+ # This is a private interface.
4
4
  #
5
5
  # Rails components cherry pick from Active Support as needed, but there are a
6
6
  # few features that are used for sure in some way or another and it is not worth
@@ -13,9 +13,6 @@
13
13
  # Defines Object#blank? and Object#present?.
14
14
  require "active_support/core_ext/object/blank"
15
15
 
16
- # Rails own autoload, eager_load, etc.
17
- require "active_support/dependencies/autoload"
18
-
19
16
  # Support for ClassMethods and the included macro.
20
17
  require "active_support/concern"
21
18
 
@@ -9,6 +9,26 @@ module ActiveSupport
9
9
 
10
10
  config.eager_load_namespaces << ActiveSupport
11
11
 
12
+ initializer "active_support.deprecator", before: :load_environment_config do |app|
13
+ app.deprecators[:active_support] = ActiveSupport.deprecator
14
+ end
15
+
16
+ initializer "active_support.isolation_level" do |app|
17
+ config.after_initialize do
18
+ if level = app.config.active_support.delete(:isolation_level)
19
+ ActiveSupport::IsolatedExecutionState.isolation_level = level
20
+ end
21
+ end
22
+ end
23
+
24
+ initializer "active_support.raise_on_invalid_cache_expiration_time" do |app|
25
+ config.after_initialize do
26
+ if app.config.active_support.raise_on_invalid_cache_expiration_time
27
+ ActiveSupport::Cache::Store.raise_on_invalid_cache_expiration_time = true
28
+ end
29
+ end
30
+ end
31
+
12
32
  initializer "active_support.set_authenticated_message_encryption" do |app|
13
33
  config.after_initialize do
14
34
  unless app.config.active_support.use_authenticated_message_encryption.nil?
@@ -18,15 +38,48 @@ module ActiveSupport
18
38
  end
19
39
  end
20
40
 
41
+ initializer "active_support.reset_execution_context" do |app|
42
+ app.reloader.before_class_unload { ActiveSupport::ExecutionContext.clear }
43
+ app.executor.to_run { ActiveSupport::ExecutionContext.clear }
44
+ app.executor.to_complete { ActiveSupport::ExecutionContext.clear }
45
+ end
46
+
21
47
  initializer "active_support.reset_all_current_attributes_instances" do |app|
22
48
  app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
23
49
  app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
24
50
  app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
51
+
52
+ ActiveSupport.on_load(:active_support_test_case) do
53
+ if app.config.active_support.executor_around_test_case
54
+ require "active_support/executor/test_helper"
55
+ include ActiveSupport::Executor::TestHelper
56
+ else
57
+ require "active_support/current_attributes/test_helper"
58
+ include ActiveSupport::CurrentAttributes::TestHelper
59
+
60
+ require "active_support/execution_context/test_helper"
61
+ include ActiveSupport::ExecutionContext::TestHelper
62
+ end
63
+ end
25
64
  end
26
65
 
27
66
  initializer "active_support.deprecation_behavior" do |app|
28
- if deprecation = app.config.active_support.deprecation
29
- ActiveSupport::Deprecation.behavior = deprecation
67
+ if app.config.active_support.report_deprecations == false
68
+ app.deprecators.silenced = true
69
+ app.deprecators.behavior = :silence
70
+ app.deprecators.disallowed_behavior = :silence
71
+ else
72
+ if deprecation = app.config.active_support.deprecation
73
+ app.deprecators.behavior = deprecation
74
+ end
75
+
76
+ if disallowed_deprecation = app.config.active_support.disallowed_deprecation
77
+ app.deprecators.disallowed_behavior = disallowed_deprecation
78
+ end
79
+
80
+ if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings
81
+ app.deprecators.disallowed_warnings = disallowed_warnings
82
+ end
30
83
  end
31
84
  end
32
85
 
@@ -64,17 +117,48 @@ module ActiveSupport
64
117
 
65
118
  initializer "active_support.set_configs" do |app|
66
119
  app.config.active_support.each do |k, v|
67
- k = "#{k}="
68
- ActiveSupport.send(k, v) if ActiveSupport.respond_to? k
120
+ if k == "disable_to_s_conversion"
121
+ ActiveSupport.deprecator.warn("config.active_support.disable_to_s_conversion is deprecated and will be removed in Rails 7.2.")
122
+ elsif k == "remove_deprecated_time_with_zone_name"
123
+ ActiveSupport.deprecator.warn("config.active_support.remove_deprecated_time_with_zone_name is deprecated and will be removed in Rails 7.2.")
124
+ elsif k == "use_rfc4122_namespaced_uuids"
125
+ ActiveSupport.deprecator.warn("config.active_support.use_rfc4122_namespaced_uuids is deprecated and will be removed in Rails 7.2.")
126
+ else
127
+ k = "#{k}="
128
+ ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
129
+ end
69
130
  end
70
131
  end
71
132
 
72
133
  initializer "active_support.set_hash_digest_class" do |app|
73
134
  config.after_initialize do
74
- if app.config.active_support.use_sha1_digests
75
- ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
135
+ if klass = app.config.active_support.hash_digest_class
136
+ ActiveSupport::Digest.hash_digest_class = klass
137
+ end
138
+ end
139
+ end
140
+
141
+ initializer "active_support.set_key_generator_hash_digest_class" do |app|
142
+ config.after_initialize do
143
+ if klass = app.config.active_support.key_generator_hash_digest_class
144
+ ActiveSupport::KeyGenerator.hash_digest_class = klass
76
145
  end
77
146
  end
78
147
  end
148
+
149
+ initializer "active_support.set_default_message_serializer" do |app|
150
+ config.after_initialize do
151
+ if message_serializer = app.config.active_support.message_serializer
152
+ ActiveSupport::Messages::Codec.default_serializer = message_serializer
153
+ end
154
+ end
155
+ end
156
+
157
+ initializer "active_support.set_use_message_serializer_for_metadata" do |app|
158
+ config.after_initialize do
159
+ ActiveSupport::Messages::Metadata.use_message_serializer_for_metadata =
160
+ app.config.active_support.use_message_serializer_for_metadata
161
+ end
162
+ end
79
163
  end
80
164
  end
@@ -4,7 +4,8 @@ require "active_support/execution_wrapper"
4
4
  require "active_support/executor"
5
5
 
6
6
  module ActiveSupport
7
- #--
7
+ # = Active Support \Reloader
8
+ #
8
9
  # This class defines several callbacks:
9
10
  #
10
11
  # to_prepare -- Run once at application startup, and also from
@@ -67,9 +68,16 @@ module ActiveSupport
67
68
  end
68
69
 
69
70
  # Run the supplied block as a work unit, reloading code as needed
70
- def self.wrap
71
- executor.wrap do
72
- super
71
+ def self.wrap(**kwargs)
72
+ return yield if active?
73
+
74
+ executor.wrap(**kwargs) do
75
+ instance = run!
76
+ begin
77
+ yield
78
+ ensure
79
+ instance.complete!
80
+ end
73
81
  end
74
82
  end
75
83
 
@@ -5,6 +5,8 @@ require "active_support/core_ext/class/attribute"
5
5
  require "active_support/core_ext/string/inflections"
6
6
 
7
7
  module ActiveSupport
8
+ # = Active Support \Rescuable
9
+ #
8
10
  # Rescuable module adds support for easier exception handling.
9
11
  module Rescuable
10
12
  extend Concern
@@ -14,12 +16,12 @@ module ActiveSupport
14
16
  end
15
17
 
16
18
  module ClassMethods
17
- # Rescue exceptions raised in controller actions.
19
+ # Registers exception classes with a handler to be called by <tt>rescue_with_handler</tt>.
18
20
  #
19
21
  # <tt>rescue_from</tt> receives a series of exception classes or class
20
- # names, and a trailing <tt>:with</tt> option with the name of a method
21
- # or a Proc object to be called to handle them. Alternatively a block can
22
- # be given.
22
+ # names, and an exception handler specified by a trailing <tt>:with</tt>
23
+ # option containing the name of a method or a Proc object. Alternatively, a block
24
+ # can be given as the handler.
23
25
  #
24
26
  # Handlers that take one argument will be called with the exception, so
25
27
  # that the exception can be inspected when dealing with it.
@@ -30,20 +32,20 @@ module ActiveSupport
30
32
  # any.
31
33
  #
32
34
  # class ApplicationController < ActionController::Base
33
- # rescue_from User::NotAuthorized, with: :deny_access # self defined exception
34
- # rescue_from ActiveRecord::RecordInvalid, with: :show_errors
35
+ # rescue_from User::NotAuthorized, with: :deny_access
36
+ # rescue_from ActiveRecord::RecordInvalid, with: :show_record_errors
35
37
  #
36
- # rescue_from 'MyAppError::Base' do |exception|
37
- # render xml: exception, status: 500
38
+ # rescue_from "MyApp::BaseError" do |exception|
39
+ # redirect_to root_url, alert: exception.message
38
40
  # end
39
41
  #
40
42
  # private
41
43
  # def deny_access
42
- # ...
44
+ # head :forbidden
43
45
  # end
44
46
  #
45
- # def show_errors(exception)
46
- # exception.record.new_record? ? ...
47
+ # def show_record_errors(exception)
48
+ # redirect_back_or_to root_url, alert: exception.record.errors.full_messages.to_sentence
47
49
  # end
48
50
  # end
49
51
  #
@@ -74,12 +76,12 @@ module ActiveSupport
74
76
  # Matches an exception to a handler based on the exception class.
75
77
  #
76
78
  # If no handler matches the exception, check for a handler matching the
77
- # (optional) exception.cause. If no handler matches the exception or its
79
+ # (optional) +exception.cause+. If no handler matches the exception or its
78
80
  # cause, this returns +nil+, so you can deal with unhandled exceptions.
79
81
  # Be sure to re-raise unhandled exceptions if this is what you expect.
80
82
  #
81
83
  # begin
82
- #
84
+ # # ...
83
85
  # rescue => exception
84
86
  # rescue_with_handler(exception) || raise
85
87
  # end
@@ -100,7 +102,7 @@ module ActiveSupport
100
102
  end
101
103
  end
102
104
 
103
- def handler_for_rescue(exception, object: self) #:nodoc:
105
+ def handler_for_rescue(exception, object: self) # :nodoc:
104
106
  case rescuer = find_rescue_handler(exception)
105
107
  when Symbol
106
108
  method = object.method(rescuer)
@@ -160,14 +162,14 @@ module ActiveSupport
160
162
  end
161
163
 
162
164
  # Delegates to the class method, but uses the instance as the subject for
163
- # rescue_from handlers (method calls, instance_exec blocks).
165
+ # rescue_from handlers (method calls, +instance_exec+ blocks).
164
166
  def rescue_with_handler(exception)
165
167
  self.class.rescue_with_handler exception, object: self
166
168
  end
167
169
 
168
170
  # Internal handler lookup. Delegates to class method. Some libraries call
169
171
  # this directly, so keeping it around for compatibility.
170
- def handler_for_rescue(exception) #:nodoc:
172
+ def handler_for_rescue(exception) # :nodoc:
171
173
  self.class.handler_for_rescue exception, object: self
172
174
  end
173
175
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module RubyFeatures # :nodoc:
5
+ CLASS_SUBCLASSES = Class.method_defined?(:subclasses) # RUBY_VERSION >= "3.1"
6
+ end
7
+ end