activesupport 7.0.0 → 7.2.2.1

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +156 -255
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +3 -1
  7. data/lib/active_support/backtrace_cleaner.rb +41 -9
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/broadcast_logger.rb +251 -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 +49 -17
  14. data/lib/active_support/cache/mem_cache_store.rb +111 -129
  15. data/lib/active_support/cache/memory_store.rb +81 -26
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +175 -154
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +31 -13
  20. data/lib/active_support/cache.rb +457 -377
  21. data/lib/active_support/callbacks.rb +123 -139
  22. data/lib/active_support/code_generator.rb +15 -10
  23. data/lib/active_support/concern.rb +4 -2
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/configurable.rb +12 -2
  27. data/lib/active_support/core_ext/array/conversions.rb +7 -9
  28. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  29. data/lib/active_support/core_ext/array.rb +0 -1
  30. data/lib/active_support/core_ext/class/subclasses.rb +4 -15
  31. data/lib/active_support/core_ext/date/blank.rb +4 -0
  32. data/lib/active_support/core_ext/date/calculations.rb +20 -5
  33. data/lib/active_support/core_ext/date/conversions.rb +15 -16
  34. data/lib/active_support/core_ext/date.rb +0 -1
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  36. data/lib/active_support/core_ext/date_and_time/compatibility.rb +29 -2
  37. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  38. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  39. data/lib/active_support/core_ext/date_time/conversions.rb +15 -15
  40. data/lib/active_support/core_ext/date_time.rb +0 -1
  41. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  42. data/lib/active_support/core_ext/enumerable.rb +51 -101
  43. data/lib/active_support/core_ext/erb/util.rb +201 -0
  44. data/lib/active_support/core_ext/file/atomic.rb +2 -0
  45. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  46. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  49. data/lib/active_support/core_ext/hash/keys.rb +7 -7
  50. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  51. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  52. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  53. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  54. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +38 -20
  55. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  56. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  57. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  58. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  60. data/lib/active_support/core_ext/numeric/conversions.rb +77 -75
  61. data/lib/active_support/core_ext/numeric.rb +0 -1
  62. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  63. data/lib/active_support/core_ext/object/blank.rb +45 -1
  64. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  65. data/lib/active_support/core_ext/object/duplicable.rb +25 -16
  66. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  67. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  68. data/lib/active_support/core_ext/object/json.rb +17 -7
  69. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  70. data/lib/active_support/core_ext/object/with.rb +46 -0
  71. data/lib/active_support/core_ext/object/with_options.rb +9 -9
  72. data/lib/active_support/core_ext/object.rb +1 -0
  73. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  74. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  75. data/lib/active_support/core_ext/pathname.rb +1 -0
  76. data/lib/active_support/core_ext/range/conversions.rb +32 -11
  77. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  78. data/lib/active_support/core_ext/range.rb +1 -2
  79. data/lib/active_support/core_ext/securerandom.rb +2 -6
  80. data/lib/active_support/core_ext/string/conversions.rb +3 -3
  81. data/lib/active_support/core_ext/string/filters.rb +21 -15
  82. data/lib/active_support/core_ext/string/indent.rb +1 -1
  83. data/lib/active_support/core_ext/string/inflections.rb +16 -9
  84. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  85. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  86. data/lib/active_support/core_ext/string/output_safety.rb +39 -150
  87. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  88. data/lib/active_support/core_ext/time/calculations.rb +42 -32
  89. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  90. data/lib/active_support/core_ext/time/conversions.rb +13 -15
  91. data/lib/active_support/core_ext/time/zones.rb +8 -9
  92. data/lib/active_support/core_ext/time.rb +0 -1
  93. data/lib/active_support/core_ext.rb +0 -1
  94. data/lib/active_support/current_attributes.rb +53 -46
  95. data/lib/active_support/deep_mergeable.rb +53 -0
  96. data/lib/active_support/delegation.rb +202 -0
  97. data/lib/active_support/dependencies/autoload.rb +9 -16
  98. data/lib/active_support/deprecation/behaviors.rb +65 -42
  99. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  100. data/lib/active_support/deprecation/deprecators.rb +104 -0
  101. data/lib/active_support/deprecation/disallowed.rb +6 -8
  102. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  103. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  104. data/lib/active_support/deprecation/reporting.rb +49 -27
  105. data/lib/active_support/deprecation.rb +39 -9
  106. data/lib/active_support/deprecator.rb +7 -0
  107. data/lib/active_support/descendants_tracker.rb +66 -175
  108. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  109. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  110. data/lib/active_support/duration.rb +13 -7
  111. data/lib/active_support/encrypted_configuration.rb +63 -10
  112. data/lib/active_support/encrypted_file.rb +29 -13
  113. data/lib/active_support/environment_inquirer.rb +22 -2
  114. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  115. data/lib/active_support/error_reporter.rb +160 -36
  116. data/lib/active_support/evented_file_update_checker.rb +19 -7
  117. data/lib/active_support/execution_wrapper.rb +23 -28
  118. data/lib/active_support/file_update_checker.rb +5 -3
  119. data/lib/active_support/fork_tracker.rb +4 -32
  120. data/lib/active_support/gem_version.rb +4 -4
  121. data/lib/active_support/gzip.rb +2 -0
  122. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  123. data/lib/active_support/html_safe_translation.rb +19 -6
  124. data/lib/active_support/i18n.rb +1 -1
  125. data/lib/active_support/i18n_railtie.rb +20 -13
  126. data/lib/active_support/inflector/inflections.rb +2 -0
  127. data/lib/active_support/inflector/methods.rb +28 -18
  128. data/lib/active_support/inflector/transliterate.rb +4 -2
  129. data/lib/active_support/isolated_execution_state.rb +39 -19
  130. data/lib/active_support/json/decoding.rb +2 -1
  131. data/lib/active_support/json/encoding.rb +25 -43
  132. data/lib/active_support/key_generator.rb +13 -5
  133. data/lib/active_support/lazy_load_hooks.rb +33 -7
  134. data/lib/active_support/locale/en.yml +2 -0
  135. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  136. data/lib/active_support/log_subscriber.rb +76 -36
  137. data/lib/active_support/logger.rb +22 -60
  138. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  139. data/lib/active_support/message_encryptor.rb +200 -55
  140. data/lib/active_support/message_encryptors.rb +141 -0
  141. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  142. data/lib/active_support/message_pack/extensions.rb +305 -0
  143. data/lib/active_support/message_pack/serializer.rb +63 -0
  144. data/lib/active_support/message_pack.rb +50 -0
  145. data/lib/active_support/message_verifier.rb +220 -89
  146. data/lib/active_support/message_verifiers.rb +135 -0
  147. data/lib/active_support/messages/codec.rb +65 -0
  148. data/lib/active_support/messages/metadata.rb +111 -45
  149. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  150. data/lib/active_support/messages/rotator.rb +34 -32
  151. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  152. data/lib/active_support/multibyte/chars.rb +4 -2
  153. data/lib/active_support/multibyte/unicode.rb +9 -37
  154. data/lib/active_support/notifications/fanout.rb +248 -87
  155. data/lib/active_support/notifications/instrumenter.rb +93 -25
  156. data/lib/active_support/notifications.rb +38 -31
  157. data/lib/active_support/number_helper/number_converter.rb +16 -7
  158. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  159. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  160. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  161. data/lib/active_support/number_helper.rb +379 -317
  162. data/lib/active_support/option_merger.rb +4 -4
  163. data/lib/active_support/ordered_hash.rb +3 -3
  164. data/lib/active_support/ordered_options.rb +68 -16
  165. data/lib/active_support/parameter_filter.rb +103 -84
  166. data/lib/active_support/proxy_object.rb +8 -3
  167. data/lib/active_support/railtie.rb +30 -25
  168. data/lib/active_support/reloader.rb +13 -5
  169. data/lib/active_support/rescuable.rb +12 -10
  170. data/lib/active_support/secure_compare_rotator.rb +17 -10
  171. data/lib/active_support/string_inquirer.rb +4 -2
  172. data/lib/active_support/subscriber.rb +10 -27
  173. data/lib/active_support/syntax_error_proxy.rb +60 -0
  174. data/lib/active_support/tagged_logging.rb +64 -25
  175. data/lib/active_support/test_case.rb +160 -7
  176. data/lib/active_support/testing/assertions.rb +29 -13
  177. data/lib/active_support/testing/autorun.rb +0 -2
  178. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  179. data/lib/active_support/testing/deprecation.rb +20 -27
  180. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  181. data/lib/active_support/testing/isolation.rb +46 -33
  182. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  183. data/lib/active_support/testing/parallelization/server.rb +3 -0
  184. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  185. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  186. data/lib/active_support/testing/stream.rb +1 -1
  187. data/lib/active_support/testing/strict_warnings.rb +43 -0
  188. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  189. data/lib/active_support/testing/time_helpers.rb +38 -16
  190. data/lib/active_support/time_with_zone.rb +28 -54
  191. data/lib/active_support/values/time_zone.rb +26 -15
  192. data/lib/active_support/version.rb +1 -1
  193. data/lib/active_support/xml_mini/jdom.rb +3 -10
  194. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  195. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  196. data/lib/active_support/xml_mini/rexml.rb +1 -1
  197. data/lib/active_support/xml_mini.rb +13 -4
  198. data/lib/active_support.rb +15 -3
  199. metadata +142 -21
  200. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  201. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
  202. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
  203. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  204. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
  205. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
  206. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  207. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
  208. data/lib/active_support/core_ext/uri.rb +0 -5
  209. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  210. data/lib/active_support/per_thread_registry.rb +0 -65
  211. data/lib/active_support/ruby_features.rb +0 -7
