activesupport 7.0.8.7 → 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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +143 -459
  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 +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 +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 +94 -128
  15. data/lib/active_support/cache/memory_store.rb +80 -25
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +165 -152
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +29 -14
  20. data/lib/active_support/cache.rb +363 -291
  21. data/lib/active_support/callbacks.rb +118 -134
  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/class/subclasses.rb +17 -34
  30. data/lib/active_support/core_ext/date/blank.rb +4 -0
  31. data/lib/active_support/core_ext/date/conversions.rb +1 -2
  32. data/lib/active_support/core_ext/date.rb +0 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
  35. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  36. data/lib/active_support/core_ext/date_time/conversions.rb +2 -2
  37. data/lib/active_support/core_ext/date_time.rb +0 -1
  38. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  39. data/lib/active_support/core_ext/enumerable.rb +3 -75
  40. data/lib/active_support/core_ext/erb/util.rb +201 -0
  41. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  42. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  43. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  44. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  45. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  46. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  47. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  48. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  49. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  50. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  51. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  52. data/lib/active_support/core_ext/numeric/conversions.rb +5 -3
  53. data/lib/active_support/core_ext/numeric.rb +0 -1
  54. data/lib/active_support/core_ext/object/blank.rb +45 -1
  55. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  56. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  57. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  58. data/lib/active_support/core_ext/object/json.rb +17 -7
  59. data/lib/active_support/core_ext/object/with.rb +46 -0
  60. data/lib/active_support/core_ext/object/with_options.rb +4 -4
  61. data/lib/active_support/core_ext/object.rb +1 -0
  62. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  63. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  64. data/lib/active_support/core_ext/pathname.rb +1 -0
  65. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  66. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  67. data/lib/active_support/core_ext/range.rb +1 -2
  68. data/lib/active_support/core_ext/securerandom.rb +1 -5
  69. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  70. data/lib/active_support/core_ext/string/filters.rb +21 -15
  71. data/lib/active_support/core_ext/string/indent.rb +1 -1
  72. data/lib/active_support/core_ext/string/inflections.rb +16 -5
  73. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  74. data/lib/active_support/core_ext/string/output_safety.rb +34 -177
  75. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  76. data/lib/active_support/core_ext/time/calculations.rb +36 -30
  77. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  78. data/lib/active_support/core_ext/time/conversions.rb +1 -3
  79. data/lib/active_support/core_ext/time/zones.rb +4 -4
  80. data/lib/active_support/core_ext/time.rb +0 -1
  81. data/lib/active_support/core_ext.rb +0 -1
  82. data/lib/active_support/current_attributes.rb +53 -46
  83. data/lib/active_support/deep_mergeable.rb +53 -0
  84. data/lib/active_support/delegation.rb +202 -0
  85. data/lib/active_support/dependencies/autoload.rb +9 -16
  86. data/lib/active_support/deprecation/behaviors.rb +65 -42
  87. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  88. data/lib/active_support/deprecation/deprecators.rb +104 -0
  89. data/lib/active_support/deprecation/disallowed.rb +3 -5
  90. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  91. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  92. data/lib/active_support/deprecation/reporting.rb +49 -27
  93. data/lib/active_support/deprecation.rb +39 -9
  94. data/lib/active_support/deprecator.rb +7 -0
  95. data/lib/active_support/descendants_tracker.rb +66 -172
  96. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  97. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  98. data/lib/active_support/duration.rb +13 -7
  99. data/lib/active_support/encrypted_configuration.rb +30 -9
  100. data/lib/active_support/encrypted_file.rb +9 -4
  101. data/lib/active_support/environment_inquirer.rb +22 -2
  102. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  103. data/lib/active_support/error_reporter.rb +160 -36
  104. data/lib/active_support/evented_file_update_checker.rb +0 -1
  105. data/lib/active_support/execution_wrapper.rb +4 -5
  106. data/lib/active_support/file_update_checker.rb +5 -3
  107. data/lib/active_support/fork_tracker.rb +4 -32
  108. data/lib/active_support/gem_version.rb +4 -4
  109. data/lib/active_support/gzip.rb +2 -0
  110. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  111. data/lib/active_support/html_safe_translation.rb +19 -6
  112. data/lib/active_support/i18n.rb +1 -1
  113. data/lib/active_support/i18n_railtie.rb +20 -13
  114. data/lib/active_support/inflector/inflections.rb +2 -0
  115. data/lib/active_support/inflector/methods.rb +23 -11
  116. data/lib/active_support/inflector/transliterate.rb +3 -1
  117. data/lib/active_support/isolated_execution_state.rb +26 -22
  118. data/lib/active_support/json/decoding.rb +2 -1
  119. data/lib/active_support/json/encoding.rb +25 -43
  120. data/lib/active_support/key_generator.rb +9 -1
  121. data/lib/active_support/lazy_load_hooks.rb +6 -4
  122. data/lib/active_support/locale/en.yml +2 -0
  123. data/lib/active_support/log_subscriber.rb +74 -34
  124. data/lib/active_support/logger.rb +22 -60
  125. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  126. data/lib/active_support/message_encryptor.rb +197 -53
  127. data/lib/active_support/message_encryptors.rb +141 -0
  128. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  129. data/lib/active_support/message_pack/extensions.rb +305 -0
  130. data/lib/active_support/message_pack/serializer.rb +63 -0
  131. data/lib/active_support/message_pack.rb +50 -0
  132. data/lib/active_support/message_verifier.rb +220 -89
  133. data/lib/active_support/message_verifiers.rb +135 -0
  134. data/lib/active_support/messages/codec.rb +65 -0
  135. data/lib/active_support/messages/metadata.rb +111 -45
  136. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  137. data/lib/active_support/messages/rotator.rb +34 -32
  138. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  139. data/lib/active_support/multibyte/chars.rb +4 -2
  140. data/lib/active_support/multibyte/unicode.rb +9 -37
  141. data/lib/active_support/notifications/fanout.rb +248 -87
  142. data/lib/active_support/notifications/instrumenter.rb +93 -25
  143. data/lib/active_support/notifications.rb +29 -28
  144. data/lib/active_support/number_helper/number_converter.rb +16 -7
  145. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  146. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  147. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  148. data/lib/active_support/number_helper.rb +379 -318
  149. data/lib/active_support/option_merger.rb +2 -2
  150. data/lib/active_support/ordered_hash.rb +3 -3
  151. data/lib/active_support/ordered_options.rb +67 -15
  152. data/lib/active_support/parameter_filter.rb +84 -69
  153. data/lib/active_support/proxy_object.rb +8 -3
  154. data/lib/active_support/railtie.rb +25 -20
  155. data/lib/active_support/reloader.rb +12 -4
  156. data/lib/active_support/rescuable.rb +2 -0
  157. data/lib/active_support/secure_compare_rotator.rb +16 -9
  158. data/lib/active_support/string_inquirer.rb +4 -2
  159. data/lib/active_support/subscriber.rb +10 -27
  160. data/lib/active_support/syntax_error_proxy.rb +60 -0
  161. data/lib/active_support/tagged_logging.rb +64 -25
  162. data/lib/active_support/test_case.rb +156 -7
  163. data/lib/active_support/testing/assertions.rb +28 -12
  164. data/lib/active_support/testing/autorun.rb +0 -2
  165. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  166. data/lib/active_support/testing/deprecation.rb +20 -27
  167. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  168. data/lib/active_support/testing/isolation.rb +21 -9
  169. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  170. data/lib/active_support/testing/parallelization/server.rb +3 -0
  171. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  172. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  173. data/lib/active_support/testing/stream.rb +1 -1
  174. data/lib/active_support/testing/strict_warnings.rb +43 -0
  175. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  176. data/lib/active_support/testing/time_helpers.rb +38 -16
  177. data/lib/active_support/time_with_zone.rb +12 -18
  178. data/lib/active_support/values/time_zone.rb +25 -14
  179. data/lib/active_support/version.rb +1 -1
  180. data/lib/active_support/xml_mini/jdom.rb +3 -10
  181. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  182. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  183. data/lib/active_support/xml_mini/rexml.rb +1 -1
  184. data/lib/active_support/xml_mini.rb +12 -3
  185. data/lib/active_support.rb +15 -3
  186. metadata +140 -19
  187. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  188. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
  189. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
  190. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  191. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
  192. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
  193. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  194. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
  195. data/lib/active_support/core_ext/uri.rb +0 -5
  196. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  197. data/lib/active_support/per_thread_registry.rb +0 -65
  198. data/lib/active_support/ruby_features.rb +0 -7
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
- # Returns the currently loaded version of Active Support as a <tt>Gem::Version</tt>.
4
+ # Returns the currently loaded version of Active Support as a +Gem::Version+.
5
5
  def self.gem_version
