activesupport 7.2.1 → 8.0.0
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.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +67 -189
 - data/lib/active_support/backtrace_cleaner.rb +1 -1
 - data/lib/active_support/benchmark.rb +21 -0
 - data/lib/active_support/benchmarkable.rb +3 -2
 - data/lib/active_support/broadcast_logger.rb +14 -14
 - data/lib/active_support/cache/file_store.rb +12 -2
 - data/lib/active_support/cache/memory_store.rb +6 -2
 - data/lib/active_support/cache/redis_cache_store.rb +5 -2
 - data/lib/active_support/cache.rb +18 -13
 - data/lib/active_support/callbacks.rb +1 -2
 - data/lib/active_support/class_attribute.rb +26 -0
 - data/lib/active_support/code_generator.rb +9 -0
 - data/lib/active_support/concurrency/share_lock.rb +0 -1
 - data/lib/active_support/configuration_file.rb +15 -6
 - data/lib/active_support/core_ext/benchmark.rb +6 -9
 - data/lib/active_support/core_ext/class/attribute.rb +10 -19
 - data/lib/active_support/core_ext/date/conversions.rb +2 -0
 - data/lib/active_support/core_ext/date_and_time/compatibility.rb +2 -2
 - data/lib/active_support/core_ext/enumerable.rb +8 -3
 - data/lib/active_support/core_ext/hash/except.rb +0 -12
 - data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
 - data/lib/active_support/core_ext/object/json.rb +20 -12
 - data/lib/active_support/core_ext/string/multibyte.rb +1 -1
 - data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
 - data/lib/active_support/core_ext/time/calculations.rb +14 -2
 - data/lib/active_support/core_ext/time/compatibility.rb +9 -1
 - data/lib/active_support/core_ext/time/conversions.rb +2 -0
 - data/lib/active_support/core_ext/time/zones.rb +1 -1
 - data/lib/active_support/current_attributes.rb +7 -3
 - data/lib/active_support/delegation.rb +0 -2
 - data/lib/active_support/dependencies.rb +0 -1
 - data/lib/active_support/deprecation/reporting.rb +2 -21
 - data/lib/active_support/deprecation.rb +1 -1
 - data/lib/active_support/duration.rb +14 -10
 - data/lib/active_support/encrypted_configuration.rb +20 -2
 - data/lib/active_support/encrypted_file.rb +1 -1
 - data/lib/active_support/error_reporter.rb +25 -1
 - data/lib/active_support/evented_file_update_checker.rb +0 -1
 - data/lib/active_support/gem_version.rb +3 -3
 - data/lib/active_support/hash_with_indifferent_access.rb +16 -16
 - data/lib/active_support/i18n_railtie.rb +19 -11
 - data/lib/active_support/isolated_execution_state.rb +0 -2
 - data/lib/active_support/json/encoding.rb +2 -2
 - data/lib/active_support/notifications/fanout.rb +0 -1
 - data/lib/active_support/number_helper.rb +22 -0
 - data/lib/active_support/railtie.rb +4 -0
 - data/lib/active_support/tagged_logging.rb +5 -0
 - data/lib/active_support/testing/assertions.rb +79 -21
 - data/lib/active_support/testing/isolation.rb +2 -2
 - data/lib/active_support/testing/parallelization/server.rb +3 -0
 - data/lib/active_support/testing/strict_warnings.rb +3 -0
 - data/lib/active_support/testing/time_helpers.rb +2 -1
 - data/lib/active_support/time_with_zone.rb +22 -13
 - data/lib/active_support/values/time_zone.rb +17 -15
 - data/lib/active_support.rb +10 -3
 - metadata +40 -11
 - data/lib/active_support/proxy_object.rb +0 -20
 
| 
         @@ -55,6 +55,11 @@ module ActiveSupport 
     | 
|
| 
       55 
55 
     | 
    
         
             
                  @path = path
         
     | 
| 
       56 
56 
     | 
    
         
             
                  @line = line
         
     | 
| 
       57 
57 
     | 
    
         
             
                  @namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @sources = []
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def class_eval
         
     | 
| 
      
 62 
     | 
    
         
            +
                  yield @sources
         
     | 
| 
       58 
63 
     | 
    
         
             
                end
         
     | 
| 
       59 
64 
     | 
    
         | 
| 
       60 
65 
     | 
    
         
             
                def define_cached_method(canonical_name, namespace:, as: nil, &block)
         
     | 
| 
         @@ -65,6 +70,10 @@ module ActiveSupport 
     | 
|
| 
       65 
70 
     | 
    
         
             
                  @namespaces.each_value do |method_set|
         
     | 
| 
       66 
71 
     | 
    
         
             
                    method_set.apply(@owner, @path, @line - 1)
         
     | 
| 
       67 
72 
     | 
    
         
             
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  unless @sources.empty?
         
     | 
| 
      
 75 
     | 
    
         
            +
                    @owner.class_eval("# frozen_string_literal: true\n" + @sources.join(";"), @path, @line - 1)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
       68 
77 
     | 
    
         
             
                end
         
     | 
| 
       69 
78 
     | 
    
         
             
              end
         
     | 
| 
       70 
79 
     | 
    
         
             
            end
         
     | 
| 
         @@ -19,11 +19,20 @@ module ActiveSupport 
     | 
|
| 
       19 
19 
     | 
    
         
             
                end
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
                def parse(context: nil, **options)
         
     | 
| 
       22 
     | 
    
         
            -
                  source = render(context)
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                  source = @content.include?("<%") ? render(context) : @content
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  if source == @content
         
     | 