@@ -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)
@@ -31,8 +31,8 @@ module ActiveSupport
31
31
  end
32
32
  end
33
33
 
34
- def respond_to_missing?(*arguments)
35
- @context.respond_to?(*arguments)
34
+ def respond_to_missing?(...)
35
+ @context.respond_to?(...)
36
36
  end
37
37
  end
38
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,9 +17,9 @@ 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
24
  class OrderedHash < ::Hash # :nodoc:
25
25
  def to_yaml_type
@@ -3,6 +3,8 @@
3
3
  require "active_support/core_ext/object/blank"
4
4
 
5
5
  module ActiveSupport
6
+ # = Ordered Options
7
+ #
6
8
  # +OrderedOptions+ inherits from +Hash+ and provides dynamic accessor methods.
7
9
  #
8
10
  # With a +Hash+, key-value pairs are typically managed like this:
@@ -40,18 +42,18 @@ module ActiveSupport
40
42
  super(key.to_sym)
41
43
  end
42
44
 
43
- def method_missing(name, *args)
44
- name_string = +name.to_s
45
- if name_string.chomp!("=")
46
- self[name_string] = args.first
47
- else
48
- bangs = name_string.chomp!("!")
45
+ def dig(key, *identifiers)
46
+ super(key.to_sym, *identifiers)
47
+ end
49
48
 