6
6
  Gem::Version.new VERSION::STRING
7
7
  end
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 7
11
- MINOR = 0
12
- TINY = 8
13
- PRE = "7"
11
+ MINOR = 2
12
+ TINY = 2
13
+ PRE = "1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -4,6 +4,8 @@ require "zlib"
4
4
  require "stringio"
5
5
 
6
6
  module ActiveSupport
7
+ # = Active Support \Gzip
8
+ #
7
9
  # A convenient wrapper for the zlib standard library that allows
8
10
  # compression/decompression of strings with gzip.
9
11
  #
@@ -6,6 +6,8 @@ require "active_support/core_ext/hash/except"
6
6
  require "active_support/core_ext/hash/slice"
7
7
 
8
8
  module ActiveSupport
9
+ # = \Hash With Indifferent Access
10
+ #
9
11
  # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
10
12
  # to be the same.
11
13
  #
@@ -37,7 +39,7 @@ module ActiveSupport
37
39
  #
38
40
  # but this class is intended for use cases where strings or symbols are the
39
41
  # expected keys and it is convenient to understand both as the same. For
40
- # example the +params+ hash in Ruby on Rails.
42
+ # example the +params+ hash in Ruby on \Rails.
41
43
  #
42
44
  # Note that core extensions define <tt>Hash#with_indifferent_access</tt>:
43
45
  #
@@ -45,7 +47,7 @@ module ActiveSupport
45
47
  #
46
48
  # which may be handy.
47
49
  #
48
- # To access this class outside of Rails, require the core extension with:
50
+ # To access this class outside of \Rails, require the core extension with:
49
51
  #
50
52
  # require "active_support/core_ext/hash/indifferent_access"
51
53
  #
@@ -113,7 +115,7 @@ module ActiveSupport
113
115
  # hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
114
116
  #
115
117
  # The arguments can be either an
116
- # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
118
+ # +ActiveSupport::HashWithIndifferentAccess+ or a regular +Hash+.
117
119
  # In either case the merge respects the semantics of indifferent access.
118
120
  #
119
121
  # If the argument is a regular hash with keys +:key+ and <tt>"key"</tt> only one
@@ -218,8 +220,12 @@ module ActiveSupport
218
220
  # hash.default # => nil
219
221
  # hash.default('foo') # => 'foo'
220
222
  # hash.default(:foo) # => 'foo'
221
- def default(*args)
222
- super(*args.map { |arg| convert_key(arg) })
223
+ def default(key = (no_key = true))
224
+ if no_key
225
+ super()
226
+ else
227
+ super(convert_key(key))
228
+ end
223
229
  end
224
230
 
225
231
  # Returns an array of the values at the specified indices:
@@ -229,7 +235,8 @@ module ActiveSupport
229
235
  # hash[:b] = 'y'
230
236
  # hash.values_at('a', 'b') # => ["x", "y"]
231
237
  def values_at(*keys)
232
- super(*keys.map { |key| convert_key(key) })
238
+ keys.map! { |key| convert_key(key) }
239
+ super
233
240
  end
234
241
 
235
242
  # Returns an array of the values at the specified indices, but also
@@ -242,7 +249,8 @@ module ActiveSupport
242
249
  # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
243
250
  # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
244
251
  def fetch_values(*indices, &block)
245
- super(*indices.map { |key| convert_key(key) }, &block)
252
+ indices.map! { |key| convert_key(key) }
253
+ super
246
254
  end
247
255
 
248
256
  # Returns a shallow copy of the hash.
@@ -301,7 +309,7 @@ module ActiveSupport
301
309
  # hash.except(:a, "b") # => {c: 10}.with_indifferent_access
302
310
  # hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
303
311
  def except(*keys)
304
- slice(*self.keys - keys.map { |key| convert_key(key) })
312
+ dup.except!(*keys)
305
313
  end
306
314
  alias_method :without, :except
307
315
 
@@ -326,21 +334,31 @@ module ActiveSupport
326
334
  dup.tap { |hash| hash.reject!(*args, &block) }
