activesupport 7.0.8.3 → 7.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +731 -303
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +2 -0
  7. data/lib/active_support/backtrace_cleaner.rb +25 -5
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/builder.rb +1 -1
  10. data/lib/active_support/cache/coder.rb +153 -0
  11. data/lib/active_support/cache/entry.rb +128 -0
  12. data/lib/active_support/cache/file_store.rb +36 -9
  13. data/lib/active_support/cache/mem_cache_store.rb +84 -68
  14. data/lib/active_support/cache/memory_store.rb +76 -24
  15. data/lib/active_support/cache/null_store.rb +6 -0
  16. data/lib/active_support/cache/redis_cache_store.rb +126 -131
  17. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  18. data/lib/active_support/cache/strategy/local_cache.rb +20 -8
  19. data/lib/active_support/cache.rb +304 -246
  20. data/lib/active_support/callbacks.rb +38 -18
  21. data/lib/active_support/concern.rb +4 -2
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  23. data/lib/active_support/concurrency/null_lock.rb +13 -0
  24. data/lib/active_support/configurable.rb +10 -0
  25. data/lib/active_support/core_ext/array/conversions.rb +2 -1
  26. data/lib/active_support/core_ext/array.rb +0 -1
  27. data/lib/active_support/core_ext/class/subclasses.rb +13 -10
  28. data/lib/active_support/core_ext/date/conversions.rb +1 -0
  29. data/lib/active_support/core_ext/date.rb +0 -1
  30. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  31. data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
  32. data/lib/active_support/core_ext/date_time.rb +0 -1
  33. data/lib/active_support/core_ext/digest/uuid.rb +1 -10
  34. data/lib/active_support/core_ext/enumerable.rb +3 -75
  35. data/lib/active_support/core_ext/erb/util.rb +196 -0
  36. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  37. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  38. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  39. data/lib/active_support/core_ext/module/delegation.rb +40 -11
  40. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  41. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  42. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  43. data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
  44. data/lib/active_support/core_ext/numeric.rb +0 -1
  45. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  46. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  47. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  48. data/lib/active_support/core_ext/object/json.rb +10 -2
  49. data/lib/active_support/core_ext/object/with.rb +44 -0
  50. data/lib/active_support/core_ext/object/with_options.rb +3 -3
  51. data/lib/active_support/core_ext/object.rb +1 -0
  52. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  53. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  54. data/lib/active_support/core_ext/pathname.rb +1 -0
  55. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  56. data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
  57. data/lib/active_support/core_ext/range.rb +1 -2
  58. data/lib/active_support/core_ext/securerandom.rb +24 -12
  59. data/lib/active_support/core_ext/string/filters.rb +20 -14
  60. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  61. data/lib/active_support/core_ext/string/output_safety.rb +38 -174
  62. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  63. data/lib/active_support/core_ext/time/calculations.rb +18 -2
  64. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  65. data/lib/active_support/core_ext/time/zones.rb +4 -4
  66. data/lib/active_support/core_ext/time.rb +0 -1
  67. data/lib/active_support/current_attributes.rb +15 -6
  68. data/lib/active_support/dependencies/autoload.rb +17 -12
  69. data/lib/active_support/deprecation/behaviors.rb +53 -32
  70. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  71. data/lib/active_support/deprecation/deprecators.rb +104 -0
  72. data/lib/active_support/deprecation/disallowed.rb +3 -5
  73. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  74. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  75. data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
  76. data/lib/active_support/deprecation/reporting.rb +35 -21
  77. data/lib/active_support/deprecation.rb +32 -5
  78. data/lib/active_support/deprecator.rb +7 -0
  79. data/lib/active_support/descendants_tracker.rb +104 -132
  80. data/lib/active_support/duration/iso8601_serializer.rb +0 -2
  81. data/lib/active_support/duration.rb +2 -1
  82. data/lib/active_support/encrypted_configuration.rb +30 -9
  83. data/lib/active_support/encrypted_file.rb +8 -3
  84. data/lib/active_support/environment_inquirer.rb +22 -2
  85. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  86. data/lib/active_support/error_reporter.rb +121 -35
  87. data/lib/active_support/execution_wrapper.rb +4 -4
  88. data/lib/active_support/file_update_checker.rb +4 -2
  89. data/lib/active_support/fork_tracker.rb +10 -2
  90. data/lib/active_support/gem_version.rb +4 -4
  91. data/lib/active_support/gzip.rb +2 -0
  92. data/lib/active_support/hash_with_indifferent_access.rb +35 -17
  93. data/lib/active_support/i18n.rb +1 -1
  94. data/lib/active_support/i18n_railtie.rb +20 -13
  95. data/lib/active_support/inflector/inflections.rb +2 -0
  96. data/lib/active_support/inflector/methods.rb +22 -10
  97. data/lib/active_support/inflector/transliterate.rb +3 -1
  98. data/lib/active_support/isolated_execution_state.rb +26 -22
  99. data/lib/active_support/json/decoding.rb +2 -1
  100. data/lib/active_support/json/encoding.rb +25 -43
  101. data/lib/active_support/key_generator.rb +9 -1
  102. data/lib/active_support/lazy_load_hooks.rb +6 -4
  103. data/lib/active_support/locale/en.yml +2 -0
  104. data/lib/active_support/log_subscriber.rb +78 -33
  105. data/lib/active_support/logger.rb +1 -1
  106. data/lib/active_support/logger_thread_safe_level.rb +9 -21
  107. data/lib/active_support/message_encryptor.rb +197 -53
  108. data/lib/active_support/message_encryptors.rb +140 -0
  109. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  110. data/lib/active_support/message_pack/extensions.rb +292 -0
  111. data/lib/active_support/message_pack/serializer.rb +63 -0
  112. data/lib/active_support/message_pack.rb +50 -0
  113. data/lib/active_support/message_verifier.rb +212 -93
  114. data/lib/active_support/message_verifiers.rb +134 -0
  115. data/lib/active_support/messages/codec.rb +65 -0
  116. data/lib/active_support/messages/metadata.rb +111 -45
  117. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  118. data/lib/active_support/messages/rotator.rb +34 -32
  119. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  120. data/lib/active_support/multibyte/chars.rb +2 -0
  121. data/lib/active_support/multibyte/unicode.rb +9 -37
  122. data/lib/active_support/notifications/fanout.rb +239 -81
  123. data/lib/active_support/notifications/instrumenter.rb +71 -14
  124. data/lib/active_support/notifications.rb +1 -1
  125. data/lib/active_support/number_helper/number_converter.rb +2 -2
  126. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  127. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  128. data/lib/active_support/ordered_hash.rb +3 -3
  129. data/lib/active_support/ordered_options.rb +14 -0
  130. data/lib/active_support/parameter_filter.rb +84 -69
  131. data/lib/active_support/proxy_object.rb +2 -0
  132. data/lib/active_support/railtie.rb +33 -21
  133. data/lib/active_support/reloader.rb +12 -4
  134. data/lib/active_support/rescuable.rb +2 -0
  135. data/lib/active_support/secure_compare_rotator.rb +16 -9
  136. data/lib/active_support/string_inquirer.rb +3 -1
  137. data/lib/active_support/subscriber.rb +9 -27
  138. data/lib/active_support/syntax_error_proxy.rb +49 -0
  139. data/lib/active_support/tagged_logging.rb +60 -24
  140. data/lib/active_support/test_case.rb +153 -6
  141. data/lib/active_support/testing/assertions.rb +25 -9
  142. data/lib/active_support/testing/autorun.rb +0 -2
  143. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  144. data/lib/active_support/testing/deprecation.rb +25 -25
  145. data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
  146. data/lib/active_support/testing/isolation.rb +1 -1
  147. data/lib/active_support/testing/method_call_assertions.rb +21 -8
  148. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  149. data/lib/active_support/testing/stream.rb +1 -1
  150. data/lib/active_support/testing/strict_warnings.rb +38 -0
  151. data/lib/active_support/testing/time_helpers.rb +32 -14
  152. data/lib/active_support/time_with_zone.rb +4 -14
  153. data/lib/active_support/values/time_zone.rb +9 -7
  154. data/lib/active_support/version.rb +1 -1
  155. data/lib/active_support/xml_mini/jdom.rb +3 -10
  156. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  157. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  158. data/lib/active_support/xml_mini/rexml.rb +1 -1
  159. data/lib/active_support/xml_mini.rb +2 -2
  160. data/lib/active_support.rb +13 -3
  161. metadata +103 -18
  162. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  163. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
  164. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
  165. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  166. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
  167. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  168. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
  169. data/lib/active_support/core_ext/uri.rb +0 -5
  170. data/lib/active_support/per_thread_registry.rb +0 -65