50
- if bangs
51
- self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
52
- else
53
- self[name_string]
54
- end
49
+ def method_missing(method, *args)
50
+ if method.end_with?("=")
51
+ self[method.name.chomp("=")] = args.first
52
+ elsif method.end_with?("!")
53
+ name_string = method.name.chomp("!")
54
+ self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
55
+ else
56
+ self[method.name]
55
57
  end
56
58
  end
57
59
 
@@ -68,7 +70,9 @@ module ActiveSupport
68
70
  end
69
71
  end
70
72
 
71
- # +InheritableOptions+ provides a constructor to build an +OrderedOptions+
73
+ # = Inheritable Options
74
+ #
75
+ # +InheritableOptions+ provides a constructor to build an OrderedOptions
72
76
  # hash inherited from another hash.
73
77
  #
74
78
  # Use this if you already have some hash and you want to create a new one based on it.
@@ -76,20 +80,68 @@ module ActiveSupport
76
80
  # h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
77
81
  # h.girl # => 'Mary'
78
82
  # h.boy # => 'John'
83
+ #
84
+ # If the existing hash has string keys, call Hash#symbolize_keys on it.
85
+ #
86
+ # h = ActiveSupport::InheritableOptions.new({ 'girl' => 'Mary', 'boy' => 'John' }.symbolize_keys)
87
+ # h.girl # => 'Mary'
88
+ # h.boy # => 'John'
79
89
  class InheritableOptions < OrderedOptions
