activesupport 7.0.8.7 → 7.2.3

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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +229 -397
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  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 +39 -7
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/broadcast_logger.rb +238 -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 +51 -19
  14. data/lib/active_support/cache/mem_cache_store.rb +98 -134
  15. data/lib/active_support/cache/memory_store.rb +85 -30
  16. data/lib/active_support/cache/null_store.rb +8 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +166 -153
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +64 -13
  20. data/lib/active_support/cache.rb +364 -292
  21. data/lib/active_support/callbacks.rb +121 -136
  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 +10 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +1 -2
  28. data/lib/active_support/core_ext/array.rb +0 -1
  29. data/lib/active_support/core_ext/benchmark.rb +1 -0
  30. data/lib/active_support/core_ext/class/attribute.rb +2 -2
  31. data/lib/active_support/core_ext/class/subclasses.rb +17 -34
  32. data/lib/active_support/core_ext/date/blank.rb +4 -0
  33. data/lib/active_support/core_ext/date/conversions.rb +1 -2
  34. data/lib/active_support/core_ext/date.rb +0 -1
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  36. data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
  37. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  38. data/lib/active_support/core_ext/date_time/conversions.rb +6 -4
  39. data/lib/active_support/core_ext/date_time.rb +0 -1
  40. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  41. data/lib/active_support/core_ext/enumerable.rb +20 -80
  42. data/lib/active_support/core_ext/erb/util.rb +201 -0
  43. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  44. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  45. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  46. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  47. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  48. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  49. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  50. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  51. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  52. data/lib/active_support/core_ext/module/introspection.rb +3 -1
  53. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  54. data/lib/active_support/core_ext/numeric/conversions.rb +5 -3
  55. data/lib/active_support/core_ext/numeric.rb +0 -1
  56. data/lib/active_support/core_ext/object/blank.rb +45 -1
  57. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  58. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  59. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  60. data/lib/active_support/core_ext/object/json.rb +17 -7
  61. data/lib/active_support/core_ext/object/try.rb +2 -2
  62. data/lib/active_support/core_ext/object/with.rb +46 -0
  63. data/lib/active_support/core_ext/object/with_options.rb +4 -4
  64. data/lib/active_support/core_ext/object.rb +1 -0
  65. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  66. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  67. data/lib/active_support/core_ext/pathname.rb +1 -0
  68. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  69. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  70. data/lib/active_support/core_ext/range/sole.rb +17 -0
  71. data/lib/active_support/core_ext/range.rb +2 -2
  72. data/lib/active_support/core_ext/securerandom.rb +24 -12
  73. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  74. data/lib/active_support/core_ext/string/filters.rb +24 -18
  75. data/lib/active_support/core_ext/string/indent.rb +1 -1
  76. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  77. data/lib/active_support/core_ext/string/multibyte.rb +3 -3
  78. data/lib/active_support/core_ext/string/output_safety.rb +34 -177
  79. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  80. data/lib/active_support/core_ext/time/calculations.rb +36 -30
  81. data/lib/active_support/core_ext/time/compatibility.rb +24 -0
  82. data/lib/active_support/core_ext/time/conversions.rb +1 -3
  83. data/lib/active_support/core_ext/time/zones.rb +4 -4
  84. data/lib/active_support/core_ext/time.rb +0 -1
  85. data/lib/active_support/core_ext.rb +0 -1
  86. data/lib/active_support/current_attributes.rb +60 -46
  87. data/lib/active_support/deep_mergeable.rb +53 -0
  88. data/lib/active_support/delegation.rb +202 -0
  89. data/lib/active_support/dependencies/autoload.rb +9 -16
  90. data/lib/active_support/deprecation/behaviors.rb +65 -42
  91. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  92. data/lib/active_support/deprecation/deprecators.rb +104 -0
  93. data/lib/active_support/deprecation/disallowed.rb +3 -5
  94. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  95. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  96. data/lib/active_support/deprecation/reporting.rb +49 -27
  97. data/lib/active_support/deprecation.rb +39 -9
  98. data/lib/active_support/deprecator.rb +7 -0
  99. data/lib/active_support/descendants_tracker.rb +66 -172
  100. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  101. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  102. data/lib/active_support/duration.rb +13 -7
  103. data/lib/active_support/encrypted_configuration.rb +30 -9
  104. data/lib/active_support/encrypted_file.rb +9 -4
  105. data/lib/active_support/environment_inquirer.rb +22 -2
  106. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  107. data/lib/active_support/error_reporter.rb +163 -36
  108. data/lib/active_support/evented_file_update_checker.rb +0 -1
  109. data/lib/active_support/execution_wrapper.rb +5 -6
  110. data/lib/active_support/file_update_checker.rb +6 -4
  111. data/lib/active_support/fork_tracker.rb +4 -32
  112. data/lib/active_support/gem_version.rb +4 -4
  113. data/lib/active_support/gzip.rb +2 -0
  114. data/lib/active_support/hash_with_indifferent_access.rb +50 -30
  115. data/lib/active_support/html_safe_translation.rb +19 -6
  116. data/lib/active_support/i18n.rb +1 -1
  117. data/lib/active_support/i18n_railtie.rb +20 -13
  118. data/lib/active_support/inflector/inflections.rb +2 -0
  119. data/lib/active_support/inflector/methods.rb +23 -11
  120. data/lib/active_support/inflector/transliterate.rb +3 -1
  121. data/lib/active_support/isolated_execution_state.rb +26 -22
  122. data/lib/active_support/json/decoding.rb +3 -2
  123. data/lib/active_support/json/encoding.rb +48 -48
  124. data/lib/active_support/key_generator.rb +9 -1
  125. data/lib/active_support/lazy_load_hooks.rb +7 -5
  126. data/lib/active_support/locale/en.yml +2 -0
  127. data/lib/active_support/log_subscriber.rb +74 -34
  128. data/lib/active_support/logger.rb +22 -60
  129. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  130. data/lib/active_support/message_encryptor.rb +197 -53
  131. data/lib/active_support/message_encryptors.rb +141 -0
  132. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  133. data/lib/active_support/message_pack/extensions.rb +305 -0
  134. data/lib/active_support/message_pack/serializer.rb +63 -0
  135. data/lib/active_support/message_pack.rb +50 -0
  136. data/lib/active_support/message_verifier.rb +229 -89
  137. data/lib/active_support/message_verifiers.rb +137 -0
  138. data/lib/active_support/messages/codec.rb +65 -0
  139. data/lib/active_support/messages/metadata.rb +111 -45
  140. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  141. data/lib/active_support/messages/rotator.rb +38 -31
  142. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  143. data/lib/active_support/multibyte/chars.rb +8 -3
  144. data/lib/active_support/multibyte/unicode.rb +9 -37
  145. data/lib/active_support/notifications/fanout.rb +248 -87
  146. data/lib/active_support/notifications/instrumenter.rb +93 -25
  147. data/lib/active_support/notifications.rb +29 -28
  148. data/lib/active_support/number_helper/number_converter.rb +16 -7
  149. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  150. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  151. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  152. data/lib/active_support/number_helper.rb +379 -318
  153. data/lib/active_support/option_merger.rb +2 -2
  154. data/lib/active_support/ordered_hash.rb +3 -3
  155. data/lib/active_support/ordered_options.rb +67 -15
  156. data/lib/active_support/parameter_filter.rb +84 -69
  157. data/lib/active_support/proxy_object.rb +8 -3
  158. data/lib/active_support/railtie.rb +25 -20
  159. data/lib/active_support/reloader.rb +12 -4
  160. data/lib/active_support/rescuable.rb +2 -0
  161. data/lib/active_support/secure_compare_rotator.rb +16 -9
  162. data/lib/active_support/string_inquirer.rb +4 -2
  163. data/lib/active_support/subscriber.rb +10 -27
  164. data/lib/active_support/syntax_error_proxy.rb +60 -0
  165. data/lib/active_support/tagged_logging.rb +64 -25
  166. data/lib/active_support/test_case.rb +156 -7
  167. data/lib/active_support/testing/assertions.rb +28 -12
  168. data/lib/active_support/testing/autorun.rb +0 -2
  169. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  170. data/lib/active_support/testing/deprecation.rb +20 -27
  171. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  172. data/lib/active_support/testing/isolation.rb +21 -9
  173. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  174. data/lib/active_support/testing/parallelization/server.rb +18 -2
  175. data/lib/active_support/testing/parallelization/worker.rb +2 -2
  176. data/lib/active_support/testing/parallelization.rb +12 -1
  177. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  178. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  179. data/lib/active_support/testing/stream.rb +1 -1
  180. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  181. data/lib/active_support/testing/time_helpers.rb +38 -16
  182. data/lib/active_support/time_with_zone.rb +12 -18
  183. data/lib/active_support/values/time_zone.rb +25 -14
  184. data/lib/active_support/version.rb +1 -1
  185. data/lib/active_support/xml_mini/jdom.rb +3 -10
  186. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  187. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  188. data/lib/active_support/xml_mini/rexml.rb +1 -1
  189. data/lib/active_support/xml_mini.rb +14 -3
  190. data/lib/active_support.rb +15 -3
  191. metadata +142 -24
  192. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  193. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
  194. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
  195. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  196. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
  197. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  198. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  199. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
  200. data/lib/active_support/core_ext/uri.rb +0 -5
  201. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  202. data/lib/active_support/per_thread_registry.rb +0 -65
  203. data/lib/active_support/ruby_features.rb +0 -7