327
335
  end
328
336
 
329
- def transform_values(*args, &block)
337
+ def transform_values(&block)
330
338
  return to_enum(:transform_values) unless block_given?
331
- dup.tap { |hash| hash.transform_values!(*args, &block) }
339
+ dup.tap { |hash| hash.transform_values!(&block) }
332
340
  end
333
341
 
334
- def transform_keys(*args, &block)
335
- return to_enum(:transform_keys) unless block_given?
336
- dup.tap { |hash| hash.transform_keys!(*args, &block) }
342
+ NOT_GIVEN = Object.new # :nodoc:
343
+
344
+ def transform_keys(hash = NOT_GIVEN, &block)
345
+ return to_enum(:transform_keys) if NOT_GIVEN.equal?(hash) && !block_given?
346
+ dup.tap { |h| h.transform_keys!(hash, &block) }
337
347
  end
338
348
 
339
- def transform_keys!
340
- return enum_for(:transform_keys!) { size } unless block_given?
341
- keys.each do |key|
342
- self[yield(key)] = delete(key)
349
+ def transform_keys!(hash = NOT_GIVEN, &block)
350
+ return to_enum(:transform_keys!) if NOT_GIVEN.equal?(hash) && !block_given?
351
+
352
+ if hash.nil?
353
+ super
354
+ elsif NOT_GIVEN.equal?(hash)
355
+ keys.each { |key| self[yield(key)] = delete(key) }
356
+ elsif block_given?
357
+ keys.each { |key| self[hash[key] || yield(key)] = delete(key) }
358
+ else
359
+ keys.each { |key| self[hash[key] || key] = delete(key) }
343
360
  end
361
+
344
362
  self
345
363
  end
346
364
 
@@ -369,15 +387,13 @@ module ActiveSupport
369
387
  _new_hash
370
388
  end
371
389
 
390
+ def to_proc
391
+ proc { |key| self[key] }
392
+ end
393
+
372
394
  private
373
- if Symbol.method_defined?(:name)
374
- def convert_key(key)
375
- key.kind_of?(Symbol) ? key.name : key
376
- end
377
- else
378
- def convert_key(key)
379
- key.kind_of?(Symbol) ? key.to_s : key
380
- end
395
+ def convert_key(key)
396
+ Symbol === key ? key.name : key
381
397
  end
382
398
 
383
399
  def convert_value(value, conversion: nil)
@@ -7,18 +7,31 @@ module ActiveSupport
7
7
  def translate(key, **options)
8
8
  if html_safe_translation_key?(key)
9
9
  html_safe_options = html_escape_translation_options(options)
10
- translation = I18n.translate(key, **html_safe_options)
11
- html_safe_translation(translation)
10
+
11
+ exception = false
12
+
13
+ exception_handler = ->(*args) do
14
+ exception = true
15
+ I18n.exception_handler.call(*args)
16
+ end
17
+
18
+ translation = I18n.translate(key, **html_safe_options, exception_handler: exception_handler)
19
+
20
+ if exception
21
+ translation
22
+ else
23
+ html_safe_translation(translation)
24
+ end
12
25
  else
13
26
  I18n.translate(key, **options)
14
27
  end
15
28
  end
16
29
 
17
- private
18
- def html_safe_translation_key?(key)
19
- /(?:_|\b)html\z/.match?(key)
20
- end
30
+ def html_safe_translation_key?(key)
31
+ /(?:_|\b)html\z/.match?(key)
32
+ end
21
33
 
34
+ private
22
35
  def html_escape_translation_options(options)
23
36
  options.each do |name, value|
24
37
  unless i18n_option?(name) || (name == :count && value.is_a?(Numeric))
@@ -7,7 +7,7 @@ begin
7
7
  require "i18n"
8
8
  require "i18n/backend/fallbacks"
9
9
  rescue LoadError => e
10
- $stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
10
+ warn "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
11
11
  raise e
12
12
  end
13
13
  require "active_support/lazy_load_hooks"
@@ -49,7 +49,7 @@ module I18n
49
49
  when :load_path
50
50
  I18n.load_path += value
51
51
  when :raise_on_missing_translations
52
- forward_raise_on_missing_translations_config(app)
52
+ setup_raise_on_missing_translations_config(app)
53
53
  else