@@ -1,8 +1,11 @@
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
7
+ # = Active Support Parameter Filter
8
+ #
6
9
  # +ParameterFilter+ replaces values in a <tt>Hash</tt>-like object if their
7
10
  # keys match one of the specified filters.
8
11
  #
@@ -36,6 +39,34 @@ module ActiveSupport
36
39
  class ParameterFilter
37
40
  FILTERED = "[FILTERED]" # :nodoc:
38
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
+
39
70
  # Create instance with given filters. Supported type of filters are +String+, +Regexp+, and +Proc+.
40
71
  # Other types of filters are treated as +String+ using +to_s+.
41
72
  # For +Proc+ filters, key, value, and optional original hash is passed to block arguments.
@@ -44,99 +75,83 @@ module ActiveSupport
44
75
  #
45
76
  # * <tt>:mask</tt> - A replaced object when filtered. Defaults to <tt>"[FILTERED]"</tt>.
46
77
  def initialize(filters = [], mask: FILTERED)
47
- @filters = filters
48
78
  @mask = mask
79
+ compile_filters!(filters)
49
80
  end
50
81
 
51
82
  # Mask value of +params+ if key matches one of filters.
52
83
  def filter(params)
53
- compiled_filter.call(params)
84
+ @no_filters ? params.dup : call(params)
54
85
  end