@@ -1,218 +1,112 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "weakref"
4
- require "active_support/ruby_features"
5
4
 
6
5
  module ActiveSupport
6
+ # = Active Support Descendants Tracker
7
+ #
7
8
  # This module provides an internal implementation to track descendants
8
- # which is faster than iterating through ObjectSpace.
9
+ # which is faster than iterating through +ObjectSpace+.
10
+ #
11
+ # However Ruby 3.1 provide a fast native +Class#subclasses+ method,
12
+ # so if you know your code won't be executed on older rubies, including
13
+ # +ActiveSupport::DescendantsTracker+ does not provide any benefit.
9
14
  module DescendantsTracker
10
- class << self
11
- def direct_descendants(klass)
12
- ActiveSupport::Deprecation.warn(<<~MSG)
13
- ActiveSupport::DescendantsTracker.direct_descendants is deprecated and will be removed in Rails 7.1.
14
- Use ActiveSupport::DescendantsTracker.subclasses instead.
15
- MSG
16
- subclasses(klass)
17
- end
18
- end
19
-
20
15
  @clear_disabled = false
21
16
 
22
- if RubyFeatures::CLASS_SUBCLASSES
23
- @@excluded_descendants = if RUBY_ENGINE == "ruby"
24
- # On MRI `ObjectSpace::WeakMap` keys are weak references.
25
- # So we can simply use WeakMap as a `Set`.
26
- ObjectSpace::WeakMap.new
27
- else
28
- # On TruffleRuby `ObjectSpace::WeakMap` keys are strong references.
29
- # So we use `object_id` as a key and the actual object as a value.
30
- #
31
- # JRuby for now doesn't have Class#descendant, but when it will, it will likely
32
- # have the same WeakMap semantic than Truffle so we future proof this as much as possible.
33
- class WeakSet # :nodoc:
34
- def initialize
35
- @map = ObjectSpace::WeakMap.new
36
- end
37
-
38
- def [](object)
39
- @map.key?(object.object_id)
40
- end
17
+ if RUBY_ENGINE == "ruby"
18
+ # On MRI `ObjectSpace::WeakMap` keys are weak references.
19
+ # So we can simply use WeakMap as a `Set`.
20
+ class WeakSet < ObjectSpace::WeakMap # :nodoc:
21
+ alias_method :to_a, :keys
41
22
 