54
54
  I18n.public_send("#{setting}=", value)
55
55
  end
@@ -60,28 +60,35 @@ module I18n
60
60
  # Restore available locales check so it will take place from now on.
61
61
  I18n.enforce_available_locales = enforce_available_locales
62
62
 
63
- directories = watched_dirs_with_extensions(reloadable_paths)
64
- reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
65
- I18n.load_path.keep_if { |p| File.exist?(p) }
66
- I18n.load_path |= reloadable_paths.flat_map(&:existent)
67
- end
63
+ if app.config.reloading_enabled?
64
+ directories = watched_dirs_with_extensions(reloadable_paths)
65
+ reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
66
+ I18n.load_path.keep_if { |p| File.exist?(p) }
67
+ I18n.load_path |= reloadable_paths.flat_map(&:existent)
68
+ end
68
69
 
69
- app.reloaders << reloader
70
- app.reloader.to_run do
71
- reloader.execute_if_updated { require_unload_lock! }
70
+ app.reloaders << reloader
71
+ app.reloader.to_run do
72
+ reloader.execute_if_updated { require_unload_lock! }
73
+ end
74
+ reloader.execute
72
75
  end
73
- reloader.execute
74
76
 
75
77
  @i18n_inited = true
76
78
  end
77
79
 
78
- def self.forward_raise_on_missing_translations_config(app)
80
+ def self.setup_raise_on_missing_translations_config(app)
79
81
  ActiveSupport.on_load(:action_view) do
80
82
  ActionView::Helpers::TranslationHelper.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
81
83
  end
82
84
 
83
- ActiveSupport.on_load(:action_controller) do
84
- AbstractController::Translation.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
85
+ if app.config.i18n.raise_on_missing_translations &&
86
+ I18n.exception_handler.is_a?(I18n::ExceptionHandler) # Only override the i18n gem's default exception handler.
87
+
88
+ I18n.exception_handler = ->(exception, *) {
89
+ exception = exception.to_exception if exception.is_a?(I18n::MissingTranslation)
90
+ raise exception
91
+ }
85
92
  end
86
93
  end
87
94
 
@@ -7,6 +7,8 @@ module ActiveSupport
7
7
  module Inflector
8
8
  extend self
9
9
 
10
+ # = Active Support \Inflections
11
+ #
10
12
  # A singleton instance of this class is yielded by Inflector.inflections,
11
13
  # which can then be used to specify additional inflection rules. If passed
12
14
  # an optional locale, rules for other languages can be specified. The
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/inflections"
4
- require "active_support/core_ext/object/blank"
5
4
 
6
5
  module ActiveSupport
6
+ # = Active Support \Inflector
7
+ #
7
8
  # The Inflector transforms words from singular to plural, class names to table
8
9
  # names, modularized class names to ones without, and class names to foreign
9
10
  # keys. The default inflections for pluralization, singularization, and
10
11
  # uncountable words are kept in inflections.rb.
11
12
  #
12
- # The Rails core team has stated patches for the inflections library will not
13
+ # The \Rails core team has stated patches for the inflections library will not
13
14
  # be accepted in order to avoid breaking legacy applications which may be
14
15
  # relying on errant inflections. If you discover an incorrect inflection and
15
16
  # require it for your application or wish to define rules for languages other
@@ -71,6 +72,8 @@ module ActiveSupport
71
72
  # String#camelize takes a symbol (:upper or :lower), so here we also support :lower to keep the methods consistent.
72
73
  if !uppercase_first_letter || uppercase_first_letter == :lower
73
74
  string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase! || match }
75
+ elsif string.match?(/\A[a-z\d]*\z/)
76
+ return inflections.acronyms[string]&.dup || string.capitalize
74
77
  else
75
78
  string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize! || match }
76
79
  end
@@ -94,10 +97,10 @@ module ActiveSupport
94
97
  #
95
98
  # camelize(underscore('SSLError')) # => "SslError"
96
99
  def underscore(camel_cased_word)
97
- return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
100
+ return camel_cased_word.to_s.dup unless /[A-Z-]|::/.match?(camel_cased_word)
98
101
  word = camel_cased_word.to_s.gsub("::", "/")
99
102
  word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