80
90
  def initialize(parent = nil)
81
- if parent.kind_of?(OrderedOptions)
91
+ @parent = parent
92
+ if @parent.kind_of?(OrderedOptions)
82
93
  # use the faster _get when dealing with OrderedOptions
83
- super() { |h, k| parent._get(k) }
84
- elsif parent
85
- super() { |h, k| parent[k] }
94
+ super() { |h, k| @parent._get(k) }
95
+ elsif @parent
96
+ super() { |h, k| @parent[k] }
86
97
  else
87
98
  super()
99
+ @parent = {}
88
100
  end
89
101
  end
90
102
 
103
+ def to_h
104
+ @parent.merge(self)
105
+ end
106
+
107
+ def ==(other)
108
+ to_h == other.to_h
109
+ end
110
+
111
+ def inspect
112
+ "#<#{self.class.name} #{to_h.inspect}>"
113
+ end
114
+
115
+ def to_s
116
+ to_h.to_s
117
+ end
118
+
119
+ def pretty_print(pp)
120
+ pp.pp_hash(to_h)
121
+ end
122
+
123
+ alias_method :own_key?, :key?
124
+ private :own_key?
125
+
126
+ def key?(key)
127
+ super || @parent.key?(key)
128
+ end
129
+
130
+ def overridden?(key)
131
+ !!(@parent && @parent.key?(key) && own_key?(key.to_sym))
132
+ end
133
+
91
134
  def inheritable_copy
92
135
  self.class.new(self)
93
136
  end
137
+
138
+ def to_a
139
+ entries
140
+ end
141
+
142
+ def each(&block)
143
+ to_h.each(&block)
144
+ self
145
+ end
94
146
  end
95
147
  end
@@ -1,37 +1,72 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/duplicable"
4
+ require "active_support/core_ext/array/extract"
4
5
 
5
6
  module ActiveSupport
6
- # +ParameterFilter+ allows you to specify keys for sensitive data from
7
- # hash-like object and replace corresponding value. Filtering only certain
8
- # sub-keys from a hash is possible by using the dot notation:
9
- # 'credit_card.number'. If a proc is given, each key and value of a hash and
10
- # all sub-hashes are passed to it, where the value or the key can be replaced
11
- # using String#replace or similar methods.
7
+ # = Active Support Parameter Filter
12
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.
13
20
  # ActiveSupport::ParameterFilter.new([:password])
14
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
15
21
  #
22
+ # # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
16
23
  # ActiveSupport::ParameterFilter.new([:foo, "bar"])
17
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
18
24
  #
19
- # ActiveSupport::ParameterFilter.new([/\Apin\z/i, /\Apin_/i])
20
- # => replaces the value for the exact (case-insensitive) key 'pin' and all
21
- # (case-insensitive) keys beginning with 'pin_', with "[FILTERED]".
22
- # Does not match keys with 'pin' as a substring, such as 'shipping_id'.
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_/])
23
29
  #
30
+ # # Replaces the value for :code in `{ credit_card: { code: "xxxx" } }`.
31
+ # # Does not change `{ file: { code: "xxxx" } }`.
24
32
  # ActiveSupport::ParameterFilter.new(["credit_card.code"])