| 
      
 25 
     | 
    
         
            +
                    if YAML.respond_to?(:unsafe_load)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      YAML.unsafe_load_file(@content_path, **options) || {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                    else
         
     | 
| 
      
 28 
     | 
    
         
            +
                      YAML.load_file(@content_path, **options) || {}
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
       25 
30 
     | 
    
         
             
                  else
         
     | 
| 
       26 
     | 
    
         
            -
                    YAML. 
     | 
| 
      
 31 
     | 
    
         
            +
                    if YAML.respond_to?(:unsafe_load)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      YAML.unsafe_load(source, **options) || {}
         
     | 
| 
      
 33 
     | 
    
         
            +
                    else
         
     | 
| 
      
 34 
     | 
    
         
            +
                      YAML.load(source, **options) || {}
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
       27 
36 
     | 
    
         
             
                  end
         
     | 
| 
       28 
37 
     | 
    
         
             
                rescue Psych::SyntaxError => error
         
     | 
| 
       29 
38 
     | 
    
         
             
                  raise "YAML syntax error occurred while parsing #{@content_path}. " \
         
     | 
| 
         @@ -33,8 +42,7 @@ module ActiveSupport 
     | 
|
| 
       33 
42 
     | 
    
         | 
| 
       34 
43 
     | 
    
         
             
                private
         
     | 
| 
       35 
44 
     | 
    
         
             
                  def read(content_path)
         
     | 
| 
       36 
     | 
    
         
            -
                    require "yaml"
         
     | 
| 
       37 
     | 
    
         
            -
                    require "erb"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    require "yaml" unless defined?(YAML)
         
     | 
| 
       38 
46 
     | 
    
         | 
| 
       39 
47 
     | 
    
         
             
                    File.read(content_path).tap do |content|
         
     | 
| 
       40 
48 
     | 
    
         
             
                      if content.include?("\u00A0")
         
     | 
| 
         @@ -44,6 +52,7 @@ module ActiveSupport 
     | 
|
| 
       44 
52 
     | 
    
         
             
                  end
         
     | 
| 
       45 
53 
     | 
    
         | 
| 
       46 
54 
     | 
    
         
             
                  def render(context)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    require "erb" unless defined?(ERB)
         
     | 
| 
       47 
56 
     | 
    
         
             
                    erb = ERB.new(@content).tap { |e| e.filename = @content_path }
         
     | 
| 
       48 
57 
     | 
    
         
             
                    context ? erb.result(context) : erb.result
         
     | 
| 
       49 
58 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -3,14 +3,11 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require "benchmark"
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            class << Benchmark
         
     | 
| 
       6 
     | 
    
         
            -
               
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
              #   # => 0.074
         
     | 
| 
       13 
     | 
    
         
            -
              def ms(&block)
         
     | 
| 
       14 
     | 
    
         
            -
                1000 * realtime(&block)
         
     | 
| 
      
 6 
     | 
    
         
            +
              def ms(&block) # :nodoc
         
     | 
| 
      
 7 
     | 
    
         
            +
                # NOTE: Please also remove the Active Support `benchmark` dependency when removing this
         
     | 
| 
      
 8 
     | 
    
         
            +
                ActiveSupport.deprecator.warn <<~TEXT
         
     | 
| 
      
 9 
     | 
    
         
            +
                  `Benchmark.ms` is deprecated and will be removed in Rails 8.1 without replacement.
         
     | 
| 
      
 10 
     | 
    
         
            +
                TEXT
         
     | 
| 
      
 11 
     | 
    
         
            +
                ActiveSupport::Benchmark.realtime(:float_millisecond, &block)
         
     | 
| 
       15 
12 
     | 
    
         
             
              end
         
     | 
| 
       16 
13 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require "active_support/core_ext/module/redefine_method"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "active_support/class_attribute"
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            class Class
         
     | 
| 
       6 
7 
     | 
    
         
             
              # Declare a class-level attribute whose value is inheritable by subclasses.
         
     | 
| 
         @@ -91,24 +92,16 @@ class Class 
     | 
|
| 
       91 
92 
     | 
    
         
             
                    raise TypeError, "#{name.inspect} is not a symbol nor a string"
         
     | 
| 
       92 
93 
     | 
    
         
             
                  end
         
     | 
| 
       93 
94 
     | 
    
         | 
| 
       94 
     | 
    
         
            -
                   
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                    end
         
     | 
| 
       97 
     | 
    
         
            -
                  RUBY
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                  methods << <<~RUBY if instance_reader
         
     | 
| 
       100 
     | 
    
         
            -
                    silence_redefinition_of_method def #{name}
         
     | 
| 
       101 
     | 
    
         
            -
                      defined?(@#{name}) ? @#{name} : self.class.#{name}
         
     | 
| 
       102 
     | 
    
         
            -
                    end
         
     | 
| 
       103 
     | 
    
         
            -
                  RUBY
         
     | 
| 
      
 95 
     | 
    
         
            +
                  name = name.to_sym
         
     | 
| 
      
 96 
     | 
    
         
            +
                  ::ActiveSupport::ClassAttribute.redefine(self, name, default)
         
     | 
| 
       104 
97 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
                   
     | 
| 
       106 
     | 
    
         
            -
                     
     | 
| 
       107 
     | 
    
         
            -
                       
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                       
     | 
| 
       110 
     | 
    
         
            -
                     
     | 
| 
       111 
     | 
    
         
            -
                   
     | 
| 
      
 98 
     | 
    
         
            +
                  unless singleton_class?
         
     | 
| 
      
 99 
     | 
    
         
            +
                    methods << <<~RUBY if instance_reader
         
     | 
| 
      
 100 
     | 
    
         
            +
                      silence_redefinition_of_method def #{name}
         
     | 
| 
      
 101 
     | 
    
         
            +
                        defined?(@#{name}) ? @#{name} : self.class.#{name}
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    RUBY
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
       112 
105 
     | 
    
         | 
| 
       113 
106 
     | 
    
         
             
                  methods << <<~RUBY if instance_writer
         
     | 
| 
       114 
107 
     | 
    
         
             
                    silence_redefinition_of_method(:#{name}=)
         
     | 
| 
         @@ -125,7 +118,5 @@ class Class 
     | 
|
| 
       125 
118 
     | 
    
         | 
| 
       126 
119 
     | 
    
         
             
                location = caller_locations(1, 1).first
         
     | 
| 
       127 
120 
     | 
    
         
             
                class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
                attrs.each { |name| public_send("#{name}=", default) }
         
     | 
| 
       130 
121 
     | 
    
         
             
              end
         
     | 
| 
       131 
122 
     | 
    
         
             
            end
         
     | 
| 
         @@ -17,6 +17,7 @@ class Date 
     | 
|
| 
       17 
17 
     | 
    
         
             
                  date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
         
     | 
| 
       18 
18 
     | 
    
         
             
                },
         
     | 
| 
       19 
19 
     | 
    
         
             
                rfc822: "%d %b %Y",
         
     | 
| 
      
 20 
     | 
    
         
            +
                rfc2822: "%d %b %Y",
         
     | 
| 
       20 
21 
     | 
    
         
             
                iso8601: lambda { |date| date.iso8601 }
         
     | 
| 
       21 
22 
     | 
    
         
             
              }
         
     | 
| 
       22 
23 
     | 
    
         | 
| 
         @@ -34,6 +35,7 @@ class Date 
     | 
|
| 
       34 
35 
     | 
    
         
             
              #   date.to_fs(:long)          # => "November 10, 2007"
         
     | 
| 
       35 
36 
     | 
    
         
             
              #   date.to_fs(:long_ordinal)  # => "November 10th, 2007"
         
     | 
| 
       36 
37 
     | 
    
         
             
              #   date.to_fs(:rfc822)        # => "10 Nov 2007"
         
     | 
| 
      
 38 
     | 
    
         
            +
              #   date.to_fs(:rfc2822)       # => "10 Nov 2007"
         
     | 
| 
       37 
39 
     | 
    
         
             
              #   date.to_fs(:iso8601)       # => "2007-11-10"
         
     | 
| 
       38 
40 
     | 
    
         
             
              #
         
     | 
| 
       39 
41 
     | 
    
         
             
              # == Adding your own date formats to to_fs
         
     | 
| 
         @@ -26,8 +26,8 @@ module DateAndTime 
     | 
|
| 
       26 
26 
     | 
    
         
             
                    # Only warn once, the first time the value is used (which should
         
     | 
| 
       27 
27 
     | 
    
         
             
                    # be the first time #to_time is called).
         
     | 
| 
       28 
28 
     | 
    
         
             
                    ActiveSupport.deprecator.warn(
         
     | 
| 
       29 
     | 
    
         
            -
                      "to_time will always preserve the timezone  
     | 
| 
       30 
     | 
    
         
            -
                      "To opt in to the new behavior, set ` 
     | 
| 
      
 29 
     | 
    
         
            +
                      "`to_time` will always preserve the receiver timezone rather than system local time in Rails 8.1." \
         
     | 
| 
      
 30 
     | 
    
         
            +
                      "To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
         
     | 
| 
       31 
31 
     | 
    
         
             
                    )
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                    @@preserve_timezone = false
         
     | 
| 
         @@ -192,9 +192,14 @@ module Enumerable 
     | 
|
| 
       192 
192 
     | 
    
         
             
              #   # => [ Person.find(1), Person.find(5), Person.find(3) ]
         
     | 
| 
       193 
193 
     | 
    
         
             
              #
         
     | 
| 
       194 
194 
     | 
    
         
             
              # If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
         
     | 
| 
       195 
     | 
    
         
            -
              # If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result 
     | 
| 
       196 
     | 
    
         
            -
               
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
      
 195 
     | 
    
         
            +
              # If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result, unless
         
     | 
| 
      
 196 
     | 
    
         
            +
              # the +filter+ option is set to +false+.
         
     | 
| 
      
 197 
     | 
    
         
            +
              def in_order_of(key, series, filter: true)
         
     | 
| 
      
 198 
     | 
    
         
            +
                if filter
         
     | 
| 
      
 199 
     | 
    
         
            +
                  group_by(&key).values_at(*series).flatten(1).compact
         
     | 
| 
      
 200 
     | 
    
         
            +
                else
         
     | 
| 
      
 201 
     | 
    
         
            +
                  sort_by { |v| series.index(v.public_send(key)) || series.size }.compact
         
     | 
| 
      
 202 
     | 
    
         
            +
                end
         
     | 
| 
       198 
203 
     | 
    
         
             
              end
         
     | 
| 
       199 
204 
     | 
    
         | 
| 
       200 
205 
     | 
    
         
             
              # Returns the sole item in the enumerable. If there are no items, or more
         
     | 
| 
         @@ -1,18 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            class Hash
         
     | 
| 
       4 
     | 
    
         
            -
              # Returns a hash that includes everything except given keys.
         
     | 
| 
       5 
     | 
    
         
            -
              #   hash = { a: true, b: false, c: nil }
         
     | 
| 
       6 
     | 
    
         
            -
              #   hash.except(:c)     # => { a: true, b: false }
         
     | 
| 
       7 
     | 
    
         
            -
              #   hash.except(:a, :b) # => { c: nil }
         
     | 
| 
       8 
     | 
    
         
            -
              #   hash                # => { a: true, b: false, c: nil }
         
     | 
| 
       9 
     | 
    
         
            -
              #
         
     | 
| 
       10 
     | 
    
         
            -
              # This is useful for limiting a set of parameters to everything but a few known toggles:
         
     | 
| 
       11 
     | 
    
         
            -
              #   @person.update(params[:person].except(:admin))
         
     | 
| 
       12 
     | 
    
         
            -
              def except(*keys)
         
     | 
| 
       13 
     | 
    
         
            -
                slice(*self.keys - keys)
         
     | 
| 
       14 
     | 
    
         
            -
              end unless method_defined?(:except)
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
4 
     | 
    
         
             
              # Removes the given keys from hash and returns it.
         
     | 
| 
       17 
5 
     | 
    
         
             
              #   hash = { a: true, b: false, c: nil }
         
     | 
| 
       18 
6 
     | 
    
         
             
              #   hash.except!(:c) # => { a: true, b: false }
         
     | 
| 
         @@ -24,14 +24,13 @@ class Module 
     | 
|
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
                def attr_internal_naming_format=(format)
         
     | 
| 
       26 
26 
     | 
    
         
             
                  if format.start_with?("@")
         
     | 
| 
       27 
     | 
    
         
            -
                     
     | 
| 
       28 
     | 
    
         
            -
                      Setting `attr_internal_naming_format` with a `@` prefix is  
     | 
| 
      
 27 
     | 
    
         
            +
                    raise ArgumentError, <<~MESSAGE.squish
         
     | 
| 
      
 28 
     | 
    
         
            +
                      Setting `attr_internal_naming_format` with a `@` prefix is not supported.
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
                      You can simply replace #{format.inspect} by #{format.delete_prefix("@").inspect}.
         
     | 
| 
       31 
31 
     | 
    
         
             
                    MESSAGE
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                    format = format.delete_prefix("@")
         
     | 
| 
       34 
32 
     | 
    
         
             
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       35 
34 
     | 
    
         
             
                  @attr_internal_naming_format = format
         
     | 
| 
       36 
35 
     | 
    
         
             
                end
         
     | 
| 
       37 
36 
     | 
    
         
             
              end
         
     | 
| 
         @@ -65,11 +65,9 @@ class Object 
     | 
|
| 
       65 
65 
     | 
    
         
             
              end
         
     | 
| 
       66 
66 
     | 
    
         
             
            end
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
               
     | 
| 
       70 
     | 
    
         
            -
                 
     | 
| 
       71 
     | 
    
         
            -
                  to_h.as_json(options)
         
     | 
| 
       72 
     | 
    
         
            -
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
            class Data # :nodoc:
         
     | 
| 
      
 69 
     | 
    
         
            +
              def as_json(options = nil)
         
     | 
| 
      
 70 
     | 
    
         
            +
                to_h.as_json(options)
         
     | 
| 
       73 
71 
     | 
    
         
             
              end
         
     | 
| 
       74 
72 
     | 
    
         
             
            end
         
     | 
| 
       75 
73 
     | 
    
         | 
| 
         @@ -105,7 +103,7 @@ end 
     | 
|
| 
       105 
103 
     | 
    
         | 
| 
       106 
104 
     | 
    
         
             
            class Symbol
         
     | 
| 
       107 
105 
     | 
    
         
             
              def as_json(options = nil) # :nodoc:
         
     | 
| 
       108 
     | 
    
         
            -
                 
     | 
| 
      
 106 
     | 
    
         
            +
                name
         
     | 
| 
       109 
107 
     | 
    
         
             
              end
         
     | 
| 
       110 
108 
     | 
    
         
             
            end
         
     | 
| 
       111 
109 
     | 
    
         | 
| 
         @@ -164,7 +162,12 @@ end 
     | 
|
| 
       164 
162 
     | 
    
         | 
| 
       165 
163 
     | 
    
         
             
            class Array
         
     | 
| 
       166 
164 
     | 
    
         
             
              def as_json(options = nil) # :nodoc:
         
     | 
| 
       167 
     | 
    
         
            -
                 
     | 
| 
      
 165 
     | 
    
         
            +
                if options
         
     | 
| 
      
 166 
     | 
    
         
            +
                  options = options.dup.freeze unless options.frozen?
         
     | 
| 
      
 167 
     | 
    
         
            +
                  map { |v| v.as_json(options) }
         
     | 
| 
      
 168 
     | 
    
         
            +
                else
         
     | 
| 
      
 169 
     | 
    
         
            +
                  map { |v| v.as_json }
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
       168 
171 
     | 
    
         
             
              end
         
     | 
| 
       169 
172 
     | 
    
         
             
            end
         
     | 
| 
       170 
173 
     | 
    
         | 
| 
         @@ -184,8 +187,11 @@ class Hash 
     | 
|
| 
       184 
187 
     | 
    
         
             
                end
         
     | 
| 
       185 
188 
     | 
    
         | 
| 
       186 
189 
     | 
    
         
             
                result = {}
         
     | 
| 
       187 
     | 
    
         
            -
                 
     | 
| 
       188 
     | 
    
         
            -
                   
     | 
| 
      
 190 
     | 
    
         
            +
                if options
         
     | 
| 
      
 191 
     | 
    
         
            +
                  options = options.dup.freeze unless options.frozen?
         
     | 
| 
      
 192 
     | 
    
         
            +
                  subset.each { |k, v| result[k.to_s] = v.as_json(options) }
         
     | 
| 
      
 193 
     | 
    
         
            +
                else
         
     | 
| 
      
 194 
     | 
    
         
            +
                  subset.each { |k, v| result[k.to_s] = v.as_json }
         
     | 
| 
       189 
195 
     | 
    
         
             
                end
         
     | 
| 
       190 
196 
     | 
    
         
             
                result
         
     | 
| 
       191 
197 
     | 
    
         
             
              end
         
     | 
| 
         @@ -233,9 +239,11 @@ class Pathname # :nodoc: 
     | 
|
| 
       233 
239 
     | 
    
         
             
              end
         
     | 
| 
       234 
240 
     | 
    
         
             
            end
         
     | 
| 
       235 
241 
     | 
    
         | 
| 
       236 
     | 
    
         
            -
             
     | 
| 
       237 
     | 
    
         
            -
               
     | 
| 
       238 
     | 
    
         
            -
                 
     | 
| 
      
 242 
     | 
    
         
            +
            unless IPAddr.method_defined?(:as_json, false)
         
     | 
| 
      
 243 
     | 
    
         
            +
              class IPAddr # :nodoc:
         
     | 
| 
      
 244 
     | 
    
         
            +
                def as_json(options = nil)
         
     | 
| 
      
 245 
     | 
    
         
            +
                  to_s
         
     | 
| 
      
 246 
     | 
    
         
            +
                end
         
     | 
| 
       239 
247 
     | 
    
         
             
              end
         
     | 
| 
       240 
248 
     | 
    
         
             
            end
         
     | 
| 
       241 
249 
     | 
    
         | 
| 
         @@ -19,7 +19,7 @@ class String 
     | 
|
| 
       19 
19 
     | 
    
         
             
              #   >> "lj".upcase
         
     | 
| 
       20 
20 
     | 
    
         
             
              #   => "LJ"
         
     | 
| 
       21 
21 
     | 
    
         
             
              #
         
     | 
| 
       22 
     | 
    
         
            -
              # == Method chaining
         
     | 
| 
      
 22 
     | 
    
         
            +
              # == \Method chaining
         
     | 
| 
       23 
23 
     | 
    
         
             
              #
         
     | 
| 
       24 
24 
     | 
    
         
             
              # All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
         
     | 
| 
       25 
25 
     | 
    
         
             
              # method chaining on the result of any of these methods.
         
     | 
| 
         @@ -1,12 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            class Thread::Backtrace::Location # :nodoc:
         
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
       5 
     | 
    
         
            -
                 
     | 
| 
       6 
     | 
    
         
            -
                  ErrorHighlight.spot(ex, backtrace_location: self)
         
     | 
| 
       7 
     | 
    
         
            -
                end
         
     | 
| 
       8 
     | 
    
         
            -
              else
         
     | 
| 
       9 
     | 
    
         
            -
                def spot(ex)
         
     | 
| 
       10 
     | 
    
         
            -
                end
         
     | 
| 
      
 4 
     | 
    
         
            +
              def spot(ex)
         
     | 
| 
      
 5 
     | 
    
         
            +
                ErrorHighlight.spot(ex, backtrace_location: self)
         
     | 
| 
       11 
6 
     | 
    
         
             
              end
         
     | 
| 
       12 
7 
     | 
    
         
             
            end
         
     | 
| 
         @@ -147,6 +147,13 @@ class Time 
     | 
|
| 
       147 
147 
     | 
    
         
             
                elsif zone.respond_to?(:utc_to_local)
         
     | 
| 
       148 
148 
     | 
    
         
             
                  new_time = ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
         
     | 
| 
       149 
149 
     | 
    
         | 
| 
      
 150 
     | 
    
         
            +
                  # Some versions of Ruby have a bug where Time.new with a zone object and
         
     | 
| 
      
 151 
     | 
    
         
            +
                  # fractional seconds will end up with a broken utc_offset.
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # This is fixed in Ruby 3.3.1 and 3.2.4
         
     | 
| 
      
 153 
     | 
    
         
            +
                  unless new_time.utc_offset.integer?
         
     | 
| 
      
 154 
     | 
    
         
            +
                    new_time += 0
         
     | 
| 
      
 155 
     | 
    
         
            +
                  end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
       150 
157 
     | 
    
         
             
                  # When there are two occurrences of a nominal time due to DST ending,
         
     | 
| 
       151 
158 
     | 
    
         
             
                  # `Time.new` chooses the first chronological occurrence (the one with a
         
     | 
| 
       152 
159 
     | 
    
         
             
                  # larger UTC offset). However, for `change`, we want to choose the
         
     | 
| 
         @@ -217,8 +224,13 @@ class Time 
     | 
|
| 
       217 
224 
     | 
    
         
             
              # Returns a new Time representing the time a number of seconds since the instance time
         
     | 
| 
       218 
225 
     | 
    
         
             
              def since(seconds)
         
     | 
| 
       219 
226 
     | 
    
         
             
                self + seconds
         
     | 
| 
       220 
     | 
    
         
            -
              rescue
         
     | 
| 
       221 
     | 
    
         
            -
                to_datetime.since(seconds)
         
     | 
| 
      
 227 
     | 
    
         
            +
              rescue TypeError
         
     | 
| 
      
 228 
     | 
    
         
            +
                result = to_datetime.since(seconds)
         
     | 
| 
      
 229 
     | 
    
         
            +
                ActiveSupport.deprecator.warn(
         
     | 
| 
      
 230 
     | 
    
         
            +
                  "Passing an instance of #{seconds.class} to #{self.class}#since is deprecated. This behavior will raise " \
         
     | 
| 
      
 231 
     | 
    
         
            +
                  "a `TypeError` in Rails 8.1."
         
     | 
| 
      
 232 
     | 
    
         
            +
                )
         
     | 
| 
      
 233 
     | 
    
         
            +
                result
         
     | 
| 
       222 
234 
     | 
    
         
             
              end
         
     | 
| 
       223 
235 
     | 
    
         
             
              alias :in :since
         
     | 
| 
       224 
236 
     | 
    
         | 
| 
         @@ -15,10 +15,18 @@ class Time 
     | 
|
| 
       15 
15 
     | 
    
         
             
              end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
              def preserve_timezone # :nodoc:
         
     | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
      
 18 
     | 
    
         
            +
                system_local_time? || super
         
     | 
| 
       19 
19 
     | 
    
         
             
              end
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
              private
         
     | 
| 
      
 22 
     | 
    
         
            +
                def system_local_time?
         
     | 
| 
      
 23 
     | 
    
         
            +
                  if ::Time.equal?(self.class)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    zone = self.zone
         
     | 
| 
      
 25 
     | 
    
         
            +
                    String === zone &&
         
     | 
| 
      
 26 
     | 
    
         
            +
                      (zone != "UTC" || active_support_local_zone == "UTC")
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       22 
30 
     | 
    
         
             
                @@active_support_local_tz = nil
         
     | 
| 
       23 
31 
     | 
    
         | 
| 
       24 
32 
     | 
    
         
             
                def active_support_local_zone
         
     | 
| 
         @@ -22,6 +22,7 @@ class Time 
     | 
|
| 
       22 
22 
     | 
    
         
             
                  offset_format = time.formatted_offset(false)
         
     | 
| 
       23 
23 
     | 
    
         
             
                  time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
         
     | 
| 
       24 
24 
     | 
    
         
             
                },
         
     | 
| 
      
 25 
     | 
    
         
            +
                rfc2822: lambda { |time| time.rfc2822 },
         
     | 
| 
       25 
26 
     | 
    
         
             
                iso8601: lambda { |time| time.iso8601 }
         
     | 
| 
       26 
27 
     | 
    
         
             
              }
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
         @@ -40,6 +41,7 @@ class Time 
     | 