100
- word.gsub!(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
103
+ word.gsub!(/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-z\d])(?=[A-Z])/, "_")
101
104
  word.tr!("-", "_")
102
105
  word.downcase!
103
106
  word
@@ -155,18 +158,27 @@ module ActiveSupport
155
158
  result
156
159
  end
157
160
 
158
- # Converts just the first character to uppercase.
161
+ # Converts the first character in the string to uppercase.
159
162
  #
160
163
  # upcase_first('what a Lovely Day') # => "What a Lovely Day"
161
164
  # upcase_first('w') # => "W"
162
165
  # upcase_first('') # => ""
163
166
  def upcase_first(string)
164
- string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
167
+ string.length > 0 ? string[0].upcase.concat(string[1..-1]) : +""
168
+ end
169
+
170
+ # Converts the first character in the string to lowercase.
171
+ #
172
+ # downcase_first('If they enjoyed The Matrix') # => "if they enjoyed The Matrix"
173
+ # downcase_first('I') # => "i"
174
+ # downcase_first('') # => ""
175
+ def downcase_first(string)
176
+ string.length > 0 ? string[0].downcase.concat(string[1..-1]) : +""
165
177
  end
166
178
 
167
179
  # Capitalizes all the words and replaces some characters in the string to
168
180
  # create a nicer looking title. +titleize+ is meant for creating pretty
169
- # output. It is not used in the Rails internals.
181
+ # output. It is not used in the \Rails internals.
170
182
  #
171
183
  # The trailing '_id','Id'.. can be kept and capitalized by setting the
172
184
  # optional parameter +keep_id_suffix+ to true.
@@ -183,7 +195,7 @@ module ActiveSupport
183
195
  end
184
196
  end
185
197
 
186
- # Creates the name of a table like Rails does for models to table names.
198
+ # Creates the name of a table like \Rails does for models to table names.
187
199
  # This method uses the #pluralize method on the last word in the string.
188
200
  #
189
201
  # tableize('RawScaledScorer') # => "raw_scaled_scorers"
@@ -193,7 +205,7 @@ module ActiveSupport
193
205
  pluralize(underscore(class_name))
194
206
  end
195
207
 
196
- # Creates a class name from a plural table name like Rails does for table
208
+ # Creates a class name from a plural table name like \Rails does for table
197
209
  # names to models. Note that this returns a string and not a Class. (To
198
210
  # convert to an actual class follow +classify+ with #constantize.)
199
211
  #
@@ -226,7 +238,7 @@ module ActiveSupport
226
238
  def demodulize(path)
227
239
  path = path.to_s
228
240
  if i = path.rindex("::")
229
- path[(i + 2)..-1]
241
+ path[(i + 2), path.length]
230
242
  else
231
243
  path
232
244
  end
@@ -345,7 +357,7 @@ module ActiveSupport
345
357
  def const_regexp(camel_cased_word)
346
358
  parts = camel_cased_word.split("::")
347
359
 
348
- return Regexp.escape(camel_cased_word) if parts.blank?
360
+ return Regexp.escape(camel_cased_word) if parts.empty?
349
361
 
350
362
  last = parts.pop
351
363
 
@@ -62,10 +62,12 @@ module ActiveSupport
62
62
  # Transliteration is restricted to UTF-8, US-ASCII, and GB18030 strings.
63
63
  # Other encodings will raise an ArgumentError.
64
64
  def transliterate(string, replacement = "?", locale: nil)
65
- string = string.dup if string.frozen?
66
65
  raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
67
66
  raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.include?(string.encoding)
68
67
 
68
+ return string.dup if string.ascii_only?
69
+ string = string.dup if string.frozen?
70
+
69
71
  input_encoding = string.encoding
70
72
 
71
73
  # US-ASCII is a subset of UTF-8 so we'll force encoding as UTF-8 if
@@ -4,25 +4,30 @@ require "fiber"
4
4
 
5
5
  module ActiveSupport
6
6
  module IsolatedExecutionState # :nodoc:
7
- @isolation_level = :thread
7
+ @isolation_level = nil
8
8
 
9
9
  Thread.attr_accessor :active_support_execution_state
10
10
  Fiber.attr_accessor :active_support_execution_state
11
11
 
12
12
  class << self
13
- attr_reader :isolation_level
13
+ attr_reader :isolation_level, :scope
14
14
 