42
- def []=(object, _present)
43
- @map[object.object_id] = object
44
- end
23
+ def <<(object)
24
+ self[object] = true
45
25
  end
46
- WeakSet.new
47
26
  end
48
-
49
- class << self
50
- def disable_clear! # :nodoc:
51
- unless @clear_disabled
52
- @clear_disabled = true
53
- remove_method(:subclasses)
54
- @@excluded_descendants = nil
55
- end
27
+ else
28
+ # On TruffleRuby `ObjectSpace::WeakMap` keys are strong references.
29
+ # So we use `object_id` as a key and the actual object as a value.
30
+ #
31
+ # JRuby for now doesn't have Class#descendant, but when it will, it will likely
32
+ # have the same WeakMap semantic than Truffle so we future proof this as much as possible.
33
+ class WeakSet # :nodoc:
34
+ def initialize
35
+ @map = ObjectSpace::WeakMap.new
56
36
  end
57
37
 
58
- def subclasses(klass)
59
- klass.subclasses
38
+ def [](object)
39
+ @map.key?(object.object_id)
60
40
  end
41
+ alias_method :include?, :[]
61
42
 
62
- def descendants(klass)
63
- klass.descendants
43
+ def []=(object, _present)
44
+ @map[object.object_id] = object
64
45
  end