|
| 
       40 
41 
     | 
    
         
             
              #   time.to_fs(:long)         # => "January 18, 2007 06:10"
         
     | 
| 
       41 
42 
     | 
    
         
             
              #   time.to_fs(:long_ordinal) # => "January 18th, 2007 06:10"
         
     | 
| 
       42 
43 
     | 
    
         
             
              #   time.to_fs(:rfc822)       # => "Thu, 18 Jan 2007 06:10:17 -0600"
         
     | 
| 
      
 44 
     | 
    
         
            +
              #   time.to_fs(:rfc2822)       # => "Thu, 18 Jan 2007 06:10:17 -0600"
         
     | 
| 
       43 
45 
     | 
    
         
             
              #   time.to_fs(:iso8601)      # => "2007-01-18T06:10:17-06:00"
         
     | 
| 
       44 
46 
     | 
    
         
             
              #
         
     | 
| 
       45 
47 
     | 
    
         
             
              # == Adding your own time formats to +to_fs+
         
     | 
| 
         @@ -20,7 +20,7 @@ class Time 
     | 
|
| 
       20 
20 
     | 
    
         
             
                # This method accepts any of the following:
         
     | 
| 
       21 
21 
     | 
    
         
             
                #
         
     | 
| 
       22 
22 
     | 
    
         
             
                # * A \Rails TimeZone object.
         
     | 