15
15
  def isolation_level=(level)
16
+ return if level == @isolation_level
17
+
16
18
  unless %i(thread fiber).include?(level)
17
19
  raise ArgumentError, "isolation_level must be `:thread` or `:fiber`, got: `#{level.inspect}`"
18
20
  end
19
21
 
20
- if level != isolation_level
21
- clear
22
- singleton_class.alias_method(:current, "current_#{level}")
23
- singleton_class.send(:private, :current)
24
- @isolation_level = level
25
- end
22
+ clear if @isolation_level
23
+
24
+ @scope =
25
+ case level
26
+ when :thread; Thread
27
+ when :fiber; Fiber
28
+ end
29
+
30
+ @isolation_level = level
26
31
  end
27
32
 
28
33
  def unique_id
@@ -30,43 +35,42 @@ module ActiveSupport
30
35
  end
31
36
 
32
37
  def [](key)
33
- current[key]
38
+ state[key]
34
39
  end
35
40
 
36
41
  def []=(key, value)
37
- current[key] = value
42
+ state[key] = value
38
43
  end
39
44
 
40
45
  def key?(key)
41
- current.key?(key)
46
+ state.key?(key)
42
47
  end
43
48
 
44
49
  def delete(key)
45
- current.delete(key)
50
+ state.delete(key)
46
51
  end
47
52
 
48
53
  def clear
49
- current.clear
54
+ state.clear
55
+ end
56
+
57
+ def context
58
+ scope.current
50
59
  end
51
60
 
52
61
  def share_with(other)
53
62
  # Action Controller streaming spawns a new thread and copy thread locals.
54
63
  # We do the same here for backward compatibility, but this is very much a hack
55
64
  # and streaming should be rethought.
56
- context = @isolation_level == :thread ? Thread.current : Fiber.current
57
65
  context.active_support_execution_state = other.active_support_execution_state.dup
58
66
  end
59
67
 
60
68
  private
61
- def current_thread
62
- Thread.current.active_support_execution_state ||= {}
63
- end
64
-
65
- def current_fiber
66
- Fiber.current.active_support_execution_state ||= {}
69
+ def state
70
+ context.active_support_execution_state ||= {}
67
71
  end
68
-
69
- alias_method :current, :current_thread
70
72
  end
73
+
74
+ self.isolation_level = :thread
71
75
  end
72
76
  end
@@ -5,7 +5,7 @@ require "active_support/core_ext/module/delegation"
5
5
  require "json"
6
6
 
7
7
  module ActiveSupport
8
- # Look for and parse json strings that look like ISO 8601 times.
8
+ # Look for and parse JSON strings that look like ISO 8601 times.
9
9
  mattr_accessor :parse_json_times
10
10
 
11
11
  module JSON
@@ -28,6 +28,7 @@ module ActiveSupport
28
28
  data
29
29
  end
30
30
  end
31
+ alias_method :load, :decode
31
32
 
32
33
  # Returns the class of the error that will be raised when there is an
33
34
  # error in decoding JSON. Using this method means you won't directly
@@ -18,8 +18,11 @@ module ActiveSupport
18
18
  #
19
19
  # ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
20
20
  # # => "{\"team\":\"rails\",\"players\":\"36\"}"
21
- def self.encode(value, options = nil)
22
- Encoding.json_encoder.new(options).encode(value)
21
+ class << self
22
+ def encode(value, options = nil)
23
+ Encoding.json_encoder.new(options).encode(value)
24
+ end
25
+ alias_method :dump, :encode
23
26
  end
24
27
 
25
28
  module Encoding # :nodoc:
@@ -32,49 +35,27 @@ module ActiveSupport
32
35
 
33
36
  # Encode the given object into a JSON string
34
37
  def encode(value)
35
- stringify jsonify value.as_json(options.dup)
36
- end
38
+ unless options.empty?
39
+ value = value.as_json(options.dup)
40
+ end
41
+ json = stringify(jsonify(value))
37
42
 
38
- private
39
43
  # Rails does more escaping than the JSON gem natively does (we
40
44
  # escape \u2028 and \u2029 and optionally >, <, & to work around
41
45
  # certain browser problems).