25
- # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
26
- # change { file: { code: "xxxx"} }
27
33
  #
34
+ # # Reverses values for keys that match /secret/i.
28
35
  # ActiveSupport::ParameterFilter.new([-> (k, v) do
29
36
  # v.reverse! if /secret/i.match?(k)
30
37
  # end])
31
- # => reverses the value to all keys matching /secret/i
38
+ #
32
39
  class ParameterFilter
33
40
  FILTERED = "[FILTERED]" # :nodoc:
34
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
+
35
70
  # Create instance with given filters. Supported type of filters are +String+, +Regexp+, and +Proc+.
36
71
  # Other types of filters are treated as +String+ using +to_s+.
37
72
  # For +Proc+ filters, key, value, and optional original hash is passed to block arguments.
@@ -40,99 +75,83 @@ module ActiveSupport
40
75
  #
41
76
  # * <tt>:mask</tt> - A replaced object when filtered. Defaults to <tt>"[FILTERED]"</tt>.
42
77
  def initialize(filters = [], mask: FILTERED)
43
- @filters = filters
44
78
  @mask = mask
79
+ compile_filters!(filters)
45
80
  end
46
81
 
47
82
  # Mask value of +params+ if key matches one of filters.
48
83
  def filter(params)
49
- compiled_filter.call(params)
84
+ @no_filters ? params.dup : call(params)
50
85
  end
51
86
 
52
87
  # Returns filtered value for given key. For +Proc+ filters, third block argument is not populated.
53
88
  def filter_param(key, value)
54
- @filters.empty? ? value : compiled_filter.value_for_key(key, value)
89
+ @no_filters ? value : value_for_key(key, value)
55
90
  end
56
91
 
57
92
  private
58
- def compiled_filter
59
- @compiled_filter ||= CompiledFilter.compile(@filters, mask: @mask)
60
- end
61
-
62
- class CompiledFilter # :nodoc:
63
- def self.compile(filters, mask:)
64
- return lambda { |params| params.dup } if filters.empty?
65
-
66
- strings, regexps, blocks, deep_regexps, deep_strings = [], [], [], nil, nil
67
-
68
- filters.each do |item|
69
- case item
70
- when Proc
71
- blocks << item
72
- when Regexp
73
- if item.to_s.include?("\\.")
74
- (deep_regexps ||= []) << item
75
- else
76
- regexps << item
77
- end
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
78
108
  else
79
- s = Regexp.escape(item.to_s)
80
- if s.include?("\\.")
81
- (deep_strings ||= []) << s
82
- else
83
- strings << s
84
- end
109
+ @regexps << item
110
+ end
111
+ else
112
+ s = Regexp.escape(item.to_s)
113
+ if s.include?("\\.")
114
+ (deep_strings ||= []) << s
115
+ else
116
+ strings << s
85
117
  end
86
118
  end
87
-
88
- regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
89
- (deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings&.any?
90
-
91
- new regexps, deep_regexps, blocks, mask: mask
92
119
  end
93
120
 
94
- attr_reader :regexps, :deep_regexps, :blocks
121
+ @regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
122
+ (@deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings
123
+ end
95
124
 
96
- def initialize(regexps, deep_regexps, blocks, mask:)
97
- @regexps = regexps
98
- @deep_regexps = deep_regexps&.any? ? deep_regexps : nil
99
- @blocks = blocks
100
- @mask = mask
101
- end
125
+ def call(params, full_parent_key = nil, original_params = params)
126
+ filtered_params = params.class.new
102
127
 
103
- def call(params, parents = [], original_params = params)
104
- filtered_params = params.class.new
128
+ params.each do |key, value|
129
+ filtered_params[key] = value_for_key(key, value, full_parent_key, original_params)
130
+ end
105
131
 
106
- params.each do |key, value|
107
- filtered_params[key] = value_for_key(key, value, parents, original_params)
108
- end
132
+ filtered_params
133
+ end
109
134
 
110
- filtered_params
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
111
138
  end
112
139
 
113
- def value_for_key(key, value, parents = [], original_params = nil)
114
- parents.push(key) if deep_regexps
115
- if regexps.any? { |r| r.match?(key.to_s) }
116
- value = @mask
117
- elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| r.match?(joined) }
118
- value = @mask
119
- elsif value.is_a?(Hash)
120
- value = call(value, parents, original_params)
121
- elsif value.is_a?(Array)
122
- # If we don't pop the current parent it will be duplicated as we
123
- # process each array value.
124
- parents.pop if deep_regexps
125
- value = value.map { |v| value_for_key(key, v, parents, original_params) }
126
- # Restore the parent stack after processing the array.
127
- parents.push(key) if deep_regexps
128
- elsif blocks.any?
129
- key = key.dup if key.duplicable?
130
- value = value.dup if value.duplicable?
131
- blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
132
- end
133
- parents.pop if deep_regexps
134
- value
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) }
135
152
  end