| 
       23 
     | 
    
         
            -
                # * An identifier for a \Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
         
     | 
| 
      
 23 
     | 
    
         
            +
                # * An identifier for a \Rails TimeZone object (e.g., "Eastern \Time (US & Canada)", <tt>-5.hours</tt>).
         
     | 
| 
       24 
24 
     | 
    
         
             
                # * A +TZInfo::Timezone+ object.
         
     | 
| 
       25 
25 
     | 
    
         
             
                # * An identifier for a +TZInfo::Timezone+ object (e.g., "America/New_York").
         
     | 
| 
       26 
26 
     | 
    
         
             
                #
         
     | 
| 
         @@ -95,6 +95,8 @@ module ActiveSupport 
     | 
|
| 
       95 
95 
     | 
    
         | 
| 
       96 
96 
     | 
    
         
             
                INVALID_ATTRIBUTE_NAMES = [:set, :reset, :resets, :instance, :before_reset, :after_reset, :reset_all, :clear_all] # :nodoc:
         
     | 
| 
       97 
97 
     | 
    
         | 
| 
      
 98 
     | 
    
         
            +
                NOT_SET = Object.new.freeze # :nodoc:
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
       98 
100 
     | 
    
         
             
                class << self
         
     | 
| 
       99 
101 
     | 
    
         
             
                  # Returns singleton instance for this class in this thread. If none exists, one is created.
         
     | 