42
- ESCAPED_CHARS = {
43
- "\u2028" => '\u2028',
44
- "\u2029" => '\u2029',
45
- ">" => '\u003e',
46
- "<" => '\u003c',
47
- "&" => '\u0026',
48
- }
49
-
50
- ESCAPE_REGEX_WITH_HTML_ENTITIES = /[\u2028\u2029><&]/u
51
- ESCAPE_REGEX_WITHOUT_HTML_ENTITIES = /[\u2028\u2029]/u
52
-
53
- # This class wraps all the strings we see and does the extra escaping
54
- class EscapedString < String # :nodoc:
55
- def to_json(*)
56
- if Encoding.escape_html_entities_in_json
57
- s = super
58
- s.gsub! ESCAPE_REGEX_WITH_HTML_ENTITIES, ESCAPED_CHARS
59
- s
60
- else
61
- s = super
62
- s.gsub! ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, ESCAPED_CHARS
63
- s
64
- end
65
- end
66
-
67
- def to_s
68
- self
69
- end
46
+ if Encoding.escape_html_entities_in_json
47
+ json.gsub!(">", '\u003e')
48
+ json.gsub!("<", '\u003c')
49
+ json.gsub!("&", '\u0026')
70
50
  end
51
+ json.gsub!("\u2028", '\u2028')
52
+ json.gsub!("\u2029", '\u2029')
53
+ json
54
+ end
71
55
 
72
- # Mark these as private so we don't leak encoding-specific constructs
73
- private_constant :ESCAPED_CHARS, :ESCAPE_REGEX_WITH_HTML_ENTITIES,
74
- :ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, :EscapedString
75
-
56
+ private
76
57
  # Convert an object into a "JSON-ready" representation composed of
77
- # primitives like Hash, Array, String, Numeric,
58
+ # primitives like Hash, Array, String, Symbol, Numeric,
78
59
  # and +true+/+false+/+nil+.
79
60
  # Recursively calls #as_json to the object to recursively build a
80
61
  # fully JSON-ready object.
@@ -88,14 +69,15 @@ module ActiveSupport
88
69
  # calls.
89
70
  def jsonify(value)
90
71
  case value
91
- when String
92
- EscapedString.new(value)
93
- when Numeric, NilClass, TrueClass, FalseClass
72
+ when String, Integer, Symbol, nil, true, false
73
+ value
74
+ when Numeric
94
75
  value.as_json
95
76
  when Hash
96
77
  result = {}
97
78
  value.each do |k, v|
98
- result[jsonify(k)] = jsonify(v)
79
+ k = k.to_s unless Symbol === k || String === k
80
+ result[k] = jsonify(v)
99
81
  end
100
82
  result
101
83
  when Array
@@ -124,7 +106,7 @@ module ActiveSupport
124
106
  # Defaults to 3 (equivalent to millisecond precision)
125
107
  attr_accessor :time_precision
126
108
 
127
- # Sets the encoder used by Rails to encode Ruby objects into JSON strings
109
+ # Sets the encoder used by \Rails to encode Ruby objects into JSON strings
128
110
  # in +Object#to_json+ and +ActiveSupport::JSON.encode+.
129
111
  attr_accessor :json_encoder
130
112
  end
@@ -4,9 +4,11 @@ require "concurrent/map"
4
4
  require "openssl"
5
5
 
6
6
  module ActiveSupport
7
+ # = Key Generator
8
+ #
7
9
  # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2.
8
10
  # It can be used to derive a number of keys for various purposes from a given secret.
9
- # This lets Rails applications have a single secure secret, but avoid reusing that
11
+ # This lets \Rails applications have a single secure secret, but avoid reusing that
10
12
  # key in multiple incompatible contexts.
11
13
  class KeyGenerator
12
14
  class << self
@@ -39,8 +41,14 @@ module ActiveSupport
39
41
  def generate_key(salt, key_size = 64)
40
42
  OpenSSL::PKCS5.pbkdf2_hmac(@secret, salt, @iterations, key_size, @hash_digest_class.new)
41
43
  end
44
+
45
+ def inspect # :nodoc:
46
+ "#<#{self.class.name}:#{'%#016x' % (object_id << 1)}>"
47
+ end
42
48
  end
43
49
 
50
+ # = Caching Key Generator
51
+ #
44
52
  # CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
45
53
  # re-executing the key generation process when it's called using the same +salt+ and
46
54
  # +key_size+.