65
46
 
66
- def clear(classes) # :nodoc:
67
- raise "DescendantsTracker.clear was disabled because config.cache_classes = true" if @clear_disabled
68
-
69
- classes.each do |klass|
70
- @@excluded_descendants[klass] = true
71
- klass.descendants.each do |descendant|
72
- @@excluded_descendants[descendant] = true
73
- end
74
- end
47
+ def to_a
48
+ @map.values
75
49
  end
76
50
 
77
- def native? # :nodoc:
78
- true
51
+ def <<(object)
52
+ self[object] = true
79
53
  end
80
54
  end
55
+ end
56
+ @excluded_descendants = WeakSet.new
81
57
 
58
+ module ReloadedClassesFiltering # :nodoc:
82
59
  def subclasses
83
- subclasses = super
84
- subclasses.reject! { |d| @@excluded_descendants[d] }
85
- subclasses
60
+ DescendantsTracker.reject!(super)
86
61
  end
87
62
 
88
63
  def descendants
89
- subclasses.concat(subclasses.flat_map(&:descendants))
90
- end
91
-
92
- def direct_descendants
93
- ActiveSupport::Deprecation.warn(<<~MSG)
94
- ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
95
- Use #subclasses instead.
96
- MSG
97
- subclasses
64
+ DescendantsTracker.reject!(super)
98
65
  end
99
- else
100
- @@direct_descendants = {}
66
+ end
101
67
 
102
- class << self
103
- def disable_clear! # :nodoc:
68
+ class << self
69
+ def disable_clear! # :nodoc:
70
+ unless @clear_disabled
104
71
  @clear_disabled = true
72
+ ReloadedClassesFiltering.remove_method(:subclasses)
73
+ ReloadedClassesFiltering.remove_method(:descendants)
74
+ @excluded_descendants = nil
105
75
  end
76
+ end
106
77
 
107
- def subclasses(klass)
108
- descendants = @@direct_descendants[klass]
109
- descendants ? descendants.to_a : []
110
- end
111
-
112
- def descendants(klass)
113
- arr = []
114
- accumulate_descendants(klass, arr)
115
- arr
116
- end
78
+ def clear(classes) # :nodoc:
79
+ raise "DescendantsTracker.clear was disabled because config.enable_reloading is false" if @clear_disabled
117
80
 
118
- def clear(classes) # :nodoc:
119
- raise "DescendantsTracker.clear was disabled because config.cache_classes = true" if @clear_disabled
120
-
121
- @@direct_descendants.each do |klass, direct_descendants_of_klass|
122
- if classes.member?(klass)
123
- @@direct_descendants.delete(klass)
124
- else
125
- direct_descendants_of_klass.reject! do |direct_descendant_of_class|
126
- classes.member?(direct_descendant_of_class)
127
- end
128
- end
81
+ classes.each do |klass|
82
+ @excluded_descendants << klass
83
+ klass.descendants.each do |descendant|
84
+ @excluded_descendants << descendant
129
85
  end
130
86
  end