153
+
154
+ value
136
155
  end
137
156
  end
138
157
  end
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
- # A class with no predefined methods that behaves similarly to Builder's
5
- # BlankSlate. Used for proxy classes.
6
- class ProxyObject < ::BasicObject
4
+ class ProxyObject < ::BasicObject # :nodoc:
7
5
  undef_method :==
8
6
  undef_method :equal?
9
7
 
@@ -11,5 +9,12 @@ module ActiveSupport
11
9
  def raise(*args)
12
10
  ::Object.send(:raise, *args)
13
11
  end
12
+
13
+ def self.inherited(_subclass)
14
+ ::ActiveSupport.deprecator.warn(<<~MSG)
15
+ ActiveSupport::ProxyObject is deprecated and will be removed in Rails 8.0.
16
+ Use Ruby's built-in BasicObject instead.
17
+ MSG
18
+ end
14
19
  end
15
20
  end
@@ -6,21 +6,25 @@ require "active_support/i18n_railtie"
6
6
  module ActiveSupport
7
7
  class Railtie < Rails::Railtie # :nodoc:
8
8
  config.active_support = ActiveSupport::OrderedOptions.new
9
- config.active_support.disable_to_s_conversion = false
10
9
 
11
10
  config.eager_load_namespaces << ActiveSupport
12
11
 
12
+ initializer "active_support.deprecator", before: :load_environment_config do |app|
13
+ app.deprecators[:active_support] = ActiveSupport.deprecator
14
+ end
15
+
13
16
  initializer "active_support.isolation_level" do |app|
14
- if level = app.config.active_support.delete(:isolation_level)
15
- ActiveSupport::IsolatedExecutionState.isolation_level = level
17
+ config.after_initialize do
18
+ if level = app.config.active_support.delete(:isolation_level)
19
+ ActiveSupport::IsolatedExecutionState.isolation_level = level
20
+ end
16
21
  end
17
22
  end
18
23
 
19
- initializer "active_support.remove_deprecated_time_with_zone_name" do |app|
24
+ initializer "active_support.raise_on_invalid_cache_expiration_time" do |app|
20
25
  config.after_initialize do
21
- if app.config.active_support.remove_deprecated_time_with_zone_name
22
- require "active_support/time_with_zone"
23
- TimeWithZone.singleton_class.remove_method(:name)
26
+ if app.config.active_support.raise_on_invalid_cache_expiration_time
27
+ ActiveSupport::Cache::Store.raise_on_invalid_cache_expiration_time = true
24
28
  end
25
29
  end
26
30
  end
@@ -41,14 +45,12 @@ module ActiveSupport
41
45
  end
42
46
 
43
47
  initializer "active_support.reset_all_current_attributes_instances" do |app|
44
- executor_around_test_case = app.config.active_support.executor_around_test_case
45
-
46
48
  app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
47
49
  app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
48
50
  app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
49
51
 
50
52
  ActiveSupport.on_load(:active_support_test_case) do