55
86
 
56
87
  # Returns filtered value for given key. For +Proc+ filters, third block argument is not populated.
57
88
  def filter_param(key, value)
58
- @filters.empty? ? value : compiled_filter.value_for_key(key, value)
89
+ @no_filters ? value : value_for_key(key, value)
59
90
  end
60
91
 
61
92
  private
62
- def compiled_filter
63
- @compiled_filter ||= CompiledFilter.compile(@filters, mask: @mask)
64
- end
65
-
66
- class CompiledFilter # :nodoc:
67
- def self.compile(filters, mask:)
68
- return lambda { |params| params.dup } if filters.empty?
69
-
70
- strings, regexps, blocks, deep_regexps, deep_strings = [], [], [], nil, nil
71
-
72
- filters.each do |item|
73
- case item
74
- when Proc
75
- blocks << item
76
- when Regexp
77
- if item.to_s.include?("\\.")
78
- (deep_regexps ||= []) << item
79
- else
80
- regexps << item
81
- 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
108
+ else
109
+ @regexps << item
110
+ end
111
+ else
112
+ s = Regexp.escape(item.to_s)
113
+ if s.include?("\\.")
114
+ (deep_strings ||= []) << s
82
115
  else
83
- s = Regexp.escape(item.to_s)
84
- if s.include?("\\.")
85
- (deep_strings ||= []) << s
86
- else
87
- strings << s
88
- end
116
+ strings << s
89
117
  end
90
118
  end
91
-
92
- regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
93
- (deep_regexps ||= []) << Regexp.new(deep_strings.join("|"), true) if deep_strings&.any?
94
-
95
- new regexps, deep_regexps, blocks, mask: mask
96
119
  end
97
120
 
98
- 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
124
+
125
+ def call(params, full_parent_key = nil, original_params = params)
126
+ filtered_params = params.class.new
99
127
 
100
- def initialize(regexps, deep_regexps, blocks, mask:)
101
- @regexps = regexps
102
- @deep_regexps = deep_regexps&.any? ? deep_regexps : nil
103
- @blocks = blocks
104
- @mask = mask
128
+ params.each do |key, value|
129
+ filtered_params[key] = value_for_key(key, value, full_parent_key, original_params)
105
130
  end
106
131
 
107
- def call(params, parents = [], original_params = params)
108
- filtered_params = params.class.new
109
-
110
- params.each do |key, value|
111
- filtered_params[key] = value_for_key(key, value, parents, original_params)
112
- end
132
+ filtered_params
133
+ end
113
134
 
114
- 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
115
138
  end
116
139
 