| 
       100 
102 
     | 
    
         
             
                  def instance
         
     | 
| 
         @@ -109,7 +111,7 @@ module ActiveSupport 
     | 
|
| 
       109 
111 
     | 
    
         
             
                  # is a proc or lambda, it will be called whenever an instance is
         
     | 
| 
       110 
112 
     | 
    
         
             
                  # constructed. Otherwise, the value will be duplicated with +#dup+.
         
     | 
| 
       111 
113 
     | 
    
         
             
                  # Default values are re-assigned when the attributes are reset.
         
     | 
| 
       112 
     | 
    
         
            -
                  def attribute(*names, default:  
     | 
| 
      
 114 
     | 
    
         
            +
                  def attribute(*names, default: NOT_SET)
         
     | 
| 
       113 
115 
     | 
    
         
             
                    invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
         
     | 
| 
       114 
116 
     | 
    
         
             
                    if invalid_attribute_names.any?
         
     | 
| 
       115 
117 
     | 
    
         
             
                      raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
         
     | 
| 
         @@ -221,8 +223,10 @@ module ActiveSupport 
     | 
|
| 
       221 
223 
     | 
    
         | 
| 
       222 
224 
     | 
    
         
             
                private
         
     | 
| 
       223 
225 
     | 
    
         
             
                  def resolve_defaults
         
     | 
| 
       224 
     | 
    
         
            -
                    defaults. 
     | 
| 
       225 
     | 
    
         
            -
                       
     | 
| 
      
 226 
     | 
    
         
            +
                    defaults.each_with_object({}) do |(key, value), result|
         
     | 
| 
      
 227 
     | 
    
         
            +
                      if value != NOT_SET
         
     | 
| 
      
 228 
     | 
    
         
            +
                        result[key] = Proc === value ? value.call : value.dup
         
     | 
| 
      
 229 
     | 
    
         
            +
                      end
         
     | 
| 
       226 
230 
     | 
    
         
             
                    end
         
     | 
| 
       227 
231 
     | 
    
         
             
                  end
         
     | 
| 
       228 
232 
     | 
    
         
             
              end
         
     | 
| 
         @@ -139,7 +139,6 @@ module ActiveSupport 
     | 
|
| 
       139 
139 
     | 
    
         | 
| 
       140 
140 
     | 
    
         
             
                    def extract_callstack(callstack)
         
     | 
| 
       141 
141 
     | 
    
         
             
                      return [] if callstack.empty?
         
     | 
| 
       142 
     | 
    
         
            -
                      return _extract_callstack(callstack) if callstack.first.is_a? String
         
     | 
| 
       143 
142 
     | 
    
         | 
| 
       144 
143 
     | 
    
         
             
                      offending_line = callstack.find { |frame|
         
     | 
| 
       145 
144 
     | 
    
         
             
                        # Code generated with `eval` doesn't have an `absolute_path`, e.g. templates.
         
     | 
| 
         @@ -150,26 +149,8 @@ module ActiveSupport 
     | 
|
| 
       150 
149 
     | 
    
         
             
                      [offending_line.path, offending_line.lineno, offending_line.label]
         
     | 
| 
       151 
150 
     | 
    
         
             
                    end
         
     | 
| 
       152 
151 
     | 
    
         | 
| 
       153 
     | 
    
         
            -
                     
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
                        Passing the result of `caller` to ActiveSupport::Deprecation#warn is deprecated and will be removed in Rails 8.0.
         
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
       157 
     | 
    
         
            -
                        Please pass the result of `caller_locations` instead.
         
     | 
| 
       158 
     | 
    
         
            -
                      MESSAGE
         
     | 
| 
       159 
     | 
    
         
            -
             
     | 
| 
       160 
     | 
    
         
            -
                      offending_line = callstack.find { |line| !ignored_callstack?(line) } || callstack.first
         
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
                      if offending_line
         
     | 
| 
       163 
     | 
    
         
            -
                        if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
         
     | 
| 
       164 
     | 
    
         
            -
                          md.captures
         
     | 
| 
       165 
     | 
    
         
            -
                        else
         
     | 
| 
       166 
     | 
    
         
            -
                          offending_line
         
     | 
| 
       167 
     | 
    
         
            -
                        end
         
     | 
| 
       168 
     | 
    
         
            -
                      end
         
     | 
| 
       169 
     | 
    
         
            -
                    end
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                    RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/"
         
     | 
| 
       172 
     | 
    
         
            -
                    LIB_DIR = RbConfig::CONFIG["libdir"]
         
     | 
| 
      
 152 
     | 
    
         
            +
                    RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/" # :nodoc:
         
     | 
| 
      
 153 
     | 
    
         
            +
                    LIB_DIR = RbConfig::CONFIG["libdir"] # :nodoc:
         
     | 
| 
       173 
154 
     | 
    
         | 
| 
       174 
155 
     | 
    
         
             
                    def ignored_callstack?(path)
         
     | 
| 
       175 
156 
     | 
    
         
             
                      path.start_with?(RAILS_GEM_ROOT, LIB_DIR) || path.include?("<internal:")
         
     | 
| 
         @@ -68,7 +68,7 @@ module ActiveSupport 
     | 
|
| 
       68 
68 
     | 
    
         
             
                # and the second is a library name.
         
     | 
| 
       69 
69 
     | 
    
         
             
                #
         
     | 
| 
       70 
70 
     | 
    
         
             
                #   ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
         
     | 
| 
       71 
     | 
    
         
            -
                def initialize(deprecation_horizon = "8. 
     | 
| 
      
 71 
     | 
    
         
            +
                def initialize(deprecation_horizon = "8.1", gem_name = "Rails")
         
     | 
| 
       72 
72 
     | 
    
         
             
                  self.gem_name = gem_name
         
     | 
| 
       73 
73 
     | 
    
         
             
                  self.deprecation_horizon = deprecation_horizon
         
     | 
| 
       74 
74 
     | 
    
         
             
                  # By default, warnings are not silenced and debugging is off.
         
     | 
| 
         @@ -491,17 +491,21 @@ module ActiveSupport 
     | 
|
| 
       491 
491 
     | 
    
         
             
                    if @parts.empty?
         
     | 
| 
       492 
492 
     | 
    
         
             
                      time.since(sign * value)
         
     | 
| 
       493 
493 
     | 
    
         
             
                    else
         
     | 
| 
       494 
     | 
    
         
            -
                      @parts. 
     | 
| 
       495 
     | 
    
         
            -
                         
     | 
| 
       496 
     | 
    
         
            -
             
     | 
| 
       497 
     | 
    
         
            -
             
     | 
| 
       498 
     | 
    
         
            -
             
     | 
| 
       499 
     | 
    
         
            -
             
     | 
| 
       500 
     | 
    
         
            -
             
     | 
| 
       501 
     | 
    
         
            -
             
     | 
| 
       502 
     | 
    
         
            -
             
     | 
| 
       503 
     | 
    
         
            -
             
     | 
| 
      
 494 
     | 
    
         
            +
                      @parts.each do |type, number|
         
     | 
| 
      
 495 
     | 
    
         
            +
                        t = time
         
     | 
| 
      
 496 
     | 
    
         
            +
                        time =
         
     | 
| 
      
 497 
     | 
    
         
            +
                          if type == :seconds
         
     | 
| 
      
 498 
     | 
    
         
            +
                            t.since(sign * number)
         
     | 
| 
      
 499 
     | 
    
         
            +
                          elsif type == :minutes
         
     | 
| 
      
 500 
     | 
    
         
            +
                            t.since(sign * number * 60)
         
     | 
| 
      
 501 
     | 
    
         
            +
                          elsif type == :hours
         
     | 
| 
      
 502 
     | 
    
         
            +
                            t.since(sign * number * 3600)
         
     | 
| 
      
 503 
     | 
    
         
            +
                          else
         
     | 
| 
      
 504 
     | 
    
         
            +
                            t.advance(type => sign * number)
         
     | 
| 
      
 505 
     | 
    
         
            +
                          end
         
     | 
| 
       504 
506 
     | 
    
         
             
                      end
         
     | 
| 
      
 507 
     | 
    
         
            +
             
     | 
| 
      
 508 
     | 
    
         
            +
                      time
         
     | 
| 
       505 
509 
     | 
    
         
             
                    end
         
     | 
| 
       506 
510 
     | 
    
         
             
                  end
         
     | 
| 
       507 
511 
     | 
    
         | 
| 
         @@ -43,6 +43,12 @@ module ActiveSupport 
     | 
|
| 
       43 
43 
     | 
    
         
             
                  end
         
     | 
| 
       44 
44 
     | 
    
         
             
                end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
      
 46 
     | 
    
         
            +
                class InvalidKeyError < RuntimeError
         
     | 
| 
      
 47 
     | 
    
         
            +
                  def initialize(content_path, key)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    super "Key '#{key}' is invalid, it must respond to '#to_sym' from configuration in '#{content_path}'."
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
       46 
52 
     | 
    
         
             
                delegate_missing_to :options
         
     | 
| 
       47 
53 
     | 
    
         | 
| 
       48 
54 
     | 
    
         
             
                def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
         
     | 
| 
         @@ -61,7 +67,11 @@ module ActiveSupport 
     | 
|
| 
       61 
67 
     | 
    
         
             
                end
         
     | 
| 
       62 
68 
     | 
    
         | 
| 
       63 
69 
     | 
    
         
             
                def validate! # :nodoc:
         
     | 
| 
       64 
     | 
    
         
            -
                  deserialize(read)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  deserialize(read).each_key do |key|
         
     | 
| 
      
 71 
     | 
    
         
            +
                    key.to_sym
         
     | 
| 
      
 72 
     | 
    
         
            +
                  rescue NoMethodError
         
     | 
| 
      
 73 
     | 
    
         
            +
                    raise InvalidKeyError.new(content_path, key)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
       65 
75 
     | 
    
         
             
                end
         
     | 
| 
       66 
76 
     | 
    
         | 
| 
       67 
77 
     | 
    
         
             
                # Returns the decrypted content as a Hash with symbolized keys.
         
     | 
| 
         @@ -73,7 +83,7 @@ module ActiveSupport 
     | 
|
| 
       73 
83 
     | 
    
         
             
                #   # => { some_secret: 123, some_namespace: { another_secret: 789 } }
         
     | 
| 
       74 
84 
     | 
    
         
             
                #
         
     | 
| 
       75 
85 
     | 
    
         
             
                def config
         
     | 
| 
       76 
     | 
    
         
            -
                  @config ||= deserialize(read) 
     | 
| 
      
 86 
     | 
    
         
            +
                  @config ||= deep_symbolize_keys(deserialize(read))
         
     | 
| 
       77 
87 
     | 
    
         
             
                end
         
     | 
| 
       78 
88 
     | 
    
         | 
| 
       79 
89 
     | 
    
         
             
                def inspect # :nodoc:
         
     | 
| 
         @@ -81,6 +91,14 @@ module ActiveSupport 
     | 
|
| 
       81 
91 
     | 
    
         
             
                end
         
     | 
| 
       82 
92 
     | 
    
         | 
| 
       83 
93 
     | 
    
         
             
                private
         
     | 
| 
      
 94 
     | 
    
         
            +
                  def deep_symbolize_keys(hash)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    hash.deep_transform_keys do |key|
         
     | 
| 
      
 96 
     | 
    
         
            +
                      key.to_sym
         
     | 
| 
      
 97 
     | 
    
         
            +
                    rescue NoMethodError
         
     | 
| 
      
 98 
     | 
    
         
            +
                      raise InvalidKeyError.new(content_path, key)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
       84 
102 
     | 
    
         
             
                  def deep_transform(hash)
         
     | 
| 
       85 
103 
     | 
    
         
             
                    return hash unless hash.is_a?(Hash)
         
     | 
| 
       86 
104 
     | 
    
         | 
| 
         @@ -144,9 +144,9 @@ module ActiveSupport 
     | 
|
| 
       144 
144 
     | 
    
         
             
                #
         
     | 
| 
       145 
145 
     | 
    
         
             
                def unexpected(error, severity: :warning, context: {}, source: DEFAULT_SOURCE)
         
     | 
| 
       146 
146 
     | 
    
         
             
                  error = RuntimeError.new(error) if error.is_a?(String)
         
     | 
| 
       147 
     | 
    
         
            -
                  error.set_backtrace(caller(1)) if error.backtrace.nil?
         
     | 
| 
       148 
147 
     | 
    
         | 
| 
       149 
148 
     | 
    
         
             
                  if @debug_mode
         
     | 
| 
      
 149 
     | 
    
         
            +
                    ensure_backtrace(error)
         
     | 
| 
       150 
150 
     | 
    
         
             
                    raise UnexpectedError, "#{error.class.name}: #{error.message}", error.backtrace, cause: error
         
     | 
| 
       151 
151 
     | 
    
         
             
                  else
         
     | 
| 
       152 
152 
     | 
    
         
             
                    report(error, handled: true, severity: severity, context: context, source: source)
         
     | 
| 
         @@ -209,6 +209,7 @@ module ActiveSupport 
     | 
|
| 
       209 
209 
     | 
    
         
             
                #
         
     | 
| 
       210 
210 
     | 
    
         
             
                def report(error, handled: true, severity: handled ? :warning : :error, context: {}, source: DEFAULT_SOURCE)
         
     | 
| 
       211 
211 
     | 
    
         
             
                  return if error.instance_variable_defined?(:@__rails_error_reported)
         
     | 
| 
      
 212 
     | 
    
         
            +
                  ensure_backtrace(error)
         
     | 
| 
       212 
213 
     | 
    
         | 
| 
       213 
214 
     | 
    
         
             
                  unless SEVERITIES.include?(severity)
         
     | 
| 
       214 
215 
     | 
    
         
             
                    raise ArgumentError, "severity must be one of #{SEVERITIES.map(&:inspect).join(", ")}, got: #{severity.inspect}"
         
     | 
| 
         @@ -237,5 +238,28 @@ module ActiveSupport 
     | 
|
| 
       237 
238 
     | 
    
         | 
| 
       238 
239 
     | 
    
         
             
                  nil
         
     | 
| 
       239 
240 
     | 
    
         
             
                end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                private
         
     | 
| 
      
 243 
     | 
    
         
            +
                  def ensure_backtrace(error)
         
     | 
| 
      
 244 
     | 
    
         
            +
                    return if error.frozen? # re-raising won't add a backtrace
         
     | 
| 
      
 245 
     | 
    
         
            +
                    return unless error.backtrace.nil?
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 248 
     | 
    
         
            +
                      # We could use Exception#set_backtrace, but until Ruby 3.4
         
     | 
| 
      
 249 
     | 
    
         
            +
                      # it only support setting `Exception#backtrace` and not
         
     | 
| 
      
 250 
     | 
    
         
            +
                      # `Exception#backtrace_locations`. So raising the exception
         
     | 
| 
      
 251 
     | 
    
         
            +
                      # is a good way to build a real backtrace.
         
     | 
| 
      
 252 
     | 
    
         
            +
                      raise error
         
     | 
| 
      
 253 
     | 
    
         
            +
                    rescue error.class => error
         
     | 
| 
      
 254 
     | 
    
         
            +
                    end
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
                    count = 0
         
     | 
| 
      
 257 
     | 
    
         
            +
                    while error.backtrace_locations.first&.path == __FILE__
         
     | 
| 
      
 258 
     | 
    
         
            +
                      count += 1
         
     | 
| 
      
 259 
     | 
    
         
            +
                      error.backtrace_locations.shift
         
     | 
| 
      
 260 
     | 
    
         
            +
                    end
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                    error.backtrace.shift(count)
         
     | 
| 
      
 263 
     | 
    
         
            +
                  end
         
     | 
| 
       240 
264 
     | 
    
         
             
              end
         
     | 
| 
       241 
265 
     | 
    
         
             
            end
         
     |