51
- if executor_around_test_case
53
+ if app.config.active_support.executor_around_test_case
52
54
  require "active_support/executor/test_helper"
53
55
  include ActiveSupport::Executor::TestHelper
54
56
  else
@@ -63,20 +65,20 @@ module ActiveSupport
63
65
 
64
66
  initializer "active_support.deprecation_behavior" do |app|
65
67
  if app.config.active_support.report_deprecations == false
66
- ActiveSupport::Deprecation.silenced = true
67
- ActiveSupport::Deprecation.behavior = :silence
68
- ActiveSupport::Deprecation.disallowed_behavior = :silence
68
+ app.deprecators.silenced = true
69
+ app.deprecators.behavior = :silence
70
+ app.deprecators.disallowed_behavior = :silence
69
71
  else
70
72
  if deprecation = app.config.active_support.deprecation
71
- ActiveSupport::Deprecation.behavior = deprecation
73
+ app.deprecators.behavior = deprecation
72
74
  end
73
75
 
74
76
  if disallowed_deprecation = app.config.active_support.disallowed_deprecation
75
- ActiveSupport::Deprecation.disallowed_behavior = disallowed_deprecation
77
+ app.deprecators.disallowed_behavior = disallowed_deprecation
76
78
  end
77
79
 
78
80
  if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings
79
- ActiveSupport::Deprecation.disallowed_warnings = disallowed_warnings
81
+ app.deprecators.disallowed_warnings = disallowed_warnings
80
82
  end
81
83
  end
82
84
  end
@@ -87,10 +89,11 @@ module ActiveSupport
87
89
  begin
88
90
  TZInfo::DataSource.get
89
91
  rescue TZInfo::DataSourceNotFound => e
90
- raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
92
+ raise e.exception('tzinfo-data is not present. Please add gem "tzinfo-data" to your Gemfile and run bundle install')
91
93
  end
92
94
  require "active_support/core_ext/time/zones"
93
95
  Time.zone_default = Time.find_zone!(app.config.time_zone)
96
+ config.eager_load_namespaces << TZInfo
94
97
  end
95
98
 
96
99
  # Sets the default week start
@@ -113,10 +116,6 @@ module ActiveSupport
113
116
  end
114
117
  end
115
118
 
116
- initializer "active_support.set_error_reporter" do |app|
117
- ActiveSupport.error_reporter = app.executor.error_reporter
118
- end
119
-
120
119
  initializer "active_support.set_configs" do |app|
121
120
  app.config.active_support.each do |k, v|
122
121
  k = "#{k}="
@@ -140,13 +139,19 @@ module ActiveSupport
140
139
  end
141
140
  end
142
141
 
143
- initializer "active_support.set_rfc4122_namespaced_uuids" do |app|
142
+ initializer "active_support.set_default_message_serializer" do |app|
144
143
  config.after_initialize do
145
- if app.config.active_support.use_rfc4122_namespaced_uuids
146
- require "active_support/core_ext/digest"
147
- ::Digest::UUID.use_rfc4122_namespaced_uuids = app.config.active_support.use_rfc4122_namespaced_uuids
144
+ if message_serializer = app.config.active_support.message_serializer
145
+ ActiveSupport::Messages::Codec.default_serializer = message_serializer
148
146
  end
149
147
  end
150
148
  end
149
+
150
+ initializer "active_support.set_use_message_serializer_for_metadata" do |app|
151
+ config.after_initialize do
152
+ ActiveSupport::Messages::Metadata.use_message_serializer_for_metadata =
153
+ app.config.active_support.use_message_serializer_for_metadata
154
+ end
155
+ end
151
156
  end
152
157
  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
@@ -58,7 +59,7 @@ module ActiveSupport
58
59
  prepare!
59
60
  end
60
61
 
61
- def self.run! # :nodoc:
62
+ def self.run!(reset: false) # :nodoc:
62
63
  if check!
63
64
  super
64
65
  else
@@ -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
@@ -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
@@ -160,7 +162,7 @@ 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