117
- def value_for_key(key, value, parents = [], original_params = nil)
118
- parents.push(key) if deep_regexps
119
- if regexps.any? { |r| r.match?(key.to_s) }
120
- value = @mask
121
- elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| r.match?(joined) }
122
- value = @mask
123
- elsif value.is_a?(Hash)
124
- value = call(value, parents, original_params)
125
- elsif value.is_a?(Array)
126
- # If we don't pop the current parent it will be duplicated as we
127
- # process each array value.
128
- parents.pop if deep_regexps
129
- value = value.map { |v| value_for_key(key, v, parents, original_params) }
130
- # Restore the parent stack after processing the array.
131
- parents.push(key) if deep_regexps
132
- elsif blocks.any?
133
- key = key.dup if key.duplicable?
134
- value = value.dup if value.duplicable?
135
- blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
136
- end
137
- parents.pop if deep_regexps
138
- 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) }
139
152
  end
153
+
154
+ value
140
155
  end
141
156
  end
142
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
@@ -6,10 +6,13 @@ 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
17
  config.after_initialize do
15
18
  if level = app.config.active_support.delete(:isolation_level)
@@ -18,11 +21,10 @@ module ActiveSupport
18
21
  end
19
22
  end
20
23
 
21
- initializer "active_support.remove_deprecated_time_with_zone_name" do |app|
24
+ initializer "active_support.raise_on_invalid_cache_expiration_time" do |app|
22
25
  config.after_initialize do
23
- if app.config.active_support.remove_deprecated_time_with_zone_name
24
- require "active_support/time_with_zone"
25
- 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
26
28
  end
27
29
  end
28
30
  end
@@ -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
@@ -113,14 +115,18 @@ module ActiveSupport
113
115
  end
114
116
  end
115
117
 
116
- initializer "active_support.set_error_reporter" do |app|
117
- ActiveSupport.error_reporter = app.executor.error_reporter
118
- end
119
-
120
118
  initializer "active_support.set_configs" do |app|
121
119
  app.config.active_support.each do |k, v|
122
- k = "#{k}="
123
- ActiveSupport.public_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
124
130
  end
125
131
  end
126
132
 
@@ -140,13 +146,19 @@ module ActiveSupport
140
146
  end
141
147
  end
142
148
 
143
- initializer "active_support.set_rfc4122_namespaced_uuids" do |app|
149
+ initializer "active_support.set_default_message_serializer" do |app|
144
150
  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
151
+ if message_serializer = app.config.active_support.message_serializer
152
+ ActiveSupport::Messages::Codec.default_serializer = message_serializer
148
153
  end
149
154
  end
150
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
151
163
  end
152
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
@@ -4,6 +4,8 @@ require "active_support/security_utils"
4
4
  require "active_support/messages/rotator"
5
5
 
6
6
  module ActiveSupport
7
+ # = Secure Compare Rotator
8
+ #
7
9
  # The ActiveSupport::SecureCompareRotator is a wrapper around ActiveSupport::SecurityUtils.secure_compare
8
10
  # and allows you to rotate a previously defined value to a new one.
9
11
  #
@@ -29,23 +31,28 @@ module ActiveSupport
29
31
  # end
30
32
  class SecureCompareRotator
31
33
  include SecurityUtils
32
- prepend Messages::Rotator
33
34
 
34
35
  InvalidMatch = Class.new(StandardError)
35
36
 
36
- def initialize(value, **_options)
37
+ def initialize(value, on_rotation: nil)
37
38
  @value = value
39
+ @rotate_values = []
40
+ @on_rotation = on_rotation
38
41
  end
39
42
 
40
- def secure_compare!(other_value, on_rotation: @on_rotation)
41
- secure_compare(@value, other_value) ||
42
- run_rotations(on_rotation) { |wrapper| wrapper.secure_compare!(other_value) } ||
43
- raise(InvalidMatch)
43
+ def rotate(previous_value)
44
+ @rotate_values << previous_value
44
45
  end
45
46
 
46
- private
47
- def build_rotation(previous_value, _options)
48
- self.class.new(previous_value)
47
+ def secure_compare!(other_value, on_rotation: @on_rotation)
48
+ if secure_compare(@value, other_value)
49
+ true
50
+ elsif @rotate_values.any? { |value| secure_compare(value, other_value) }
51
+ on_rotation&.call
52
+ true
53
+ else
54
+ raise InvalidMatch
49
55
  end
56
+ end
50
57
  end
51
58
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = \String Inquirer
5
+ #
4
6
  # Wrapping a string in this class gives you a prettier way to test
5
7
  # for equality. The value returned by <tt>Rails.env</tt> is wrapped
6
8
  # in a StringInquirer object, so instead of calling this:
@@ -11,7 +13,7 @@ module ActiveSupport
11
13
  #
12
14
  # Rails.env.production?
13
15
  #
14
- # == Instantiating a new StringInquirer
16
+ # == Instantiating a new \StringInquirer
15
17
  #
16
18
  # vehicle = ActiveSupport::StringInquirer.new('car')
17
19
  # vehicle.car? # => true
@@ -3,7 +3,9 @@
3
3
  require "active_support/notifications"
4
4
 
5
5
  module ActiveSupport
6
- # ActiveSupport::Subscriber is an object set to consume
6
+ # = Active Support \Subscriber
7
+ #
8
+ # +ActiveSupport::Subscriber+ is an object set to consume
7
9
  # ActiveSupport::Notifications. The subscriber dispatches notifications to
8
10
  # a registered object based on its given namespace.
9
11
  #
@@ -20,9 +22,9 @@ module ActiveSupport
20
22
  # end
21
23
  # end
22
24
  #
23
- # After configured, whenever a "sql.active_record" notification is published,
24
- # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
25
- # the +sql+ method.
25
+ # After configured, whenever a <tt>"sql.active_record"</tt> notification is
26
+ # published, it will properly dispatch the event
27
+ # (ActiveSupport::Notifications::Event) to the +sql+ method.
26
28
  #
27
29
  # We can detach a subscriber as well:
28
30
  #
@@ -126,38 +128,18 @@ module ActiveSupport
126
128
  attr_reader :patterns # :nodoc:
127
129
 
128
130
  def initialize
129
- @queue_key = [self.class.name, object_id].join "-"
130
131
  @patterns = {}
131
132
  super
132
133
  end
133
134
 
134
- def start(name, id, payload)
135
- event = ActiveSupport::Notifications::Event.new(name, nil, nil, id, payload)
136
- event.start!
137
- parent = event_stack.last
138
- parent << event if parent
139
-
140
- event_stack.push event
141
- end
142
-
143
- def finish(name, id, payload)
144
- event = event_stack.pop
145
- event.finish!
146
- event.payload.merge!(payload)
147
-
148
- method = name.split(".").first
135
+ def call(event)
136
+ method = event.name[0, event.name.index(".")]
149
137
  send(method, event)
150
138
  end
151
139
 
152
140
  def publish_event(event) # :nodoc:
153
- method = event.name.split(".").first
141
+ method = event.name[0, event.name.index(".")]
154
142
  send(method, event)
155
143
  end
156
-
157
- private
158
- def event_stack
159
- registry = ActiveSupport::IsolatedExecutionState[:active_support_subscriber_queue_registry] ||= {}
160
- registry[@queue_key] ||= []
161
- end
162
144
  end
163
145
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+
5
+ module ActiveSupport
6
+ # This is a class for wrapping syntax errors. The purpose of this class
7
+ # is to enhance the backtraces on SyntaxError exceptions to include the
8
+ # source location of the syntax error. That way we can display the error
9
+ # source on error pages in development.
10
+ class SyntaxErrorProxy < DelegateClass(SyntaxError) # :nodoc:
11
+ def backtrace
12
+ parse_message_for_trace + super
13
+ end
14
+
15
+ class BacktraceLocation < Struct.new(:path, :lineno, :to_s) # :nodoc:
16
+ def spot(_)
17
+ end
18
+
19
+ def label
20
+ end
21
+ end
22
+
23
+ class BacktraceLocationProxy < DelegateClass(Thread::Backtrace::Location) # :nodoc:
24
+ def initialize(loc, ex)
25
+ super(loc)
26
+ @ex = ex
27
+ end
28
+
29
+ def spot(_)
30
+ super(@ex.__getobj__)
31
+ end
32
+ end
33
+
34
+ def backtrace_locations
35
+ parse_message_for_trace.map { |trace|
36
+ file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
37
+ BacktraceLocation.new(file, line.to_i, trace)
38
+ # We have to wrap these backtrace locations because we need the
39
+ # spot information to come from the originating exception, not the
40
+ # proxy object that's generating these
41
+ } + super.map { |loc| BacktraceLocationProxy.new(loc, self) }
42
+ end
43
+
44
+ private
45
+ def parse_message_for_trace
46
+ __getobj__.to_s.split("\n")
47
+ end
48
+ end
49
+ end
@@ -6,14 +6,16 @@ require "logger"
6
6
  require "active_support/logger"