131
-
132
- def native? # :nodoc:
133
- false
134
- end
135
-
136
- # This is the only method that is not thread safe, but is only ever called
137
- # during the eager loading phase.
138
- def store_inherited(klass, descendant)
139
- (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
140
- end
141
-
142
- private
143
- def accumulate_descendants(klass, acc)
144
- if direct_descendants = @@direct_descendants[klass]
145
- direct_descendants.each do |direct_descendant|
146
- acc << direct_descendant
147
- accumulate_descendants(direct_descendant, acc)
148
- end
149
- end
150
- end
151
- end
152
-
153
- def inherited(base)
154
- DescendantsTracker.store_inherited(self, base)
155
- super
156
87
  end
157
88
 
158
- def direct_descendants
159
- ActiveSupport::Deprecation.warn(<<~MSG)
160
- ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
161
- Use #subclasses instead.
162
- MSG
163
- DescendantsTracker.subclasses(self)
89
+ def reject!(classes) # :nodoc:
90
+ if @excluded_descendants
91
+ classes.reject! { |d| @excluded_descendants.include?(d) }
92
+ end
93
+ classes
164
94
  end
95
+ end
165
96
 
166
- def subclasses
167
- DescendantsTracker.subclasses(self)
97
+ class << self
98
+ def subclasses(klass)
99
+ klass.subclasses
168
100
  end
169
101
 
170
- def descendants
171
- DescendantsTracker.descendants(self)
102
+ def descendants(klass)
103
+ klass.descendants
172
104
  end
105
+ end
173
106
 
174
- # DescendantsArray is an array that contains weak references to classes.
175
- class DescendantsArray # :nodoc:
176
- include Enumerable
177
-
178
- def initialize
179
- @refs = []
180
- end
181
-
182
- def initialize_copy(orig)
183
- @refs = @refs.dup
184
- end
185
-
186
- def <<(klass)
187
- @refs << WeakRef.new(klass)
188
- end
189
-
190
- def each
191
- @refs.reject! do |ref|
192
- yield ref.__getobj__
193
- false
194
- rescue WeakRef::RefError
195
- true
196
- end
197
- self
198
- end
199
-
200
- def refs_size
201
- @refs.size
202
- end
203
-
204
- def cleanup!
205
- @refs.delete_if { |ref| !ref.weakref_alive? }
206
- end
207
-
208
- def reject!
209
- @refs.reject! do |ref|
210
- yield ref.__getobj__
211
- rescue WeakRef::RefError
212
- true
213
- end
214
- end
215
- end
107
+ def descendants
108
+ subclasses = DescendantsTracker.reject!(self.subclasses)
109
+ subclasses.concat(subclasses.flat_map(&:descendants))
216
110
  end
217
111
  end
218
112
  end
@@ -102,12 +102,12 @@ module ActiveSupport
102
102
  raise_parsing_error("is empty duration") if parts.empty?
103
103
 
104
104
  # Mixing any of Y, M, D with W is invalid.
105
- if parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
105
+ if parts.key?(:weeks) && parts.keys.intersect?(DATE_COMPONENTS)
106
106
  raise_parsing_error("mixing weeks with other date parts not allowed")
107
107
  end
108
108
 
109
109
  # Specifying an empty T part is invalid.
110
- if mode == :time && (parts.keys & TIME_COMPONENTS).empty?
110
+ if mode == :time && !parts.keys.intersect?(TIME_COMPONENTS)
111
111
  raise_parsing_error("time part marker is present but time part is empty")
112
112
  end
113
113
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/object/blank"
4
-
5
3
  module ActiveSupport
6
4
  class Duration
7
5
  # Serializes duration to string according to ISO 8601 Duration format.
@@ -37,7 +35,6 @@ module ActiveSupport
37
35
  # Return pair of duration's parts and whole duration sign.
38
36
  # Parts are summarized (as they can become repetitive due to addition, etc).
39
37
  # Zero parts are removed as not significant.
40
- # If all parts are negative it will negate all of them and return minus as a sign.
41
38
  def normalize
42
39
  parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
43
40
  p[k] += v unless v.zero?
@@ -52,7 +49,7 @@ module ActiveSupport
52
49
  end
53
50
 
54
51
  def week_mixed_with_date?(parts)
55
- parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
52
+ parts.key?(:weeks) && parts.keys.intersect?(DATE_COMPONENTS)
56
53
  end
57
54
 
58
55
  def format_seconds(seconds)
@@ -3,9 +3,10 @@
3
3
  require "active_support/core_ext/array/conversions"
4
4
  require "active_support/core_ext/module/delegation"
5
5
  require "active_support/core_ext/object/acts_like"
6
- require "active_support/core_ext/string/filters"
7
6
 
8
7
  module ActiveSupport
8
+ # = Active Support \Duration
9
+ #
9
10
  # Provides accurate date and time measurements using Date#advance and
10
11
  # Time#advance, respectively. It mainly supports the methods on Numeric.
11
12
  #
@@ -13,7 +14,7 @@ module ActiveSupport
13
14
  class Duration
14
15
  class Scalar < Numeric # :nodoc:
15
16
  attr_reader :value
16
- delegate :to_i, :to_f, :to_s, to: :value
17
+ delegate :to_i, :to_f, :to_s, to: :@value
17
18
 
18
19
  def initialize(value)
19
20
  @value = value
@@ -220,6 +221,8 @@ module ActiveSupport
220
221
  end
221
222
  end
222
223
 
224
+ Delegation.generate(self, [:to_f, :positive?, :negative?, :zero?, :abs], to: :@value, as: Integer, nilable: false)
225
+
223
226
  def initialize(value, parts, variable = nil) # :nodoc:
224
227
  @value, @parts = value, parts
225
228
  @parts.reject! { |k, v| v.zero? } unless value == 0
@@ -231,7 +234,10 @@ module ActiveSupport
231
234
  end
232
235
  end
233
236
 
234
- # Returns a copy of the parts hash that defines the duration
237
+ # Returns a copy of the parts hash that defines the duration.
238
+ #
239
+ # 5.minutes.parts # => {:minutes=>5}
240
+ # 3.years.parts # => {:years=>3}
235
241
  def parts
236
242
  @parts.dup
237
243
  end
@@ -365,8 +371,8 @@ module ActiveSupport
365
371
  # 1.year.to_i # => 31556952
366
372
  #
367
373
  # In such cases, Ruby's core
368
- # Date[https://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and
369
- # Time[https://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision
374
+ # Date[https://docs.ruby-lang.org/en/master/Date.html] and
375
+ # Time[https://docs.ruby-lang.org/en/master/Time.html] should be used for precision
370
376
  # date and time arithmetic.
371
377
  def to_i
372
378
  @value.to_i
@@ -503,8 +509,8 @@ module ActiveSupport
503
509
  value.respond_to?(method)
504
510
  end
505
511
 
506
- def method_missing(method, *args, &block)
507
- value.public_send(method, *args, &block)
512
+ def method_missing(...)
513
+ value.public_send(...)
508
514
  end
509
515
 
510
516
  def raise_type_error(other)
@@ -4,9 +4,12 @@ require "yaml"
4
4
  require "active_support/encrypted_file"
5
5
  require "active_support/ordered_options"
6
6
  require "active_support/core_ext/object/inclusion"
7
+ require "active_support/core_ext/hash/keys"
7
8
  require "active_support/core_ext/module/delegation"
8
9
 
9
10
  module ActiveSupport
11
+ # = Encrypted Configuration
12
+ #
10
13
  # Provides convenience methods on top of EncryptedFile to access values stored
11
14
  # as encrypted YAML.
12
15
  #
@@ -30,12 +33,23 @@ module ActiveSupport
30
33
  # # => KeyError
31
34
  #
32
35
  class EncryptedConfiguration < EncryptedFile
33
- delegate :[], :fetch, to: :config
36
+ class InvalidContentError < RuntimeError
37
+ def initialize(content_path)
38
+ super "Invalid YAML in '#{content_path}'."
39
+ end
40
+
41
+ def message
42
+ cause.is_a?(Psych::SyntaxError) ? "#{super}\n\n #{cause.message}" : super
43
+ end
44
+ end
45
+
34
46
  delegate_missing_to :options
35
47
 
36
48
  def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
37
49
  super content_path: config_path, key_path: key_path,
38
50
  env_key: env_key, raise_if_missing_key: raise_if_missing_key
51
+ @config = nil
52
+ @options = nil
39
53
  end
40
54
 
41
55
  # Reads the file and returns the decrypted content. See EncryptedFile#read.
@@ -46,10 +60,8 @@ module ActiveSupport
46
60
  ""
47
61
  end
48
62
 
49
- def write(contents)
50
- deserialize(contents)
51
-
52
- super
63
+ def validate! # :nodoc:
64
+ deserialize(read)
53
65
  end
54
66
 
55
67
  # Returns the decrypted content as a Hash with symbolized keys.
@@ -64,11 +76,15 @@ module ActiveSupport
64
76
  @config ||= deserialize(read).deep_symbolize_keys
65
77
  end
66
78
 
79
+ def inspect # :nodoc:
80
+ "#<#{self.class.name}:#{'%#016x' % (object_id << 1)}>"
81
+ end
82
+
67
83
  private
68
84
  def deep_transform(hash)
69
85
  return hash unless hash.is_a?(Hash)
70
86
 
71
- h = ActiveSupport::InheritableOptions.new
87
+ h = ActiveSupport::OrderedOptions.new
72
88
  hash.each do |k, v|
73
89
  h[k] = deep_transform(v)
74
90
  end
@@ -79,9 +95,14 @@ module ActiveSupport
79
95
  @options ||= deep_transform(config)
80
96
  end
81
97
 
82
- def deserialize(config)
83
- doc = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(config) : YAML.load(config)
84
- doc.presence || {}
98
+ def deserialize(content)
99
+ config = YAML.respond_to?(:unsafe_load) ?
100
+ YAML.unsafe_load(content, filename: content_path) :
101
+ YAML.load(content, filename: content_path)
102
+
103
+ config.presence || {}
104
+ rescue Psych::SyntaxError
105
+ raise InvalidContentError.new(content_path)
85
106
  end
86
107
  end
87
108
  end
@@ -53,6 +53,12 @@ module ActiveSupport
53
53
  read_env_key || read_key_file || handle_missing_key
54
54
  end
55
55
 
56
+ # Returns truthy if #key is truthy. Returns falsy otherwise. Unlike #key,
57
+ # does not raise MissingKeyError when +raise_if_missing_key+ is true.
58
+ def key?
59
+ read_env_key || read_key_file
60
+ end
61
+
56
62
  # Reads the file and returns the decrypted content.
57
63
  #
58
64
  # Raises:
@@ -63,7 +69,7 @@ module ActiveSupport
63
69
  # decrypted or verified.
64
70
  def read
65
71
  if !key.nil? && content_path.exist?
66
- decrypt content_path.binread
72
+ decrypt content_path.binread.strip
67
73
  else
68
74
  raise MissingContentError, content_path
69
75
  end
@@ -104,7 +110,7 @@ module ActiveSupport
104
110
  end
105
111
 
106
112
  def encryptor
107
- @encryptor ||= ActiveSupport::MessageEncryptor.new([ key ].pack("H*"), cipher: CIPHER)
113
+ @encryptor ||= ActiveSupport::MessageEncryptor.new([ key ].pack("H*"), cipher: CIPHER, serializer: Marshal)
108
114
  end
109
115
 
110
116
 
@@ -113,8 +119,7 @@ module ActiveSupport
113
119
  end
114
120
 
115
121
  def read_key_file
116
- return @key_file_contents if defined?(@key_file_contents)
117
- @key_file_contents = (key_path.binread.strip if key_path.exist?)
122
+ @key_file_contents ||= (key_path.binread.strip if key_path.exist?)
118
123
  end
119
124
 
120
125
  def handle_missing_key
@@ -1,20 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/string_inquirer"
4
+ require "active_support/core_ext/object/inclusion"
4
5
 
5
6
  module ActiveSupport
6
7
  class EnvironmentInquirer < StringInquirer # :nodoc:
7
- DEFAULT_ENVIRONMENTS = ["development", "test", "production"]
8
+ # Optimization for the three default environments, so this inquirer doesn't need to rely on
9
+ # the slower delegation through method_missing that StringInquirer would normally entail.
10
+ DEFAULT_ENVIRONMENTS = %w[ development test production ]
11
+
12
+ # Environments that'll respond true for #local?
13
+ LOCAL_ENVIRONMENTS = %w[ development test ]
14
+
8
15
  def initialize(env)
16
+ raise(ArgumentError, "'local' is a reserved environment name") if env == "local"
17
+
9
18
  super(env)
10
19
 
11
20
  DEFAULT_ENVIRONMENTS.each do |default|
12
21
  instance_variable_set :"@#{default}", env == default
13
22
  end
23
+
24
+ @local = in? LOCAL_ENVIRONMENTS
14
25
  end
15
26
 
16
27
  DEFAULT_ENVIRONMENTS.each do |env|
17
- class_eval "def #{env}?; @#{env}; end"
28
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
29
+ def #{env}?
30
+ @#{env}
31
+ end
32
+ RUBY
33
+ end
34
+
35
+ # Returns true if we're in the development or test environment.
36
+ def local?
37
+ @local
18
38
  end
19
39
  end
20
40
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport::ErrorReporter::TestHelper # :nodoc:
4
+ class ErrorSubscriber
5
+ attr_reader :events
6
+
7
+ def initialize
8
+ @events = []
9
+ end
10
+
11
+ def report(error, handled:, severity:, source:, context:)
12
+ @events << [error, handled, severity, source, context]
13
+ end
14
+ end
15
+ end