7
7
 
8
8
  module ActiveSupport
9
+ # = Active Support Tagged Logging
10
+ #
9
11
  # Wraps any standard Logger object to provide tagging capabilities.
10
12
  #
11
13
  # May be called with a block:
12
14
  #
13
15
  # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
14
- # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
15
- # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
16
- # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
16
+ # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
17
+ # logger.tagged('BCX', "Jason") { |tagged_logger| tagged_logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
18
+ # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
17
19
  #
18
20
  # If called without a block, a new logger will be returned with applied tags:
19
21
  #
@@ -29,52 +31,86 @@ module ActiveSupport
29
31
  module Formatter # :nodoc:
30
32
  # This method is invoked when a log event occurs.
31
33
  def call(severity, timestamp, progname, msg)
32
- super(severity, timestamp, progname, "#{tags_text}#{msg}")
34
+ super(severity, timestamp, progname, tag_stack.format_message(msg))
33
35
  end
34
36
 
35
37
  def tagged(*tags)
36
- new_tags = push_tags(*tags)
38
+ pushed_count = tag_stack.push_tags(tags).size
37
39
  yield self
38
40
  ensure
39
- pop_tags(new_tags.size)
41
+ pop_tags(pushed_count)
40
42
  end
41
43
 
42
44
  def push_tags(*tags)
43
- tags.flatten!
44
- tags.reject!(&:blank?)
45
- current_tags.concat tags
46
- tags
45
+ tag_stack.push_tags(tags)
47
46
  end
48
47
 
49
- def pop_tags(size = 1)
50
- current_tags.pop size
48
+ def pop_tags(count = 1)
49
+ tag_stack.pop_tags(count)
51
50
  end
52
51
 
53
52
  def clear_tags!
54
- current_tags.clear
53
+ tag_stack.clear
55
54
  end
56
55
 
57
- def current_tags
56
+ def tag_stack
58
57
  # We use our object ID here to avoid conflicting with other instances
59
- thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
60
- IsolatedExecutionState[thread_key] ||= []
58
+ @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
59
+ IsolatedExecutionState[@thread_key] ||= TagStack.new
60
+ end
61
+
62
+ def current_tags
63
+ tag_stack.tags
61
64
  end
62
65
 
63
66
  def tags_text
64
- tags = current_tags
65
- if tags.one?
66
- "[#{tags[0]}] "
67
- elsif tags.any?
68
- tags.collect { |tag| "[#{tag}] " }.join
67
+ tag_stack.format_message("")
68
+ end
69
+ end
70
+
71
+ class TagStack # :nodoc:
72
+ attr_reader :tags
73
+
74
+ def initialize
75
+ @tags = []
76
+ @tags_string = nil
77
+ end
78
+
79
+ def push_tags(tags)
80
+ @tags_string = nil
81
+ tags.flatten!
82
+ tags.reject!(&:blank?)
83
+ @tags.concat(tags)
84
+ tags
85
+ end
86
+
87
+ def pop_tags(count)
88
+ @tags_string = nil
89
+ @tags.pop(count)
90
+ end
91
+
92
+ def clear
93
+ @tags_string = nil
94
+ @tags.clear
95
+ end
96
+
97
+ def format_message(message)
98
+ if @tags.empty?
99
+ message
100
+ elsif @tags.size == 1
101
+ "[#{@tags[0]}] #{message}"
102
+ else
103
+ @tags_string ||= "[#{@tags.join("] [")}] "
104
+ "#{@tags_string}#{message}"
69
105
  end
70
106
  end
71
107
  end
72
108
 
73
109
  module LocalTagStorage # :nodoc:
74
- attr_accessor :current_tags
110
+ attr_accessor :tag_stack
75
111
 
76
112
  def self.extended(base)
77
- base.current_tags = []
113
+ base.tag_stack = TagStack.new
78
114
  end
79
115
  end
80
116
 
@@ -82,7 +118,7 @@ module ActiveSupport
82
118
  logger = logger.clone
83
119
 
84
120
  if logger.formatter
85
- logger.formatter = logger.formatter.dup
121
+ logger.formatter = logger.formatter.clone
86
122
  else
87
123
  # Ensure we set a default formatter so we aren't extending nil!
88
124
  logger.formatter = ActiveSupport::Logger::SimpleFormatter.new