Remove unused parts of activesupport
This commit is contained in:
		
							parent
							
								
									3b92bb9da5
								
							
						
					
					
						commit
						6935b84584
					
				@ -1,48 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Actionable errors let's you define actions to resolve an error.
 | 
			
		||||
  #
 | 
			
		||||
  # To make an error actionable, include the <tt>ActiveSupport::ActionableError</tt>
 | 
			
		||||
  # module and invoke the +action+ class macro to define the action. An action
 | 
			
		||||
  # needs a name and a block to execute.
 | 
			
		||||
  module ActionableError
 | 
			
		||||
    extend Concern
 | 
			
		||||
 | 
			
		||||
    class NonActionable < StandardError; end
 | 
			
		||||
 | 
			
		||||
    included do
 | 
			
		||||
      class_attribute :_actions, default: {}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.actions(error) # :nodoc:
 | 
			
		||||
      case error
 | 
			
		||||
      when ActionableError, -> it { Class === it && it < ActionableError }
 | 
			
		||||
        error._actions
 | 
			
		||||
      else
 | 
			
		||||
        {}
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.dispatch(error, name) # :nodoc:
 | 
			
		||||
      actions(error).fetch(name).call
 | 
			
		||||
    rescue KeyError
 | 
			
		||||
      raise NonActionable, "Cannot find action \"#{name}\""
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module ClassMethods
 | 
			
		||||
      # Defines an action that can resolve the error.
 | 
			
		||||
      #
 | 
			
		||||
      #   class PendingMigrationError < MigrationError
 | 
			
		||||
      #     include ActiveSupport::ActionableError
 | 
			
		||||
      #
 | 
			
		||||
      #     action "Run pending migrations" do
 | 
			
		||||
      #       ActiveRecord::Tasks::DatabaseTasks.migrate
 | 
			
		||||
      #     end
 | 
			
		||||
      #   end
 | 
			
		||||
      def action(name, &block)
 | 
			
		||||
        _actions[name] = block
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,50 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/symbol/starts_ends_with"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
 | 
			
		||||
  # its string-like contents:
 | 
			
		||||
  #
 | 
			
		||||
  #   variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
 | 
			
		||||
  #
 | 
			
		||||
  #   variants.phone?    # => true
 | 
			
		||||
  #   variants.tablet?   # => true
 | 
			
		||||
  #   variants.desktop?  # => false
 | 
			
		||||
  class ArrayInquirer < Array
 | 
			
		||||
    # Passes each element of +candidates+ collection to ArrayInquirer collection.
 | 
			
		||||
    # The method returns true if any element from the ArrayInquirer collection
 | 
			
		||||
    # is equal to the stringified or symbolized form of any element in the +candidates+ collection.
 | 
			
		||||
    #
 | 
			
		||||
    # If +candidates+ collection is not given, method returns true.
 | 
			
		||||
    #
 | 
			
		||||
    #   variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
 | 
			
		||||
    #
 | 
			
		||||
    #   variants.any?                      # => true
 | 
			
		||||
    #   variants.any?(:phone, :tablet)     # => true
 | 
			
		||||
    #   variants.any?('phone', 'desktop')  # => true
 | 
			
		||||
    #   variants.any?(:desktop, :watch)    # => false
 | 
			
		||||
    def any?(*candidates)
 | 
			
		||||
      if candidates.none?
 | 
			
		||||
        super
 | 
			
		||||
      else
 | 
			
		||||
        candidates.any? do |candidate|
 | 
			
		||||
          include?(candidate.to_sym) || include?(candidate.to_s)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def respond_to_missing?(name, include_private = false)
 | 
			
		||||
        name.end_with?("?") || super
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def method_missing(name, *args)
 | 
			
		||||
        if name.end_with?("?")
 | 
			
		||||
          any?(name[0..-2])
 | 
			
		||||
        else
 | 
			
		||||
          super
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,131 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Backtraces often include many lines that are not relevant for the context
 | 
			
		||||
  # under review. This makes it hard to find the signal amongst the backtrace
 | 
			
		||||
  # noise, and adds debugging time. With a BacktraceCleaner, filters and
 | 
			
		||||
  # silencers are used to remove the noisy lines, so that only the most relevant
 | 
			
		||||
  # lines remain.
 | 
			
		||||
  #
 | 
			
		||||
  # Filters are used to modify lines of data, while silencers are used to remove
 | 
			
		||||
  # lines entirely. The typical filter use case is to remove lengthy path
 | 
			
		||||
  # information from the start of each line, and view file paths relevant to the
 | 
			
		||||
  # app directory instead of the file system root. The typical silencer use case
 | 
			
		||||
  # is to exclude the output of a noisy library from the backtrace, so that you
 | 
			
		||||
  # can focus on the rest.
 | 
			
		||||
  #
 | 
			
		||||
  #   bc = ActiveSupport::BacktraceCleaner.new
 | 
			
		||||
  #   bc.add_filter   { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
 | 
			
		||||
  #   bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
 | 
			
		||||
  #   bc.clean(exception.backtrace) # perform the cleanup
 | 
			
		||||
  #
 | 
			
		||||
  # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
 | 
			
		||||
  # and show as much data as possible, you can always call
 | 
			
		||||
  # <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
 | 
			
		||||
  # backtrace to a pristine state. If you need to reconfigure an existing
 | 
			
		||||
  # BacktraceCleaner so that it does not filter or modify the paths of any lines
 | 
			
		||||
  # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
 | 
			
		||||
  # These two methods will give you a completely untouched backtrace.
 | 
			
		||||
  #
 | 
			
		||||
  # Inspired by the Quiet Backtrace gem by thoughtbot.
 | 
			
		||||
  class BacktraceCleaner
 | 
			
		||||
    def initialize
 | 
			
		||||
      @filters, @silencers = [], []
 | 
			
		||||
      add_gem_filter
 | 
			
		||||
      add_gem_silencer
 | 
			
		||||
      add_stdlib_silencer
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the backtrace after all filters and silencers have been run
 | 
			
		||||
    # against it. Filters run first, then silencers.
 | 
			
		||||
    def clean(backtrace, kind = :silent)
 | 
			
		||||
      filtered = filter_backtrace(backtrace)
 | 
			
		||||
 | 
			
		||||
      case kind
 | 
			
		||||
      when :silent
 | 
			
		||||
        silence(filtered)
 | 
			
		||||
      when :noise
 | 
			
		||||
        noise(filtered)
 | 
			
		||||
      else
 | 
			
		||||
        filtered
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    alias :filter :clean
 | 
			
		||||
 | 
			
		||||
    # Adds a filter from the block provided. Each line in the backtrace will be
 | 
			
		||||
    # mapped against this filter.
 | 
			
		||||
    #
 | 
			
		||||
    #   # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
 | 
			
		||||
    #   backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
 | 
			
		||||
    def add_filter(&block)
 | 
			
		||||
      @filters << block
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Adds a silencer from the block provided. If the silencer returns +true+
 | 
			
		||||
    # for a given line, it will be excluded from the clean backtrace.
 | 
			
		||||
    #
 | 
			
		||||
    #   # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
 | 
			
		||||
    #   backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
 | 
			
		||||
    def add_silencer(&block)
 | 
			
		||||
      @silencers << block
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Removes all silencers, but leaves in the filters. Useful if your
 | 
			
		||||
    # context of debugging suddenly expands as you suspect a bug in one of
 | 
			
		||||
    # the libraries you use.
 | 
			
		||||
    def remove_silencers!
 | 
			
		||||
      @silencers = []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Removes all filters, but leaves in the silencers. Useful if you suddenly
 | 
			
		||||
    # need to see entire filepaths in the backtrace that you had already
 | 
			
		||||
    # filtered out.
 | 
			
		||||
    def remove_filters!
 | 
			
		||||
      @filters = []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      FORMATTED_GEMS_PATTERN = /\A[^\/]+ \([\w.]+\) /
 | 
			
		||||
 | 
			
		||||
      def add_gem_filter
 | 
			
		||||
        gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
 | 
			
		||||
        return if gems_paths.empty?
 | 
			
		||||
 | 
			
		||||
        gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
 | 
			
		||||
        gems_result = '\3 (\4) \5'
 | 
			
		||||
        add_filter { |line| line.sub(gems_regexp, gems_result) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def add_gem_silencer
 | 
			
		||||
        add_silencer { |line| FORMATTED_GEMS_PATTERN.match?(line) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def add_stdlib_silencer
 | 
			
		||||
        add_silencer { |line| line.start_with?(RbConfig::CONFIG["rubylibdir"]) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def filter_backtrace(backtrace)
 | 
			
		||||
        @filters.each do |f|
 | 
			
		||||
          backtrace = backtrace.map { |line| f.call(line) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        backtrace
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def silence(backtrace)
 | 
			
		||||
        @silencers.each do |s|
 | 
			
		||||
          backtrace = backtrace.reject { |line| s.call(line) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        backtrace
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def noise(backtrace)
 | 
			
		||||
        backtrace.select do |line|
 | 
			
		||||
          @silencers.any? do |s|
 | 
			
		||||
            s.call(line)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,51 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/benchmark"
 | 
			
		||||
require "active_support/core_ext/hash/keys"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module Benchmarkable
 | 
			
		||||
    # Allows you to measure the execution time of a block in a template and
 | 
			
		||||
    # records the result to the log. Wrap this block around expensive operations
 | 
			
		||||
    # or possible bottlenecks to get a time reading for the operation. For
 | 
			
		||||
    # example, let's say you thought your file processing method was taking too
 | 
			
		||||
    # long; you could wrap it in a benchmark block.
 | 
			
		||||
    #
 | 
			
		||||
    #  <% benchmark 'Process data files' do %>
 | 
			
		||||
    #    <%= expensive_files_operation %>
 | 
			
		||||
    #  <% end %>
 | 
			
		||||
    #
 | 
			
		||||
    # That would add something like "Process data files (345.2ms)" to the log,
 | 
			
		||||
    # which you can then use to compare timings when optimizing your code.
 | 
			
		||||
    #
 | 
			
		||||
    # You may give an optional logger level (<tt>:debug</tt>, <tt>:info</tt>,
 | 
			
		||||
    # <tt>:warn</tt>, <tt>:error</tt>) as the <tt>:level</tt> option. The
 | 
			
		||||
    # default logger level value is <tt>:info</tt>.
 | 
			
		||||
    #
 | 
			
		||||
    #  <% benchmark 'Low-level files', level: :debug do %>
 | 
			
		||||
    #    <%= lowlevel_files_operation %>
 | 
			
		||||
    #  <% end %>
 | 
			
		||||
    #
 | 
			
		||||
    # Finally, you can pass true as the third argument to silence all log
 | 
			
		||||
    # activity (other than the timing information) from inside the block. This
 | 
			
		||||
    # is great for boiling down a noisy block to just a single statement that
 | 
			
		||||
    # produces one log line:
 | 
			
		||||
    #
 | 
			
		||||
    #  <% benchmark 'Process data files', level: :info, silence: true do %>
 | 
			
		||||
    #    <%= expensive_and_chatty_files_operation %>
 | 
			
		||||
    #  <% end %>
 | 
			
		||||
    def benchmark(message = "Benchmarking", options = {})
 | 
			
		||||
      if logger
 | 
			
		||||
        options.assert_valid_keys(:level, :silence)
 | 
			
		||||
        options[:level] ||= :info
 | 
			
		||||
 | 
			
		||||
        result = nil
 | 
			
		||||
        ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
 | 
			
		||||
        logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
 | 
			
		||||
        result
 | 
			
		||||
      else
 | 
			
		||||
        yield
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
  require "builder"
 | 
			
		||||
rescue LoadError => e
 | 
			
		||||
  $stderr.puts "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install"
 | 
			
		||||
  raise e
 | 
			
		||||
end
 | 
			
		||||
@ -1,862 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/concern"
 | 
			
		||||
require "active_support/descendants_tracker"
 | 
			
		||||
require "active_support/core_ext/array/extract_options"
 | 
			
		||||
require "active_support/core_ext/class/attribute"
 | 
			
		||||
require "active_support/core_ext/string/filters"
 | 
			
		||||
require "thread"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Callbacks are code hooks that are run at key points in an object's life cycle.
 | 
			
		||||
  # The typical use case is to have a base class define a set of callbacks
 | 
			
		||||
  # relevant to the other functionality it supplies, so that subclasses can
 | 
			
		||||
  # install callbacks that enhance or modify the base functionality without
 | 
			
		||||
  # needing to override or redefine methods of the base class.
 | 
			
		||||
  #
 | 
			
		||||
  # Mixing in this module allows you to define the events in the object's
 | 
			
		||||
  # life cycle that will support callbacks (via +ClassMethods.define_callbacks+),
 | 
			
		||||
  # set the instance methods, procs, or callback objects to be called (via
 | 
			
		||||
  # +ClassMethods.set_callback+), and run the installed callbacks at the
 | 
			
		||||
  # appropriate times (via +run_callbacks+).
 | 
			
		||||
  #
 | 
			
		||||
  # By default callbacks are halted by throwing +:abort+.
 | 
			
		||||
  # See +ClassMethods.define_callbacks+ for details.
 | 
			
		||||
  #
 | 
			
		||||
  # Three kinds of callbacks are supported: before callbacks, run before a
 | 
			
		||||
  # certain event; after callbacks, run after the event; and around callbacks,
 | 
			
		||||
  # blocks that surround the event, triggering it when they yield. Callback code
 | 
			
		||||
  # can be contained in instance methods, procs or lambdas, or callback objects
 | 
			
		||||
  # that respond to certain predetermined methods. See +ClassMethods.set_callback+
 | 
			
		||||
  # for details.
 | 
			
		||||
  #
 | 
			
		||||
  #   class Record
 | 
			
		||||
  #     include ActiveSupport::Callbacks
 | 
			
		||||
  #     define_callbacks :save
 | 
			
		||||
  #
 | 
			
		||||
  #     def save
 | 
			
		||||
  #       run_callbacks :save do
 | 
			
		||||
  #         puts "- save"
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class PersonRecord < Record
 | 
			
		||||
  #     set_callback :save, :before, :saving_message
 | 
			
		||||
  #     def saving_message
 | 
			
		||||
  #       puts "saving..."
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  #     set_callback :save, :after do |object|
 | 
			
		||||
  #       puts "saved"
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   person = PersonRecord.new
 | 
			
		||||
  #   person.save
 | 
			
		||||
  #
 | 
			
		||||
  # Output:
 | 
			
		||||
  #   saving...
 | 
			
		||||
  #   - save
 | 
			
		||||
  #   saved
 | 
			
		||||
  module Callbacks
 | 
			
		||||
    extend Concern
 | 
			
		||||
 | 
			
		||||
    included do
 | 
			
		||||
      extend ActiveSupport::DescendantsTracker
 | 
			
		||||
      class_attribute :__callbacks, instance_writer: false, default: {}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    CALLBACK_FILTER_TYPES = [:before, :after, :around]
 | 
			
		||||
 | 
			
		||||
    # Runs the callbacks for the given event.
 | 
			
		||||
    #
 | 
			
		||||
    # Calls the before and around callbacks in the order they were set, yields
 | 
			
		||||
    # the block (if given one), and then runs the after callbacks in reverse
 | 
			
		||||
    # order.
 | 
			
		||||
    #
 | 
			
		||||
    # If the callback chain was halted, returns +false+. Otherwise returns the
 | 
			
		||||
    # result of the block, +nil+ if no callbacks have been set, or +true+
 | 
			
		||||
    # if callbacks have been set but no block is given.
 | 
			
		||||
    #
 | 
			
		||||
    #   run_callbacks :save do
 | 
			
		||||
    #     save
 | 
			
		||||
    #   end
 | 
			
		||||
    #
 | 
			
		||||
    #--
 | 
			
		||||
    #
 | 
			
		||||
    # As this method is used in many places, and often wraps large portions of
 | 
			
		||||
    # user code, it has an additional design goal of minimizing its impact on
 | 
			
		||||
    # the visible call stack. An exception from inside a :before or :after
 | 
			
		||||
    # callback can be as noisy as it likes -- but when control has passed
 | 
			
		||||
    # smoothly through and into the supplied block, we want as little evidence
 | 
			
		||||
    # as possible that we were here.
 | 
			
		||||
    def run_callbacks(kind)
 | 
			
		||||
      callbacks = __callbacks[kind.to_sym]
 | 
			
		||||
 | 
			
		||||
      if callbacks.empty?
 | 
			
		||||
        yield if block_given?
 | 
			
		||||
      else
 | 
			
		||||
        env = Filters::Environment.new(self, false, nil)
 | 
			
		||||
        next_sequence = callbacks.compile
 | 
			
		||||
 | 
			
		||||
        # Common case: no 'around' callbacks defined
 | 
			
		||||
        if next_sequence.final?
 | 
			
		||||
          next_sequence.invoke_before(env)
 | 
			
		||||
          env.value = !env.halted && (!block_given? || yield)
 | 
			
		||||
          next_sequence.invoke_after(env)
 | 
			
		||||
          env.value
 | 
			
		||||
        else
 | 
			
		||||
          invoke_sequence = Proc.new do
 | 
			
		||||
            skipped = nil
 | 
			
		||||
 | 
			
		||||
            while true
 | 
			
		||||
              current = next_sequence
 | 
			
		||||
              current.invoke_before(env)
 | 
			
		||||
              if current.final?
 | 
			
		||||
                env.value = !env.halted && (!block_given? || yield)
 | 
			
		||||
              elsif current.skip?(env)
 | 
			
		||||
                (skipped ||= []) << current
 | 
			
		||||
                next_sequence = next_sequence.nested
 | 
			
		||||
                next
 | 
			
		||||
              else
 | 
			
		||||
                next_sequence = next_sequence.nested
 | 
			
		||||
                begin
 | 
			
		||||
                  target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
 | 
			
		||||
                  target.send(method, *arguments, &block)
 | 
			
		||||
                ensure
 | 
			
		||||
                  next_sequence = current
 | 
			
		||||
                end
 | 
			
		||||
              end
 | 
			
		||||
              current.invoke_after(env)
 | 
			
		||||
              skipped.pop.invoke_after(env) while skipped&.first
 | 
			
		||||
              break env.value
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          invoke_sequence.call
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      # A hook invoked every time a before callback is halted.
 | 
			
		||||
      # This can be overridden in ActiveSupport::Callbacks implementors in order
 | 
			
		||||
      # to provide better debugging/logging.
 | 
			
		||||
      def halted_callback_hook(filter, name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      module Conditionals # :nodoc:
 | 
			
		||||
        class Value
 | 
			
		||||
          def initialize(&block)
 | 
			
		||||
            @block = block
 | 
			
		||||
          end
 | 
			
		||||
          def call(target, value); @block.call(value); end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      module Filters
 | 
			
		||||
        Environment = Struct.new(:target, :halted, :value)
 | 
			
		||||
 | 
			
		||||
        class Before
 | 
			
		||||
          def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter, name)
 | 
			
		||||
            halted_lambda = chain_config[:terminator]
 | 
			
		||||
 | 
			
		||||
            if user_conditions.any?
 | 
			
		||||
              halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
 | 
			
		||||
            else
 | 
			
		||||
              halting(callback_sequence, user_callback, halted_lambda, filter, name)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def self.halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
 | 
			
		||||
            callback_sequence.before do |env|
 | 
			
		||||
              target = env.target
 | 
			
		||||
              value  = env.value
 | 
			
		||||
              halted = env.halted
 | 
			
		||||
 | 
			
		||||
              if !halted && user_conditions.all? { |c| c.call(target, value) }
 | 
			
		||||
                result_lambda = -> { user_callback.call target, value }
 | 
			
		||||
                env.halted = halted_lambda.call(target, result_lambda)
 | 
			
		||||
                if env.halted
 | 
			
		||||
                  target.send :halted_callback_hook, filter, name
 | 
			
		||||
                end
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              env
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          private_class_method :halting_and_conditional
 | 
			
		||||
 | 
			
		||||
          def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
 | 
			
		||||
            callback_sequence.before do |env|
 | 
			
		||||
              target = env.target
 | 
			
		||||
              value  = env.value
 | 
			
		||||
              halted = env.halted
 | 
			
		||||
 | 
			
		||||
              unless halted
 | 
			
		||||
                result_lambda = -> { user_callback.call target, value }
 | 
			
		||||
                env.halted = halted_lambda.call(target, result_lambda)
 | 
			
		||||
                if env.halted
 | 
			
		||||
                  target.send :halted_callback_hook, filter, name
 | 
			
		||||
                end
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              env
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          private_class_method :halting
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        class After
 | 
			
		||||
          def self.build(callback_sequence, user_callback, user_conditions, chain_config)
 | 
			
		||||
            if chain_config[:skip_after_callbacks_if_terminated]
 | 
			
		||||
              if user_conditions.any?
 | 
			
		||||
                halting_and_conditional(callback_sequence, user_callback, user_conditions)
 | 
			
		||||
              else
 | 
			
		||||
                halting(callback_sequence, user_callback)
 | 
			
		||||
              end
 | 
			
		||||
            else
 | 
			
		||||
              if user_conditions.any?
 | 
			
		||||
                conditional callback_sequence, user_callback, user_conditions
 | 
			
		||||
              else
 | 
			
		||||
                simple callback_sequence, user_callback
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def self.halting_and_conditional(callback_sequence, user_callback, user_conditions)
 | 
			
		||||
            callback_sequence.after do |env|
 | 
			
		||||
              target = env.target
 | 
			
		||||
              value  = env.value
 | 
			
		||||
              halted = env.halted
 | 
			
		||||
 | 
			
		||||
              if !halted && user_conditions.all? { |c| c.call(target, value) }
 | 
			
		||||
                user_callback.call target, value
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              env
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          private_class_method :halting_and_conditional
 | 
			
		||||
 | 
			
		||||
          def self.halting(callback_sequence, user_callback)
 | 
			
		||||
            callback_sequence.after do |env|
 | 
			
		||||
              unless env.halted
 | 
			
		||||
                user_callback.call env.target, env.value
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              env
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          private_class_method :halting
 | 
			
		||||
 | 
			
		||||
          def self.conditional(callback_sequence, user_callback, user_conditions)
 | 
			
		||||
            callback_sequence.after do |env|
 | 
			
		||||
              target = env.target
 | 
			
		||||
              value  = env.value
 | 
			
		||||
 | 
			
		||||
              if user_conditions.all? { |c| c.call(target, value) }
 | 
			
		||||
                user_callback.call target, value
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              env
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          private_class_method :conditional
 | 
			
		||||
 | 
			
		||||
          def self.simple(callback_sequence, user_callback)
 | 
			
		||||
            callback_sequence.after do |env|
 | 
			
		||||
              user_callback.call env.target, env.value
 | 
			
		||||
 | 
			
		||||
              env
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          private_class_method :simple
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class Callback #:nodoc:#
 | 
			
		||||
        def self.build(chain, filter, kind, options)
 | 
			
		||||
          if filter.is_a?(String)
 | 
			
		||||
            raise ArgumentError, <<-MSG.squish
 | 
			
		||||
              Passing string to define a callback is not supported. See the `.set_callback`
 | 
			
		||||
              documentation to see supported values.
 | 
			
		||||
            MSG
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          new chain.name, filter, kind, options, chain.config
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        attr_accessor :kind, :name
 | 
			
		||||
        attr_reader :chain_config
 | 
			
		||||
 | 
			
		||||
        def initialize(name, filter, kind, options, chain_config)
 | 
			
		||||
          @chain_config = chain_config
 | 
			
		||||
          @name    = name
 | 
			
		||||
          @kind    = kind
 | 
			
		||||
          @filter  = filter
 | 
			
		||||
          @key     = compute_identifier filter
 | 
			
		||||
          @if      = check_conditionals(options[:if])
 | 
			
		||||
          @unless  = check_conditionals(options[:unless])
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def filter; @key; end
 | 
			
		||||
        def raw_filter; @filter; end
 | 
			
		||||
 | 
			
		||||
        def merge_conditional_options(chain, if_option:, unless_option:)
 | 
			
		||||
          options = {
 | 
			
		||||
            if: @if.dup,
 | 
			
		||||
            unless: @unless.dup
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          options[:if].concat     Array(unless_option)
 | 
			
		||||
          options[:unless].concat Array(if_option)
 | 
			
		||||
 | 
			
		||||
          self.class.build chain, @filter, @kind, options
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def matches?(_kind, _filter)
 | 
			
		||||
          @kind == _kind && filter == _filter
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def duplicates?(other)
 | 
			
		||||
          case @filter
 | 
			
		||||
          when Symbol
 | 
			
		||||
            matches?(other.kind, other.filter)
 | 
			
		||||
          else
 | 
			
		||||
            false
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Wraps code with filter
 | 
			
		||||
        def apply(callback_sequence)
 | 
			
		||||
          user_conditions = conditions_lambdas
 | 
			
		||||
          user_callback = CallTemplate.build(@filter, self)
 | 
			
		||||
 | 
			
		||||
          case kind
 | 
			
		||||
          when :before
 | 
			
		||||
            Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter, name)
 | 
			
		||||
          when :after
 | 
			
		||||
            Filters::After.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config)
 | 
			
		||||
          when :around
 | 
			
		||||
            callback_sequence.around(user_callback, user_conditions)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def current_scopes
 | 
			
		||||
          Array(chain_config[:scope]).map { |s| public_send(s) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        private
 | 
			
		||||
          EMPTY_ARRAY = [].freeze
 | 
			
		||||
          private_constant :EMPTY_ARRAY
 | 
			
		||||
 | 
			
		||||
          def check_conditionals(conditionals)
 | 
			
		||||
            return EMPTY_ARRAY if conditionals.blank?
 | 
			
		||||
 | 
			
		||||
            conditionals = Array(conditionals)
 | 
			
		||||
            if conditionals.any? { |c| c.is_a?(String) }
 | 
			
		||||
              raise ArgumentError, <<-MSG.squish
 | 
			
		||||
                Passing string to be evaluated in :if and :unless conditional
 | 
			
		||||
                options is not supported. Pass a symbol for an instance method,
 | 
			
		||||
                or a lambda, proc or block, instead.
 | 
			
		||||
              MSG
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            conditionals.freeze
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def compute_identifier(filter)
 | 
			
		||||
            case filter
 | 
			
		||||
            when ::Proc
 | 
			
		||||
              filter.object_id
 | 
			
		||||
            else
 | 
			
		||||
              filter
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def conditions_lambdas
 | 
			
		||||
            @if.map { |c| CallTemplate.build(c, self).make_lambda } +
 | 
			
		||||
              @unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
 | 
			
		||||
          end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # A future invocation of user-supplied code (either as a callback,
 | 
			
		||||
      # or a condition filter).
 | 
			
		||||
      class CallTemplate # :nodoc:
 | 
			
		||||
        def initialize(target, method, arguments, block)
 | 
			
		||||
          @override_target = target
 | 
			
		||||
          @method_name = method
 | 
			
		||||
          @arguments = arguments
 | 
			
		||||
          @override_block = block
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Return the parts needed to make this call, with the given
 | 
			
		||||
        # input values.
 | 
			
		||||
        #
 | 
			
		||||
        # Returns an array of the form:
 | 
			
		||||
        #
 | 
			
		||||
        #   [target, block, method, *arguments]
 | 
			
		||||
        #
 | 
			
		||||
        # This array can be used as such:
 | 
			
		||||
        #
 | 
			
		||||
        #   target.send(method, *arguments, &block)
 | 
			
		||||
        #
 | 
			
		||||
        # The actual invocation is left up to the caller to minimize
 | 
			
		||||
        # call stack pollution.
 | 
			
		||||
        def expand(target, value, block)
 | 
			
		||||
          expanded = [@override_target || target, @override_block || block, @method_name]
 | 
			
		||||
 | 
			
		||||
          @arguments.each do |arg|
 | 
			
		||||
            case arg
 | 
			
		||||
            when :value then expanded << value
 | 
			
		||||
            when :target then expanded << target
 | 
			
		||||
            when :block then expanded << (block || raise(ArgumentError))
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          expanded
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Return a lambda that will make this call when given the input
 | 
			
		||||
        # values.
 | 
			
		||||
        def make_lambda
 | 
			
		||||
          lambda do |target, value, &block|
 | 
			
		||||
            target, block, method, *arguments = expand(target, value, block)
 | 
			
		||||
            target.send(method, *arguments, &block)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Return a lambda that will make this call when given the input
 | 
			
		||||
        # values, but then return the boolean inverse of that result.
 | 
			
		||||
        def inverted_lambda
 | 
			
		||||
          lambda do |target, value, &block|
 | 
			
		||||
            target, block, method, *arguments = expand(target, value, block)
 | 
			
		||||
            ! target.send(method, *arguments, &block)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Filters support:
 | 
			
		||||
        #
 | 
			
		||||
        #   Symbols:: A method to call.
 | 
			
		||||
        #   Procs::   A proc to call with the object.
 | 
			
		||||
        #   Objects:: An object with a <tt>before_foo</tt> method on it to call.
 | 
			
		||||
        #
 | 
			
		||||
        # All of these objects are converted into a CallTemplate and handled
 | 
			
		||||
        # the same after this point.
 | 
			
		||||
        def self.build(filter, callback)
 | 
			
		||||
          case filter
 | 
			
		||||
          when Symbol
 | 
			
		||||
            new(nil, filter, [], nil)
 | 
			
		||||
          when Conditionals::Value
 | 
			
		||||
            new(filter, :call, [:target, :value], nil)
 | 
			
		||||
          when ::Proc
 | 
			
		||||
            if filter.arity > 1
 | 
			
		||||
              new(nil, :instance_exec, [:target, :block], filter)
 | 
			
		||||
            elsif filter.arity > 0
 | 
			
		||||
              new(nil, :instance_exec, [:target], filter)
 | 
			
		||||
            else
 | 
			
		||||
              new(nil, :instance_exec, [], filter)
 | 
			
		||||
            end
 | 
			
		||||
          else
 | 
			
		||||
            method_to_call = callback.current_scopes.join("_")
 | 
			
		||||
 | 
			
		||||
            new(filter, method_to_call, [:target], nil)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Execute before and after filters in a sequence instead of
 | 
			
		||||
      # chaining them with nested lambda calls, see:
 | 
			
		||||
      # https://github.com/rails/rails/issues/18011
 | 
			
		||||
      class CallbackSequence # :nodoc:
 | 
			
		||||
        def initialize(nested = nil, call_template = nil, user_conditions = nil)
 | 
			
		||||
          @nested = nested
 | 
			
		||||
          @call_template = call_template
 | 
			
		||||
          @user_conditions = user_conditions
 | 
			
		||||
 | 
			
		||||
          @before = []
 | 
			
		||||
          @after = []
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def before(&before)
 | 
			
		||||
          @before.unshift(before)
 | 
			
		||||
          self
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def after(&after)
 | 
			
		||||
          @after.push(after)
 | 
			
		||||
          self
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def around(call_template, user_conditions)
 | 
			
		||||
          CallbackSequence.new(self, call_template, user_conditions)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def skip?(arg)
 | 
			
		||||
          arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        attr_reader :nested
 | 
			
		||||
 | 
			
		||||
        def final?
 | 
			
		||||
          !@call_template
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def expand_call_template(arg, block)
 | 
			
		||||
          @call_template.expand(arg.target, arg.value, block)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def invoke_before(arg)
 | 
			
		||||
          @before.each { |b| b.call(arg) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def invoke_after(arg)
 | 
			
		||||
          @after.each { |a| a.call(arg) }
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class CallbackChain #:nodoc:#
 | 
			
		||||
        include Enumerable
 | 
			
		||||
 | 
			
		||||
        attr_reader :name, :config
 | 
			
		||||
 | 
			
		||||
        def initialize(name, config)
 | 
			
		||||
          @name = name
 | 
			
		||||
          @config = {
 | 
			
		||||
            scope: [:kind],
 | 
			
		||||
            terminator: default_terminator
 | 
			
		||||
          }.merge!(config)
 | 
			
		||||
          @chain = []
 | 
			
		||||
          @callbacks = nil
 | 
			
		||||
          @mutex = Mutex.new
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def each(&block); @chain.each(&block); end
 | 
			
		||||
        def index(o);     @chain.index(o); end
 | 
			
		||||
        def empty?;       @chain.empty?; end
 | 
			
		||||
 | 
			
		||||
        def insert(index, o)
 | 
			
		||||
          @callbacks = nil
 | 
			
		||||
          @chain.insert(index, o)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def delete(o)
 | 
			
		||||
          @callbacks = nil
 | 
			
		||||
          @chain.delete(o)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def clear
 | 
			
		||||
          @callbacks = nil
 | 
			
		||||
          @chain.clear
 | 
			
		||||
          self
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def initialize_copy(other)
 | 
			
		||||
          @callbacks = nil
 | 
			
		||||
          @chain     = other.chain.dup
 | 
			
		||||
          @mutex     = Mutex.new
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def compile
 | 
			
		||||
          @callbacks || @mutex.synchronize do
 | 
			
		||||
            final_sequence = CallbackSequence.new
 | 
			
		||||
            @callbacks ||= @chain.reverse.inject(final_sequence) do |callback_sequence, callback|
 | 
			
		||||
              callback.apply callback_sequence
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def append(*callbacks)
 | 
			
		||||
          callbacks.each { |c| append_one(c) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def prepend(*callbacks)
 | 
			
		||||
          callbacks.each { |c| prepend_one(c) }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        protected
 | 
			
		||||
          attr_reader :chain
 | 
			
		||||
 | 
			
		||||
        private
 | 
			
		||||
          def append_one(callback)
 | 
			
		||||
            @callbacks = nil
 | 
			
		||||
            remove_duplicates(callback)
 | 
			
		||||
            @chain.push(callback)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def prepend_one(callback)
 | 
			
		||||
            @callbacks = nil
 | 
			
		||||
            remove_duplicates(callback)
 | 
			
		||||
            @chain.unshift(callback)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def remove_duplicates(callback)
 | 
			
		||||
            @callbacks = nil
 | 
			
		||||
            @chain.delete_if { |c| callback.duplicates?(c) }
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def default_terminator
 | 
			
		||||
            Proc.new do |target, result_lambda|
 | 
			
		||||
              terminate = true
 | 
			
		||||
              catch(:abort) do
 | 
			
		||||
                result_lambda.call
 | 
			
		||||
                terminate = false
 | 
			
		||||
              end
 | 
			
		||||
              terminate
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      module ClassMethods
 | 
			
		||||
        def normalize_callback_params(filters, block) # :nodoc:
 | 
			
		||||
          type = CALLBACK_FILTER_TYPES.include?(filters.first) ? filters.shift : :before
 | 
			
		||||
          options = filters.extract_options!
 | 
			
		||||
          filters.unshift(block) if block
 | 
			
		||||
          [type, filters, options.dup]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # This is used internally to append, prepend and skip callbacks to the
 | 
			
		||||
        # CallbackChain.
 | 
			
		||||
        def __update_callbacks(name) #:nodoc:
 | 
			
		||||
          ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse_each do |target|
 | 
			
		||||
            chain = target.get_callbacks name
 | 
			
		||||
            yield target, chain.dup
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Install a callback for the given event.
 | 
			
		||||
        #
 | 
			
		||||
        #   set_callback :save, :before, :before_method
 | 
			
		||||
        #   set_callback :save, :after,  :after_method, if: :condition
 | 
			
		||||
        #   set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
 | 
			
		||||
        #
 | 
			
		||||
        # The second argument indicates whether the callback is to be run +:before+,
 | 
			
		||||
        # +:after+, or +:around+ the event. If omitted, +:before+ is assumed. This
 | 
			
		||||
        # means the first example above can also be written as:
 | 
			
		||||
        #
 | 
			
		||||
        #   set_callback :save, :before_method
 | 
			
		||||
        #
 | 
			
		||||
        # The callback can be specified as a symbol naming an instance method; as a
 | 
			
		||||
        # proc, lambda, or block; or as an object that responds to a certain method
 | 
			
		||||
        # determined by the <tt>:scope</tt> argument to +define_callbacks+.
 | 
			
		||||
        #
 | 
			
		||||
        # If a proc, lambda, or block is given, its body is evaluated in the context
 | 
			
		||||
        # of the current object. It can also optionally accept the current object as
 | 
			
		||||
        # an argument.
 | 
			
		||||
        #
 | 
			
		||||
        # Before and around callbacks are called in the order that they are set;
 | 
			
		||||
        # after callbacks are called in the reverse order.
 | 
			
		||||
        #
 | 
			
		||||
        # Around callbacks can access the return value from the event, if it
 | 
			
		||||
        # wasn't halted, from the +yield+ call.
 | 
			
		||||
        #
 | 
			
		||||
        # ===== Options
 | 
			
		||||
        #
 | 
			
		||||
        # * <tt>:if</tt> - A symbol or an array of symbols, each naming an instance
 | 
			
		||||
        #   method or a proc; the callback will be called only when they all return
 | 
			
		||||
        #   a true value.
 | 
			
		||||
        #
 | 
			
		||||
        #   If a proc is given, its body is evaluated in the context of the
 | 
			
		||||
        #   current object. It can also optionally accept the current object as
 | 
			
		||||
        #   an argument.
 | 
			
		||||
        # * <tt>:unless</tt> - A symbol or an array of symbols, each naming an
 | 
			
		||||
        #   instance method or a proc; the callback will be called only when they
 | 
			
		||||
        #   all return a false value.
 | 
			
		||||
        #
 | 
			
		||||
        #   If a proc is given, its body is evaluated in the context of the
 | 
			
		||||
        #   current object. It can also optionally accept the current object as
 | 
			
		||||
        #   an argument.
 | 
			
		||||
        # * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
 | 
			
		||||
        #   existing chain rather than appended.
 | 
			
		||||
        def set_callback(name, *filter_list, &block)
 | 
			
		||||
          type, filters, options = normalize_callback_params(filter_list, block)
 | 
			
		||||
 | 
			
		||||
          self_chain = get_callbacks name
 | 
			
		||||
          mapped = filters.map do |filter|
 | 
			
		||||
            Callback.build(self_chain, filter, type, options)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          __update_callbacks(name) do |target, chain|
 | 
			
		||||
            options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped)
 | 
			
		||||
            target.set_callbacks name, chain
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Skip a previously set callback. Like +set_callback+, <tt>:if</tt> or
 | 
			
		||||
        # <tt>:unless</tt> options may be passed in order to control when the
 | 
			
		||||
        # callback is skipped.
 | 
			
		||||
        #
 | 
			
		||||
        #   class Writer < Person
 | 
			
		||||
        #      skip_callback :validate, :before, :check_membership, if: -> { age > 18 }
 | 
			
		||||
        #   end
 | 
			
		||||
        #
 | 
			
		||||
        # An <tt>ArgumentError</tt> will be raised if the callback has not
 | 
			
		||||
        # already been set (unless the <tt>:raise</tt> option is set to <tt>false</tt>).
 | 
			
		||||
        def skip_callback(name, *filter_list, &block)
 | 
			
		||||
          type, filters, options = normalize_callback_params(filter_list, block)
 | 
			
		||||
 | 
			
		||||
          options[:raise] = true unless options.key?(:raise)
 | 
			
		||||
 | 
			
		||||
          __update_callbacks(name) do |target, chain|
 | 
			
		||||
            filters.each do |filter|
 | 
			
		||||
              callback = chain.find { |c| c.matches?(type, filter) }
 | 
			
		||||
 | 
			
		||||
              if !callback && options[:raise]
 | 
			
		||||
                raise ArgumentError, "#{type.to_s.capitalize} #{name} callback #{filter.inspect} has not been defined"
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              if callback && (options.key?(:if) || options.key?(:unless))
 | 
			
		||||
                new_callback = callback.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless])
 | 
			
		||||
                chain.insert(chain.index(callback), new_callback)
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              chain.delete(callback)
 | 
			
		||||
            end
 | 
			
		||||
            target.set_callbacks name, chain
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Remove all set callbacks for the given event.
 | 
			
		||||
        def reset_callbacks(name)
 | 
			
		||||
          callbacks = get_callbacks name
 | 
			
		||||
 | 
			
		||||
          ActiveSupport::DescendantsTracker.descendants(self).each do |target|
 | 
			
		||||
            chain = target.get_callbacks(name).dup
 | 
			
		||||
            callbacks.each { |c| chain.delete(c) }
 | 
			
		||||
            target.set_callbacks name, chain
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          set_callbacks(name, callbacks.dup.clear)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Define sets of events in the object life cycle that support callbacks.
 | 
			
		||||
        #
 | 
			
		||||
        #   define_callbacks :validate
 | 
			
		||||
        #   define_callbacks :initialize, :save, :destroy
 | 
			
		||||
        #
 | 
			
		||||
        # ===== Options
 | 
			
		||||
        #
 | 
			
		||||
        # * <tt>:terminator</tt> - Determines when a before filter will halt the
 | 
			
		||||
        #   callback chain, preventing following before and around callbacks from
 | 
			
		||||
        #   being called and the event from being triggered.
 | 
			
		||||
        #   This should be a lambda to be executed.
 | 
			
		||||
        #   The current object and the result lambda of the callback will be provided
 | 
			
		||||
        #   to the terminator lambda.
 | 
			
		||||
        #
 | 
			
		||||
        #     define_callbacks :validate, terminator: ->(target, result_lambda) { result_lambda.call == false }
 | 
			
		||||
        #
 | 
			
		||||
        #   In this example, if any before validate callbacks returns +false+,
 | 
			
		||||
        #   any successive before and around callback is not executed.
 | 
			
		||||
        #
 | 
			
		||||
        #   The default terminator halts the chain when a callback throws +:abort+.
 | 
			
		||||
        #
 | 
			
		||||
        # * <tt>:skip_after_callbacks_if_terminated</tt> - Determines if after
 | 
			
		||||
        #   callbacks should be terminated by the <tt>:terminator</tt> option. By
 | 
			
		||||
        #   default after callbacks are executed no matter if callback chain was
 | 
			
		||||
        #   terminated or not. This option has no effect if <tt>:terminator</tt>
 | 
			
		||||
        #   option is set to +nil+.
 | 
			
		||||
        #
 | 
			
		||||
        # * <tt>:scope</tt> - Indicates which methods should be executed when an
 | 
			
		||||
        #   object is used as a callback.
 | 
			
		||||
        #
 | 
			
		||||
        #     class Audit
 | 
			
		||||
        #       def before(caller)
 | 
			
		||||
        #         puts 'Audit: before is called'
 | 
			
		||||
        #       end
 | 
			
		||||
        #
 | 
			
		||||
        #       def before_save(caller)
 | 
			
		||||
        #         puts 'Audit: before_save is called'
 | 
			
		||||
        #       end
 | 
			
		||||
        #     end
 | 
			
		||||
        #
 | 
			
		||||
        #     class Account
 | 
			
		||||
        #       include ActiveSupport::Callbacks
 | 
			
		||||
        #
 | 
			
		||||
        #       define_callbacks :save
 | 
			
		||||
        #       set_callback :save, :before, Audit.new
 | 
			
		||||
        #
 | 
			
		||||
        #       def save
 | 
			
		||||
        #         run_callbacks :save do
 | 
			
		||||
        #           puts 'save in main'
 | 
			
		||||
        #         end
 | 
			
		||||
        #       end
 | 
			
		||||
        #     end
 | 
			
		||||
        #
 | 
			
		||||
        #   In the above case whenever you save an account the method
 | 
			
		||||
        #   <tt>Audit#before</tt> will be called. On the other hand
 | 
			
		||||
        #
 | 
			
		||||
        #     define_callbacks :save, scope: [:kind, :name]
 | 
			
		||||
        #
 | 
			
		||||
        #   would trigger <tt>Audit#before_save</tt> instead. That's constructed
 | 
			
		||||
        #   by calling <tt>#{kind}_#{name}</tt> on the given instance. In this
 | 
			
		||||
        #   case "kind" is "before" and "name" is "save". In this context +:kind+
 | 
			
		||||
        #   and +:name+ have special meanings: +:kind+ refers to the kind of
 | 
			
		||||
        #   callback (before/after/around) and +:name+ refers to the method on
 | 
			
		||||
        #   which callbacks are being defined.
 | 
			
		||||
        #
 | 
			
		||||
        #   A declaration like
 | 
			
		||||
        #
 | 
			
		||||
        #     define_callbacks :save, scope: [:name]
 | 
			
		||||
        #
 | 
			
		||||
        #   would call <tt>Audit#save</tt>.
 | 
			
		||||
        #
 | 
			
		||||
        # ===== Notes
 | 
			
		||||
        #
 | 
			
		||||
        # +names+ passed to +define_callbacks+ must not end with
 | 
			
		||||
        # <tt>!</tt>, <tt>?</tt> or <tt>=</tt>.
 | 
			
		||||
        #
 | 
			
		||||
        # Calling +define_callbacks+ multiple times with the same +names+ will
 | 
			
		||||
        # overwrite previous callbacks registered with +set_callback+.
 | 
			
		||||
        def define_callbacks(*names)
 | 
			
		||||
          options = names.extract_options!
 | 
			
		||||
 | 
			
		||||
          names.each do |name|
 | 
			
		||||
            name = name.to_sym
 | 
			
		||||
 | 
			
		||||
            ([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target|
 | 
			
		||||
              target.set_callbacks name, CallbackChain.new(name, options)
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            module_eval <<-RUBY, __FILE__, __LINE__ + 1
 | 
			
		||||
              def _run_#{name}_callbacks(&block)
 | 
			
		||||
                run_callbacks #{name.inspect}, &block
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              def self._#{name}_callbacks
 | 
			
		||||
                get_callbacks(#{name.inspect})
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              def self._#{name}_callbacks=(value)
 | 
			
		||||
                set_callbacks(#{name.inspect}, value)
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              def _#{name}_callbacks
 | 
			
		||||
                __callbacks[#{name.inspect}]
 | 
			
		||||
              end
 | 
			
		||||
            RUBY
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        protected
 | 
			
		||||
          def get_callbacks(name) # :nodoc:
 | 
			
		||||
            __callbacks[name.to_sym]
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if Module.instance_method(:method_defined?).arity == 1 # Ruby 2.5 and older
 | 
			
		||||
            def set_callbacks(name, callbacks) # :nodoc:
 | 
			
		||||
              self.__callbacks = __callbacks.merge(name.to_sym => callbacks)
 | 
			
		||||
            end
 | 
			
		||||
          else # Ruby 2.6 and newer
 | 
			
		||||
            def set_callbacks(name, callbacks) # :nodoc:
 | 
			
		||||
              unless singleton_class.method_defined?(:__callbacks, false)
 | 
			
		||||
                self.__callbacks = __callbacks.dup
 | 
			
		||||
              end
 | 
			
		||||
              self.__callbacks[name.to_sym] = callbacks
 | 
			
		||||
              self.__callbacks
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,215 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # A typical module looks like this:
 | 
			
		||||
  #
 | 
			
		||||
  #   module M
 | 
			
		||||
  #     def self.included(base)
 | 
			
		||||
  #       base.extend ClassMethods
 | 
			
		||||
  #       base.class_eval do
 | 
			
		||||
  #         scope :disabled, -> { where(disabled: true) }
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  #     module ClassMethods
 | 
			
		||||
  #       ...
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # By using <tt>ActiveSupport::Concern</tt> the above module could instead be
 | 
			
		||||
  # written as:
 | 
			
		||||
  #
 | 
			
		||||
  #   require "active_support/concern"
 | 
			
		||||
  #
 | 
			
		||||
  #   module M
 | 
			
		||||
  #     extend ActiveSupport::Concern
 | 
			
		||||
  #
 | 
			
		||||
  #     included do
 | 
			
		||||
  #       scope :disabled, -> { where(disabled: true) }
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  #     class_methods do
 | 
			
		||||
  #       ...
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # Moreover, it gracefully handles module dependencies. Given a +Foo+ module
 | 
			
		||||
  # and a +Bar+ module which depends on the former, we would typically write the
 | 
			
		||||
  # following:
 | 
			
		||||
  #
 | 
			
		||||
  #   module Foo
 | 
			
		||||
  #     def self.included(base)
 | 
			
		||||
  #       base.class_eval do
 | 
			
		||||
  #         def self.method_injected_by_foo
 | 
			
		||||
  #           ...
 | 
			
		||||
  #         end
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   module Bar
 | 
			
		||||
  #     def self.included(base)
 | 
			
		||||
  #       base.method_injected_by_foo
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class Host
 | 
			
		||||
  #     include Foo # We need to include this dependency for Bar
 | 
			
		||||
  #     include Bar # Bar is the module that Host really needs
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
 | 
			
		||||
  # could try to hide these from +Host+ directly including +Foo+ in +Bar+:
 | 
			
		||||
  #
 | 
			
		||||
  #   module Bar
 | 
			
		||||
  #     include Foo
 | 
			
		||||
  #     def self.included(base)
 | 
			
		||||
  #       base.method_injected_by_foo
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class Host
 | 
			
		||||
  #     include Bar
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
 | 
			
		||||
  # is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
 | 
			
		||||
  # module dependencies are properly resolved:
 | 
			
		||||
  #
 | 
			
		||||
  #   require "active_support/concern"
 | 
			
		||||
  #
 | 
			
		||||
  #   module Foo
 | 
			
		||||
  #     extend ActiveSupport::Concern
 | 
			
		||||
  #     included do
 | 
			
		||||
  #       def self.method_injected_by_foo
 | 
			
		||||
  #         ...
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   module Bar
 | 
			
		||||
  #     extend ActiveSupport::Concern
 | 
			
		||||
  #     include Foo
 | 
			
		||||
  #
 | 
			
		||||
  #     included do
 | 
			
		||||
  #       self.method_injected_by_foo
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class Host
 | 
			
		||||
  #     include Bar # It works, now Bar takes care of its dependencies
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # === Prepending concerns
 | 
			
		||||
  #
 | 
			
		||||
  # Just like <tt>include</tt>, concerns also support <tt>prepend</tt> with a corresponding
 | 
			
		||||
  # <tt>prepended do</tt> callback. <tt>module ClassMethods</tt> or <tt>class_methods do</tt> are
 | 
			
		||||
  # prepended as well.
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>prepend</tt> is also used for any dependencies.
 | 
			
		||||
  module Concern
 | 
			
		||||
    class MultipleIncludedBlocks < StandardError #:nodoc:
 | 
			
		||||
      def initialize
 | 
			
		||||
        super "Cannot define multiple 'included' blocks for a Concern"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class MultiplePrependBlocks < StandardError #:nodoc:
 | 
			
		||||
      def initialize
 | 
			
		||||
        super "Cannot define multiple 'prepended' blocks for a Concern"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.extended(base) #:nodoc:
 | 
			
		||||
      base.instance_variable_set(:@_dependencies, [])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def append_features(base) #:nodoc:
 | 
			
		||||
      if base.instance_variable_defined?(:@_dependencies)
 | 
			
		||||
        base.instance_variable_get(:@_dependencies) << self
 | 
			
		||||
        false
 | 
			
		||||
      else
 | 
			
		||||
        return false if base < self
 | 
			
		||||
        @_dependencies.each { |dep| base.include(dep) }
 | 
			
		||||
        super
 | 
			
		||||
        base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
 | 
			
		||||
        base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def prepend_features(base) #:nodoc:
 | 
			
		||||
      if base.instance_variable_defined?(:@_dependencies)
 | 
			
		||||
        base.instance_variable_get(:@_dependencies).unshift self
 | 
			
		||||
        false
 | 
			
		||||
      else
 | 
			
		||||
        return false if base < self
 | 
			
		||||
        @_dependencies.each { |dep| base.prepend(dep) }
 | 
			
		||||
        super
 | 
			
		||||
        base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
 | 
			
		||||
        base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Evaluate given block in context of base class,
 | 
			
		||||
    # so that you can write class macros here.
 | 
			
		||||
    # When you define more than one +included+ block, it raises an exception.
 | 
			
		||||
    def included(base = nil, &block)
 | 
			
		||||
      if base.nil?
 | 
			
		||||
        if instance_variable_defined?(:@_included_block)
 | 
			
		||||
          if @_included_block.source_location != block.source_location
 | 
			
		||||
            raise MultipleIncludedBlocks
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          @_included_block = block
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Evaluate given block in context of base class,
 | 
			
		||||
    # so that you can write class macros here.
 | 
			
		||||
    # When you define more than one +prepended+ block, it raises an exception.
 | 
			
		||||
    def prepended(base = nil, &block)
 | 
			
		||||
      if base.nil?
 | 
			
		||||
        if instance_variable_defined?(:@_prepended_block)
 | 
			
		||||
          if @_prepended_block.source_location != block.source_location
 | 
			
		||||
            raise MultiplePrependBlocks
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          @_prepended_block = block
 | 
			
		||||
        end
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Define class methods from given block.
 | 
			
		||||
    # You can define private class methods as well.
 | 
			
		||||
    #
 | 
			
		||||
    #   module Example
 | 
			
		||||
    #     extend ActiveSupport::Concern
 | 
			
		||||
    #
 | 
			
		||||
    #     class_methods do
 | 
			
		||||
    #       def foo; puts 'foo'; end
 | 
			
		||||
    #
 | 
			
		||||
    #       private
 | 
			
		||||
    #         def bar; puts 'bar'; end
 | 
			
		||||
    #     end
 | 
			
		||||
    #   end
 | 
			
		||||
    #
 | 
			
		||||
    #   class Buzz
 | 
			
		||||
    #     include Example
 | 
			
		||||
    #   end
 | 
			
		||||
    #
 | 
			
		||||
    #   Buzz.foo # => "foo"
 | 
			
		||||
    #   Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
 | 
			
		||||
    def class_methods(&class_methods_module_definition)
 | 
			
		||||
      mod = const_defined?(:ClassMethods, false) ?
 | 
			
		||||
        const_get(:ClassMethods) :
 | 
			
		||||
        const_set(:ClassMethods, Module.new)
 | 
			
		||||
 | 
			
		||||
      mod.module_eval(&class_methods_module_definition)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,146 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/concern"
 | 
			
		||||
require "active_support/ordered_options"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Configurable provides a <tt>config</tt> method to store and retrieve
 | 
			
		||||
  # configuration options as an <tt>OrderedOptions</tt>.
 | 
			
		||||
  module Configurable
 | 
			
		||||
    extend ActiveSupport::Concern
 | 
			
		||||
 | 
			
		||||
    class Configuration < ActiveSupport::InheritableOptions
 | 
			
		||||
      def compile_methods!
 | 
			
		||||
        self.class.compile_methods!(keys)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Compiles reader methods so we don't have to go through method_missing.
 | 
			
		||||
      def self.compile_methods!(keys)
 | 
			
		||||
        keys.reject { |m| method_defined?(m) }.each do |key|
 | 
			
		||||
          class_eval <<-RUBY, __FILE__, __LINE__ + 1
 | 
			
		||||
            def #{key}; _get(#{key.inspect}); end
 | 
			
		||||
          RUBY
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module ClassMethods
 | 
			
		||||
      def config
 | 
			
		||||
        @_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
 | 
			
		||||
          superclass.config.inheritable_copy
 | 
			
		||||
        else
 | 
			
		||||
          # create a new "anonymous" class that will host the compiled reader methods
 | 
			
		||||
          Class.new(Configuration).new
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def configure
 | 
			
		||||
        yield config
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Allows you to add shortcut so that you don't have to refer to attribute
 | 
			
		||||
      # through config. Also look at the example for config to contrast.
 | 
			
		||||
      #
 | 
			
		||||
      # Defines both class and instance config accessors.
 | 
			
		||||
      #
 | 
			
		||||
      #   class User
 | 
			
		||||
      #     include ActiveSupport::Configurable
 | 
			
		||||
      #     config_accessor :allowed_access
 | 
			
		||||
      #   end
 | 
			
		||||
      #
 | 
			
		||||
      #   User.allowed_access # => nil
 | 
			
		||||
      #   User.allowed_access = false
 | 
			
		||||
      #   User.allowed_access # => false
 | 
			
		||||
      #
 | 
			
		||||
      #   user = User.new
 | 
			
		||||
      #   user.allowed_access # => false
 | 
			
		||||
      #   user.allowed_access = true
 | 
			
		||||
      #   user.allowed_access # => true
 | 
			
		||||
      #
 | 
			
		||||
      #   User.allowed_access # => false
 | 
			
		||||
      #
 | 
			
		||||
      # The attribute name must be a valid method name in Ruby.
 | 
			
		||||
      #
 | 
			
		||||
      #   class User
 | 
			
		||||
      #     include ActiveSupport::Configurable
 | 
			
		||||
      #     config_accessor :"1_Badname"
 | 
			
		||||
      #   end
 | 
			
		||||
      #   # => NameError: invalid config attribute name
 | 
			
		||||
      #
 | 
			
		||||
      # To omit the instance writer method, pass <tt>instance_writer: false</tt>.
 | 
			
		||||
      # To omit the instance reader method, pass <tt>instance_reader: false</tt>.
 | 
			
		||||
      #
 | 
			
		||||
      #   class User
 | 
			
		||||
      #     include ActiveSupport::Configurable
 | 
			
		||||
      #     config_accessor :allowed_access, instance_reader: false, instance_writer: false
 | 
			
		||||
      #   end
 | 
			
		||||
      #
 | 
			
		||||
      #   User.allowed_access = false
 | 
			
		||||
      #   User.allowed_access # => false
 | 
			
		||||
      #
 | 
			
		||||
      #   User.new.allowed_access = true # => NoMethodError
 | 
			
		||||
      #   User.new.allowed_access        # => NoMethodError
 | 
			
		||||
      #
 | 
			
		||||
      # Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
 | 
			
		||||
      #
 | 
			
		||||
      #   class User
 | 
			
		||||
      #     include ActiveSupport::Configurable
 | 
			
		||||
      #     config_accessor :allowed_access, instance_accessor: false
 | 
			
		||||
      #   end
 | 
			
		||||
      #
 | 
			
		||||
      #   User.allowed_access = false
 | 
			
		||||
      #   User.allowed_access # => false
 | 
			
		||||
      #
 | 
			
		||||
      #   User.new.allowed_access = true # => NoMethodError
 | 
			
		||||
      #   User.new.allowed_access        # => NoMethodError
 | 
			
		||||
      #
 | 
			
		||||
      # Also you can pass a block to set up the attribute with a default value.
 | 
			
		||||
      #
 | 
			
		||||
      #   class User
 | 
			
		||||
      #     include ActiveSupport::Configurable
 | 
			
		||||
      #     config_accessor :hair_colors do
 | 
			
		||||
      #       [:brown, :black, :blonde, :red]
 | 
			
		||||
      #     end
 | 
			
		||||
      #   end
 | 
			
		||||
      #
 | 
			
		||||
      #   User.hair_colors # => [:brown, :black, :blonde, :red]
 | 
			
		||||
      def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
 | 
			
		||||
        names.each do |name|
 | 
			
		||||
          raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
 | 
			
		||||
 | 
			
		||||
          reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
 | 
			
		||||
          writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
 | 
			
		||||
 | 
			
		||||
          singleton_class.class_eval reader, __FILE__, reader_line
 | 
			
		||||
          singleton_class.class_eval writer, __FILE__, writer_line
 | 
			
		||||
 | 
			
		||||
          if instance_accessor
 | 
			
		||||
            class_eval reader, __FILE__, reader_line if instance_reader
 | 
			
		||||
            class_eval writer, __FILE__, writer_line if instance_writer
 | 
			
		||||
          end
 | 
			
		||||
          send("#{name}=", yield) if block_given?
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      private :config_accessor
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
 | 
			
		||||
    #
 | 
			
		||||
    #   require "active_support/configurable"
 | 
			
		||||
    #
 | 
			
		||||
    #   class User
 | 
			
		||||
    #     include ActiveSupport::Configurable
 | 
			
		||||
    #   end
 | 
			
		||||
    #
 | 
			
		||||
    #   user = User.new
 | 
			
		||||
    #
 | 
			
		||||
    #   user.config.allowed_access = true
 | 
			
		||||
    #   user.config.level = 1
 | 
			
		||||
    #
 | 
			
		||||
    #   user.config.allowed_access # => true
 | 
			
		||||
    #   user.config.level          # => 1
 | 
			
		||||
    def config
 | 
			
		||||
      @_config ||= self.class.config.inheritable_copy
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,51 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Reads a YAML configuration file, evaluating any ERB, then
 | 
			
		||||
  # parsing the resulting YAML.
 | 
			
		||||
  #
 | 
			
		||||
  # Warns in case of YAML confusing characters, like invisible
 | 
			
		||||
  # non-breaking spaces.
 | 
			
		||||
  class ConfigurationFile # :nodoc:
 | 
			
		||||
    class FormatError < StandardError; end
 | 
			
		||||
 | 
			
		||||
    def initialize(content_path)
 | 
			
		||||
      @content_path = content_path.to_s
 | 
			
		||||
      @content = read content_path
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def self.parse(content_path, **options)
 | 
			
		||||
      new(content_path).parse(**options)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def parse(context: nil, **options)
 | 
			
		||||
      source = render(context)
 | 
			
		||||
      if YAML.respond_to?(:unsafe_load)
 | 
			
		||||
        YAML.unsafe_load(source, **options) || {}
 | 
			
		||||
      else
 | 
			
		||||
        YAML.load(source, **options) || {}
 | 
			
		||||
      end
 | 
			
		||||
    rescue Psych::SyntaxError => error
 | 
			
		||||
      raise "YAML syntax error occurred while parsing #{@content_path}. " \
 | 
			
		||||
            "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
 | 
			
		||||
            "Error: #{error.message}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def read(content_path)
 | 
			
		||||
        require "yaml"
 | 
			
		||||
        require "erb"
 | 
			
		||||
 | 
			
		||||
        File.read(content_path).tap do |content|
 | 
			
		||||
          if content.include?("\u00A0")
 | 
			
		||||
            warn "File contains invisible non-breaking spaces, you may want to remove those"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def render(context)
 | 
			
		||||
        erb = ERB.new(@content).tap { |e| e.filename = @content_path }
 | 
			
		||||
        context ? erb.result(context) : erb.result
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).sort.each do |path|
 | 
			
		||||
  require path
 | 
			
		||||
end
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/array/wrap"
 | 
			
		||||
require "active_support/core_ext/array/access"
 | 
			
		||||
require "active_support/core_ext/array/conversions"
 | 
			
		||||
require "active_support/core_ext/array/extract"
 | 
			
		||||
require "active_support/core_ext/array/extract_options"
 | 
			
		||||
require "active_support/core_ext/array/grouping"
 | 
			
		||||
require "active_support/core_ext/array/inquiry"
 | 
			
		||||
@ -1,213 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/xml_mini"
 | 
			
		||||
require "active_support/core_ext/hash/keys"
 | 
			
		||||
require "active_support/core_ext/string/inflections"
 | 
			
		||||
require "active_support/core_ext/object/to_param"
 | 
			
		||||
require "active_support/core_ext/object/to_query"
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Converts the array to a comma-separated sentence where the last element is
 | 
			
		||||
  # joined by the connector word.
 | 
			
		||||
  #
 | 
			
		||||
  # You can pass the following options to change the default behavior. If you
 | 
			
		||||
  # pass an option key that doesn't exist in the list below, it will raise an
 | 
			
		||||
  # <tt>ArgumentError</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  # ==== Options
 | 
			
		||||
  #
 | 
			
		||||
  # * <tt>:words_connector</tt> - The sign or word used to join the elements
 | 
			
		||||
  #   in arrays with two or more elements (default: ", ").
 | 
			
		||||
  # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
 | 
			
		||||
  #   in arrays with two elements (default: " and ").
 | 
			
		||||
  # * <tt>:last_word_connector</tt> - The sign or word used to join the last element
 | 
			
		||||
  #   in arrays with three or more elements (default: ", and ").
 | 
			
		||||
  # * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
 | 
			
		||||
  #   the connector options defined on the 'support.array' namespace in the
 | 
			
		||||
  #   corresponding dictionary file.
 | 
			
		||||
  #
 | 
			
		||||
  # ==== Examples
 | 
			
		||||
  #
 | 
			
		||||
  #   [].to_sentence                      # => ""
 | 
			
		||||
  #   ['one'].to_sentence                 # => "one"
 | 
			
		||||
  #   ['one', 'two'].to_sentence          # => "one and two"
 | 
			
		||||
  #   ['one', 'two', 'three'].to_sentence # => "one, two, and three"
 | 
			
		||||
  #
 | 
			
		||||
  #   ['one', 'two'].to_sentence(passing: 'invalid option')
 | 
			
		||||
  #   # => ArgumentError: Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale
 | 
			
		||||
  #
 | 
			
		||||
  #   ['one', 'two'].to_sentence(two_words_connector: '-')
 | 
			
		||||
  #   # => "one-two"
 | 
			
		||||
  #
 | 
			
		||||
  #   ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
 | 
			
		||||
  #   # => "one or two or at least three"
 | 
			
		||||
  #
 | 
			
		||||
  # Using <tt>:locale</tt> option:
 | 
			
		||||
  #
 | 
			
		||||
  #   # Given this locale dictionary:
 | 
			
		||||
  #   #
 | 
			
		||||
  #   #   es:
 | 
			
		||||
  #   #     support:
 | 
			
		||||
  #   #       array:
 | 
			
		||||
  #   #         words_connector: " o "
 | 
			
		||||
  #   #         two_words_connector: " y "
 | 
			
		||||
  #   #         last_word_connector: " o al menos "
 | 
			
		||||
  #
 | 
			
		||||
  #   ['uno', 'dos'].to_sentence(locale: :es)
 | 
			
		||||
  #   # => "uno y dos"
 | 
			
		||||
  #
 | 
			
		||||
  #   ['uno', 'dos', 'tres'].to_sentence(locale: :es)
 | 
			
		||||
  #   # => "uno o dos o al menos tres"
 | 
			
		||||
  def to_sentence(options = {})
 | 
			
		||||
    options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
 | 
			
		||||
 | 
			
		||||
    default_connectors = {
 | 
			
		||||
      words_connector: ", ",
 | 
			
		||||
      two_words_connector: " and ",
 | 
			
		||||
      last_word_connector: ", and "
 | 
			
		||||
    }
 | 
			
		||||
    if defined?(I18n)
 | 
			
		||||
      i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
 | 
			
		||||
      default_connectors.merge!(i18n_connectors)
 | 
			
		||||
    end
 | 
			
		||||
    options = default_connectors.merge!(options)
 | 
			
		||||
 | 
			
		||||
    case length
 | 
			
		||||
    when 0
 | 
			
		||||
      +""
 | 
			
		||||
    when 1
 | 
			
		||||
      +"#{self[0]}"
 | 
			
		||||
    when 2
 | 
			
		||||
      +"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
 | 
			
		||||
    else
 | 
			
		||||
      +"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Extends <tt>Array#to_s</tt> to convert a collection of elements into a
 | 
			
		||||
  # comma separated id list if <tt>:db</tt> argument is given as the format.
 | 
			
		||||
  #
 | 
			
		||||
  #   Blog.all.to_formatted_s(:db)  # => "1,2,3"
 | 
			
		||||
  #   Blog.none.to_formatted_s(:db) # => "null"
 | 
			
		||||
  #   [1,2].to_formatted_s          # => "[1, 2]"
 | 
			
		||||
  def to_formatted_s(format = :default)
 | 
			
		||||
    case format
 | 
			
		||||
    when :db
 | 
			
		||||
      if empty?
 | 
			
		||||
        "null"
 | 
			
		||||
      else
 | 
			
		||||
        collect(&:id).join(",")
 | 
			
		||||
      end
 | 
			
		||||
    else
 | 
			
		||||
      to_default_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :to_default_s, :to_s
 | 
			
		||||
  alias_method :to_s, :to_formatted_s
 | 
			
		||||
 | 
			
		||||
  # Returns a string that represents the array in XML by invoking +to_xml+
 | 
			
		||||
  # on each element. Active Record collections delegate their representation
 | 
			
		||||
  # in XML to this method.
 | 
			
		||||
  #
 | 
			
		||||
  # All elements are expected to respond to +to_xml+, if any of them does
 | 
			
		||||
  # not then an exception is raised.
 | 
			
		||||
  #
 | 
			
		||||
  # The root node reflects the class name of the first element in plural
 | 
			
		||||
  # if all elements belong to the same type and that's not Hash:
 | 
			
		||||
  #
 | 
			
		||||
  #   customer.projects.to_xml
 | 
			
		||||
  #
 | 
			
		||||
  #   <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
  #   <projects type="array">
 | 
			
		||||
  #     <project>
 | 
			
		||||
  #       <amount type="decimal">20000.0</amount>
 | 
			
		||||
  #       <customer-id type="integer">1567</customer-id>
 | 
			
		||||
  #       <deal-date type="date">2008-04-09</deal-date>
 | 
			
		||||
  #       ...
 | 
			
		||||
  #     </project>
 | 
			
		||||
  #     <project>
 | 
			
		||||
  #       <amount type="decimal">57230.0</amount>
 | 
			
		||||
  #       <customer-id type="integer">1567</customer-id>
 | 
			
		||||
  #       <deal-date type="date">2008-04-15</deal-date>
 | 
			
		||||
  #       ...
 | 
			
		||||
  #     </project>
 | 
			
		||||
  #   </projects>
 | 
			
		||||
  #
 | 
			
		||||
  # Otherwise the root element is "objects":
 | 
			
		||||
  #
 | 
			
		||||
  #   [{ foo: 1, bar: 2}, { baz: 3}].to_xml
 | 
			
		||||
  #
 | 
			
		||||
  #   <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
  #   <objects type="array">
 | 
			
		||||
  #     <object>
 | 
			
		||||
  #       <bar type="integer">2</bar>
 | 
			
		||||
  #       <foo type="integer">1</foo>
 | 
			
		||||
  #     </object>
 | 
			
		||||
  #     <object>
 | 
			
		||||
  #       <baz type="integer">3</baz>
 | 
			
		||||
  #     </object>
 | 
			
		||||
  #   </objects>
 | 
			
		||||
  #
 | 
			
		||||
  # If the collection is empty the root element is "nil-classes" by default:
 | 
			
		||||
  #
 | 
			
		||||
  #   [].to_xml
 | 
			
		||||
  #
 | 
			
		||||
  #   <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
  #   <nil-classes type="array"/>
 | 
			
		||||
  #
 | 
			
		||||
  # To ensure a meaningful root element use the <tt>:root</tt> option:
 | 
			
		||||
  #
 | 
			
		||||
  #   customer_with_no_projects.projects.to_xml(root: 'projects')
 | 
			
		||||
  #
 | 
			
		||||
  #   <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
  #   <projects type="array"/>
 | 
			
		||||
  #
 | 
			
		||||
  # By default name of the node for the children of root is <tt>root.singularize</tt>.
 | 
			
		||||
  # You can change it with the <tt>:children</tt> option.
 | 
			
		||||
  #
 | 
			
		||||
  # The +options+ hash is passed downwards:
 | 
			
		||||
  #
 | 
			
		||||
  #   Message.all.to_xml(skip_types: true)
 | 
			
		||||
  #
 | 
			
		||||
  #   <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
  #   <messages>
 | 
			
		||||
  #     <message>
 | 
			
		||||
  #       <created-at>2008-03-07T09:58:18+01:00</created-at>
 | 
			
		||||
  #       <id>1</id>
 | 
			
		||||
  #       <name>1</name>
 | 
			
		||||
  #       <updated-at>2008-03-07T09:58:18+01:00</updated-at>
 | 
			
		||||
  #       <user-id>1</user-id>
 | 
			
		||||
  #     </message>
 | 
			
		||||
  #   </messages>
 | 
			
		||||
  #
 | 
			
		||||
  def to_xml(options = {})
 | 
			
		||||
    require "active_support/builder" unless defined?(Builder::XmlMarkup)
 | 
			
		||||
 | 
			
		||||
    options = options.dup
 | 
			
		||||
    options[:indent]  ||= 2
 | 
			
		||||
    options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
 | 
			
		||||
    options[:root]    ||= \
 | 
			
		||||
      if first.class != Hash && all? { |e| e.is_a?(first.class) }
 | 
			
		||||
        underscored = ActiveSupport::Inflector.underscore(first.class.name)
 | 
			
		||||
        ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
 | 
			
		||||
      else
 | 
			
		||||
        "objects"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    builder = options[:builder]
 | 
			
		||||
    builder.instruct! unless options.delete(:skip_instruct)
 | 
			
		||||
 | 
			
		||||
    root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
 | 
			
		||||
    children = options.delete(:children) || root.singularize
 | 
			
		||||
    attributes = options[:skip_types] ? {} : { type: "array" }
 | 
			
		||||
 | 
			
		||||
    if empty?
 | 
			
		||||
      builder.tag!(root, attributes)
 | 
			
		||||
    else
 | 
			
		||||
      builder.tag!(root, attributes) do
 | 
			
		||||
        each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
 | 
			
		||||
        yield builder if block_given?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,21 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Removes and returns the elements for which the block returns a true value.
 | 
			
		||||
  # If no block is given, an Enumerator is returned instead.
 | 
			
		||||
  #
 | 
			
		||||
  #   numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 | 
			
		||||
  #   odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
 | 
			
		||||
  #   numbers # => [0, 2, 4, 6, 8]
 | 
			
		||||
  def extract!
 | 
			
		||||
    return to_enum(:extract!) { size } unless block_given?
 | 
			
		||||
 | 
			
		||||
    extracted_elements = []
 | 
			
		||||
 | 
			
		||||
    reject! do |element|
 | 
			
		||||
      extracted_elements << element if yield(element)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    extracted_elements
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Hash
 | 
			
		||||
  # By default, only instances of Hash itself are extractable.
 | 
			
		||||
  # Subclasses of Hash may implement this method and return
 | 
			
		||||
  # true to declare themselves as extractable. If a Hash
 | 
			
		||||
  # is extractable, Array#extract_options! pops it from
 | 
			
		||||
  # the Array when it is the last element of the Array.
 | 
			
		||||
  def extractable_options?
 | 
			
		||||
    instance_of?(Hash)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Extracts options from a set of arguments. Removes and returns the last
 | 
			
		||||
  # element in the array if it's a hash, otherwise returns a blank hash.
 | 
			
		||||
  #
 | 
			
		||||
  #   def options(*args)
 | 
			
		||||
  #     args.extract_options!
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   options(1, 2)        # => {}
 | 
			
		||||
  #   options(1, 2, a: :b) # => {:a=>:b}
 | 
			
		||||
  def extract_options!
 | 
			
		||||
    if last.is_a?(Hash) && last.extractable_options?
 | 
			
		||||
      pop
 | 
			
		||||
    else
 | 
			
		||||
      {}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,109 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Splits or iterates over the array in groups of size +number+,
 | 
			
		||||
  # padding any remaining slots with +fill_with+ unless it is +false+.
 | 
			
		||||
  #
 | 
			
		||||
  #   %w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
 | 
			
		||||
  #   ["1", "2", "3"]
 | 
			
		||||
  #   ["4", "5", "6"]
 | 
			
		||||
  #   ["7", "8", "9"]
 | 
			
		||||
  #   ["10", nil, nil]
 | 
			
		||||
  #
 | 
			
		||||
  #   %w(1 2 3 4 5).in_groups_of(2, ' ') {|group| p group}
 | 
			
		||||
  #   ["1", "2"]
 | 
			
		||||
  #   ["3", "4"]
 | 
			
		||||
  #   ["5", " "]
 | 
			
		||||
  #
 | 
			
		||||
  #   %w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
 | 
			
		||||
  #   ["1", "2"]
 | 
			
		||||
  #   ["3", "4"]
 | 
			
		||||
  #   ["5"]
 | 
			
		||||
  def in_groups_of(number, fill_with = nil)
 | 
			
		||||
    if number.to_i <= 0
 | 
			
		||||
      raise ArgumentError,
 | 
			
		||||
        "Group size must be a positive integer, was #{number.inspect}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if fill_with == false
 | 
			
		||||
      collection = self
 | 
			
		||||
    else
 | 
			
		||||
      # size % number gives how many extra we have;
 | 
			
		||||
      # subtracting from number gives how many to add;
 | 
			
		||||
      # modulo number ensures we don't add group of just fill.
 | 
			
		||||
      padding = (number - size % number) % number
 | 
			
		||||
      collection = dup.concat(Array.new(padding, fill_with))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if block_given?
 | 
			
		||||
      collection.each_slice(number) { |slice| yield(slice) }
 | 
			
		||||
    else
 | 
			
		||||
      collection.each_slice(number).to_a
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Splits or iterates over the array in +number+ of groups, padding any
 | 
			
		||||
  # remaining slots with +fill_with+ unless it is +false+.
 | 
			
		||||
  #
 | 
			
		||||
  #   %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
 | 
			
		||||
  #   ["1", "2", "3", "4"]
 | 
			
		||||
  #   ["5", "6", "7", nil]
 | 
			
		||||
  #   ["8", "9", "10", nil]
 | 
			
		||||
  #
 | 
			
		||||
  #   %w(1 2 3 4 5 6 7 8 9 10).in_groups(3, ' ') {|group| p group}
 | 
			
		||||
  #   ["1", "2", "3", "4"]
 | 
			
		||||
  #   ["5", "6", "7", " "]
 | 
			
		||||
  #   ["8", "9", "10", " "]
 | 
			
		||||
  #
 | 
			
		||||
  #   %w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
 | 
			
		||||
  #   ["1", "2", "3"]
 | 
			
		||||
  #   ["4", "5"]
 | 
			
		||||
  #   ["6", "7"]
 | 
			
		||||
  def in_groups(number, fill_with = nil)
 | 
			
		||||
    # size.div number gives minor group size;
 | 
			
		||||
    # size % number gives how many objects need extra accommodation;
 | 
			
		||||
    # each group hold either division or division + 1 items.
 | 
			
		||||
    division = size.div number
 | 
			
		||||
    modulo = size % number
 | 
			
		||||
 | 
			
		||||
    # create a new array avoiding dup
 | 
			
		||||
    groups = []
 | 
			
		||||
    start = 0
 | 
			
		||||
 | 
			
		||||
    number.times do |index|
 | 
			
		||||
      length = division + (modulo > 0 && modulo > index ? 1 : 0)
 | 
			
		||||
      groups << last_group = slice(start, length)
 | 
			
		||||
      last_group << fill_with if fill_with != false &&
 | 
			
		||||
        modulo > 0 && length == division
 | 
			
		||||
      start += length
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if block_given?
 | 
			
		||||
      groups.each { |g| yield(g) }
 | 
			
		||||
    else
 | 
			
		||||
      groups
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Divides the array into one or more subarrays based on a delimiting +value+
 | 
			
		||||
  # or the result of an optional block.
 | 
			
		||||
  #
 | 
			
		||||
  #   [1, 2, 3, 4, 5].split(3)              # => [[1, 2], [4, 5]]
 | 
			
		||||
  #   (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
 | 
			
		||||
  def split(value = nil)
 | 
			
		||||
    arr = dup
 | 
			
		||||
    result = []
 | 
			
		||||
    if block_given?
 | 
			
		||||
      while (idx = arr.index { |i| yield i })
 | 
			
		||||
        result << arr.shift(idx)
 | 
			
		||||
        arr.shift
 | 
			
		||||
      end
 | 
			
		||||
    else
 | 
			
		||||
      while (idx = arr.index(value))
 | 
			
		||||
        result << arr.shift(idx)
 | 
			
		||||
        arr.shift
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    result << arr
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,19 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/array_inquirer"
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
 | 
			
		||||
  # to check its string-like contents.
 | 
			
		||||
  #
 | 
			
		||||
  #   pets = [:cat, :dog].inquiry
 | 
			
		||||
  #
 | 
			
		||||
  #   pets.cat?     # => true
 | 
			
		||||
  #   pets.ferret?  # => false
 | 
			
		||||
  #
 | 
			
		||||
  #   pets.any?(:cat, :ferret)  # => true
 | 
			
		||||
  #   pets.any?(:ferret, :alligator)  # => false
 | 
			
		||||
  def inquiry
 | 
			
		||||
    ActiveSupport::ArrayInquirer.new(self)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,48 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Wraps its argument in an array unless it is already an array (or array-like).
 | 
			
		||||
  #
 | 
			
		||||
  # Specifically:
 | 
			
		||||
  #
 | 
			
		||||
  # * If the argument is +nil+ an empty array is returned.
 | 
			
		||||
  # * Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned.
 | 
			
		||||
  # * Otherwise, returns an array with the argument as its single element.
 | 
			
		||||
  #
 | 
			
		||||
  #     Array.wrap(nil)       # => []
 | 
			
		||||
  #     Array.wrap([1, 2, 3]) # => [1, 2, 3]
 | 
			
		||||
  #     Array.wrap(0)         # => [0]
 | 
			
		||||
  #
 | 
			
		||||
  # This method is similar in purpose to <tt>Kernel#Array</tt>, but there are some differences:
 | 
			
		||||
  #
 | 
			
		||||
  # * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
 | 
			
		||||
  #   moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
 | 
			
		||||
  #   an array with the argument as its single element right away.
 | 
			
		||||
  # * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
 | 
			
		||||
  #   raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
 | 
			
		||||
  # * It does not call +to_a+ on the argument, if the argument does not respond to +to_ary+
 | 
			
		||||
  #   it returns an array with the argument as its single element.
 | 
			
		||||
  #
 | 
			
		||||
  # The last point is easily explained with some enumerables:
 | 
			
		||||
  #
 | 
			
		||||
  #   Array(foo: :bar)      # => [[:foo, :bar]]
 | 
			
		||||
  #   Array.wrap(foo: :bar) # => [{:foo=>:bar}]
 | 
			
		||||
  #
 | 
			
		||||
  # There's also a related idiom that uses the splat operator:
 | 
			
		||||
  #
 | 
			
		||||
  #   [*object]
 | 
			
		||||
  #
 | 
			
		||||
  # which returns <tt>[]</tt> for +nil+, but calls to <tt>Array(object)</tt> otherwise.
 | 
			
		||||
  #
 | 
			
		||||
  # The differences with <tt>Kernel#Array</tt> explained above
 | 
			
		||||
  # apply to the rest of <tt>object</tt>s.
 | 
			
		||||
  def self.wrap(object)
 | 
			
		||||
    if object.nil?
 | 
			
		||||
      []
 | 
			
		||||
    elsif object.respond_to?(:to_ary)
 | 
			
		||||
      object.to_ary || [object]
 | 
			
		||||
    else
 | 
			
		||||
      [object]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "benchmark"
 | 
			
		||||
 | 
			
		||||
class << Benchmark
 | 
			
		||||
  # Benchmark realtime in milliseconds.
 | 
			
		||||
  #
 | 
			
		||||
  #   Benchmark.realtime { User.all }
 | 
			
		||||
  #   # => 8.0e-05
 | 
			
		||||
  #
 | 
			
		||||
  #   Benchmark.ms { User.all }
 | 
			
		||||
  #   # => 0.074
 | 
			
		||||
  def ms(&block)
 | 
			
		||||
    1000 * realtime(&block)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/big_decimal/conversions"
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "bigdecimal"
 | 
			
		||||
require "bigdecimal/util"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module BigDecimalWithDefaultFormat #:nodoc:
 | 
			
		||||
    def to_s(format = "F")
 | 
			
		||||
      super(format)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
BigDecimal.prepend(ActiveSupport::BigDecimalWithDefaultFormat)
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/class/attribute"
 | 
			
		||||
require "active_support/core_ext/class/subclasses"
 | 
			
		||||
@ -1,131 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
 | 
			
		||||
class Class
 | 
			
		||||
  # Declare a class-level attribute whose value is inheritable by subclasses.
 | 
			
		||||
  # Subclasses can change their own value and it will not impact parent class.
 | 
			
		||||
  #
 | 
			
		||||
  # ==== Options
 | 
			
		||||
  #
 | 
			
		||||
  # * <tt>:instance_reader</tt> - Sets the instance reader method (defaults to true).
 | 
			
		||||
  # * <tt>:instance_writer</tt> - Sets the instance writer method (defaults to true).
 | 
			
		||||
  # * <tt>:instance_accessor</tt> - Sets both instance methods (defaults to true).
 | 
			
		||||
  # * <tt>:instance_predicate</tt> - Sets a predicate method (defaults to true).
 | 
			
		||||
  # * <tt>:default</tt> - Sets a default value for the attribute (defaults to nil).
 | 
			
		||||
  #
 | 
			
		||||
  # ==== Examples
 | 
			
		||||
  #
 | 
			
		||||
  #   class Base
 | 
			
		||||
  #     class_attribute :setting
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class Subclass < Base
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   Base.setting = true
 | 
			
		||||
  #   Subclass.setting            # => true
 | 
			
		||||
  #   Subclass.setting = false
 | 
			
		||||
  #   Subclass.setting            # => false
 | 
			
		||||
  #   Base.setting                # => true
 | 
			
		||||
  #
 | 
			
		||||
  # In the above case as long as Subclass does not assign a value to setting
 | 
			
		||||
  # by performing <tt>Subclass.setting = _something_</tt>, <tt>Subclass.setting</tt>
 | 
			
		||||
  # would read value assigned to parent class. Once Subclass assigns a value then
 | 
			
		||||
  # the value assigned by Subclass would be returned.
 | 
			
		||||
  #
 | 
			
		||||
  # This matches normal Ruby method inheritance: think of writing an attribute
 | 
			
		||||
  # on a subclass as overriding the reader method. However, you need to be aware
 | 
			
		||||
  # when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
 | 
			
		||||
  # In such cases, you don't want to do changes in place. Instead use setters:
 | 
			
		||||
  #
 | 
			
		||||
  #   Base.setting = []
 | 
			
		||||
  #   Base.setting                # => []
 | 
			
		||||
  #   Subclass.setting            # => []
 | 
			
		||||
  #
 | 
			
		||||
  #   # Appending in child changes both parent and child because it is the same object:
 | 
			
		||||
  #   Subclass.setting << :foo
 | 
			
		||||
  #   Base.setting               # => [:foo]
 | 
			
		||||
  #   Subclass.setting           # => [:foo]
 | 
			
		||||
  #
 | 
			
		||||
  #   # Use setters to not propagate changes:
 | 
			
		||||
  #   Base.setting = []
 | 
			
		||||
  #   Subclass.setting += [:foo]
 | 
			
		||||
  #   Base.setting               # => []
 | 
			
		||||
  #   Subclass.setting           # => [:foo]
 | 
			
		||||
  #
 | 
			
		||||
  # For convenience, an instance predicate method is defined as well.
 | 
			
		||||
  # To skip it, pass <tt>instance_predicate: false</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   Subclass.setting?       # => false
 | 
			
		||||
  #
 | 
			
		||||
  # Instances may overwrite the class value in the same way:
 | 
			
		||||
  #
 | 
			
		||||
  #   Base.setting = true
 | 
			
		||||
  #   object = Base.new
 | 
			
		||||
  #   object.setting          # => true
 | 
			
		||||
  #   object.setting = false
 | 
			
		||||
  #   object.setting          # => false
 | 
			
		||||
  #   Base.setting            # => true
 | 
			
		||||
  #
 | 
			
		||||
  # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   object.setting          # => NoMethodError
 | 
			
		||||
  #   object.setting?         # => NoMethodError
 | 
			
		||||
  #
 | 
			
		||||
  # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   object.setting = false  # => NoMethodError
 | 
			
		||||
  #
 | 
			
		||||
  # To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  # To set a default value for the attribute, pass <tt>default:</tt>, like so:
 | 
			
		||||
  #
 | 
			
		||||
  #   class_attribute :settings, default: {}
 | 
			
		||||
  def class_attribute(*attrs, instance_accessor: true,
 | 
			
		||||
    instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
 | 
			
		||||
 | 
			
		||||
    class_methods, methods = [], []
 | 
			
		||||
    attrs.each do |name|
 | 
			
		||||
      unless name.is_a?(Symbol) || name.is_a?(String)
 | 
			
		||||
        raise TypeError, "#{name.inspect} is not a symbol nor a string"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class_methods << <<~RUBY # In case the method exists and is not public
 | 
			
		||||
        silence_redefinition_of_method def #{name}
 | 
			
		||||
        end
 | 
			
		||||
      RUBY
 | 
			
		||||
 | 
			
		||||
      methods << <<~RUBY if instance_reader
 | 
			
		||||
        silence_redefinition_of_method def #{name}
 | 
			
		||||
          defined?(@#{name}) ? @#{name} : self.class.#{name}
 | 
			
		||||
        end
 | 
			
		||||
      RUBY
 | 
			
		||||
 | 
			
		||||
      class_methods << <<~RUBY
 | 
			
		||||
        silence_redefinition_of_method def #{name}=(value)
 | 
			
		||||
          redefine_method(:#{name}) { value } if singleton_class?
 | 
			
		||||
          redefine_singleton_method(:#{name}) { value }
 | 
			
		||||
          value
 | 
			
		||||
        end
 | 
			
		||||
      RUBY
 | 
			
		||||
 | 
			
		||||
      methods << <<~RUBY if instance_writer
 | 
			
		||||
        silence_redefinition_of_method(:#{name}=)
 | 
			
		||||
        attr_writer :#{name}
 | 
			
		||||
      RUBY
 | 
			
		||||
 | 
			
		||||
      if instance_predicate
 | 
			
		||||
        class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
 | 
			
		||||
        if instance_reader
 | 
			
		||||
          methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    location = caller_locations(1, 1).first
 | 
			
		||||
    class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
 | 
			
		||||
 | 
			
		||||
    attrs.each { |name| public_send("#{name}=", default) }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
# cattr_* became mattr_* aliases in 7dfbd91b0780fbd6a1dd9bfbc176e10894871d2d,
 | 
			
		||||
# but we keep this around for libraries that directly require it knowing they
 | 
			
		||||
# want cattr_*. No need to deprecate.
 | 
			
		||||
require "active_support/core_ext/module/attribute_accessors"
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Class
 | 
			
		||||
  # Returns an array with all classes that are < than its receiver.
 | 
			
		||||
  #
 | 
			
		||||
  #   class C; end
 | 
			
		||||
  #   C.descendants # => []
 | 
			
		||||
  #
 | 
			
		||||
  #   class B < C; end
 | 
			
		||||
  #   C.descendants # => [B]
 | 
			
		||||
  #
 | 
			
		||||
  #   class A < B; end
 | 
			
		||||
  #   C.descendants # => [B, A]
 | 
			
		||||
  #
 | 
			
		||||
  #   class D < C; end
 | 
			
		||||
  #   C.descendants # => [B, A, D]
 | 
			
		||||
  def descendants
 | 
			
		||||
    ObjectSpace.each_object(singleton_class).reject do |k|
 | 
			
		||||
      k.singleton_class? || k == self
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns an array with the direct children of +self+.
 | 
			
		||||
  #
 | 
			
		||||
  #   class Foo; end
 | 
			
		||||
  #   class Bar < Foo; end
 | 
			
		||||
  #   class Baz < Bar; end
 | 
			
		||||
  #
 | 
			
		||||
  #   Foo.subclasses # => [Bar]
 | 
			
		||||
  def subclasses
 | 
			
		||||
    descendants.select { |descendant| descendant.superclass == self }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/date/acts_like"
 | 
			
		||||
require "active_support/core_ext/date/blank"
 | 
			
		||||
require "active_support/core_ext/date/calculations"
 | 
			
		||||
require "active_support/core_ext/date/conversions"
 | 
			
		||||
require "active_support/core_ext/date/zones"
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/acts_like"
 | 
			
		||||
 | 
			
		||||
class Date
 | 
			
		||||
  # Duck-types as a Date-like class. See Object#acts_like?.
 | 
			
		||||
  def acts_like_date?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
 | 
			
		||||
class Date #:nodoc:
 | 
			
		||||
  # No Date is blank:
 | 
			
		||||
  #
 | 
			
		||||
  #   Date.today.blank? # => false
 | 
			
		||||
  #
 | 
			
		||||
  # @return [false]
 | 
			
		||||
  def blank?
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,146 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
require "active_support/duration"
 | 
			
		||||
require "active_support/core_ext/object/acts_like"
 | 
			
		||||
require "active_support/core_ext/date/zones"
 | 
			
		||||
require "active_support/core_ext/time/zones"
 | 
			
		||||
require "active_support/core_ext/date_and_time/calculations"
 | 
			
		||||
 | 
			
		||||
class Date
 | 
			
		||||
  include DateAndTime::Calculations
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    attr_accessor :beginning_of_week_default
 | 
			
		||||
 | 
			
		||||
    # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=).
 | 
			
		||||
    # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>.
 | 
			
		||||
    # If no config.beginning_of_week was specified, returns :monday.
 | 
			
		||||
    def beginning_of_week
 | 
			
		||||
      Thread.current[:beginning_of_week] || beginning_of_week_default || :monday
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread.
 | 
			
		||||
    #
 | 
			
		||||
    # This method accepts any of the following day symbols:
 | 
			
		||||
    # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday
 | 
			
		||||
    def beginning_of_week=(week_start)
 | 
			
		||||
      Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns week start day symbol (e.g. :monday), or raises an +ArgumentError+ for invalid day symbol.
 | 
			
		||||
    def find_beginning_of_week!(week_start)
 | 
			
		||||
      raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
 | 
			
		||||
      week_start
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
 | 
			
		||||
    def yesterday
 | 
			
		||||
      ::Date.current.yesterday
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new Date representing the date 1 day after today (i.e. tomorrow's date).
 | 
			
		||||
    def tomorrow
 | 
			
		||||
      ::Date.current.tomorrow
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns Time.zone.today when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns Date.today.
 | 
			
		||||
    def current
 | 
			
		||||
      ::Time.zone ? ::Time.zone.today : ::Date.today
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
 | 
			
		||||
  # and then subtracts the specified number of seconds.
 | 
			
		||||
  def ago(seconds)
 | 
			
		||||
    in_time_zone.since(-seconds)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
 | 
			
		||||
  # and then adds the specified number of seconds
 | 
			
		||||
  def since(seconds)
 | 
			
		||||
    in_time_zone.since(seconds)
 | 
			
		||||
  end
 | 
			
		||||
  alias :in :since
 | 
			
		||||
 | 
			
		||||
  # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
 | 
			
		||||
  def beginning_of_day
 | 
			
		||||
    in_time_zone
 | 
			
		||||
  end
 | 
			
		||||
  alias :midnight :beginning_of_day
 | 
			
		||||
  alias :at_midnight :beginning_of_day
 | 
			
		||||
  alias :at_beginning_of_day :beginning_of_day
 | 
			
		||||
 | 
			
		||||
  # Converts Date to a Time (or DateTime if necessary) with the time portion set to the middle of the day (12:00)
 | 
			
		||||
  def middle_of_day
 | 
			
		||||
    in_time_zone.middle_of_day
 | 
			
		||||
  end
 | 
			
		||||
  alias :midday :middle_of_day
 | 
			
		||||
  alias :noon :middle_of_day
 | 
			
		||||
  alias :at_midday :middle_of_day
 | 
			
		||||
  alias :at_noon :middle_of_day
 | 
			
		||||
  alias :at_middle_of_day :middle_of_day
 | 
			
		||||
 | 
			
		||||
  # Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
 | 
			
		||||
  def end_of_day
 | 
			
		||||
    in_time_zone.end_of_day
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_day :end_of_day
 | 
			
		||||
 | 
			
		||||
  def plus_with_duration(other) #:nodoc:
 | 
			
		||||
    if ActiveSupport::Duration === other
 | 
			
		||||
      other.since(self)
 | 
			
		||||
    else
 | 
			
		||||
      plus_without_duration(other)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :plus_without_duration, :+
 | 
			
		||||
  alias_method :+, :plus_with_duration
 | 
			
		||||
 | 
			
		||||
  def minus_with_duration(other) #:nodoc:
 | 
			
		||||
    if ActiveSupport::Duration === other
 | 
			
		||||
      plus_with_duration(-other)
 | 
			
		||||
    else
 | 
			
		||||
      minus_without_duration(other)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :minus_without_duration, :-
 | 
			
		||||
  alias_method :-, :minus_with_duration
 | 
			
		||||
 | 
			
		||||
  # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
 | 
			
		||||
  # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
 | 
			
		||||
  def advance(options)
 | 
			
		||||
    d = self
 | 
			
		||||
 | 
			
		||||
    d = d >> options[:years] * 12 if options[:years]
 | 
			
		||||
    d = d >> options[:months] if options[:months]
 | 
			
		||||
    d = d + options[:weeks] * 7 if options[:weeks]
 | 
			
		||||
    d = d + options[:days] if options[:days]
 | 
			
		||||
 | 
			
		||||
    d
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
 | 
			
		||||
  # The +options+ parameter is a hash with a combination of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   Date.new(2007, 5, 12).change(day: 1)               # => Date.new(2007, 5, 1)
 | 
			
		||||
  #   Date.new(2007, 5, 12).change(year: 2005, month: 1) # => Date.new(2005, 1, 12)
 | 
			
		||||
  def change(options)
 | 
			
		||||
    ::Date.new(
 | 
			
		||||
      options.fetch(:year, year),
 | 
			
		||||
      options.fetch(:month, month),
 | 
			
		||||
      options.fetch(:day, day)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Allow Date to be compared with Time by converting to DateTime and relying on the <=> from there.
 | 
			
		||||
  def compare_with_coercion(other)
 | 
			
		||||
    if other.is_a?(Time)
 | 
			
		||||
      to_datetime <=> other
 | 
			
		||||
    else
 | 
			
		||||
      compare_without_coercion(other)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :compare_without_coercion, :<=>
 | 
			
		||||
  alias_method :<=>, :compare_with_coercion
 | 
			
		||||
end
 | 
			
		||||
@ -1,97 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
require "active_support/inflector/methods"
 | 
			
		||||
require "active_support/core_ext/date/zones"
 | 
			
		||||
require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
 | 
			
		||||
class Date
 | 
			
		||||
  DATE_FORMATS = {
 | 
			
		||||
    short: "%d %b",
 | 
			
		||||
    long: "%B %d, %Y",
 | 
			
		||||
    db: "%Y-%m-%d",
 | 
			
		||||
    inspect: "%Y-%m-%d",
 | 
			
		||||
    number: "%Y%m%d",
 | 
			
		||||
    long_ordinal: lambda { |date|
 | 
			
		||||
      day_format = ActiveSupport::Inflector.ordinalize(date.day)
 | 
			
		||||
      date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
 | 
			
		||||
    },
 | 
			
		||||
    rfc822: "%d %b %Y",
 | 
			
		||||
    iso8601: lambda { |date| date.iso8601 }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # Convert to a formatted string. See DATE_FORMATS for predefined formats.
 | 
			
		||||
  #
 | 
			
		||||
  # This method is aliased to <tt>to_s</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   date = Date.new(2007, 11, 10)       # => Sat, 10 Nov 2007
 | 
			
		||||
  #
 | 
			
		||||
  #   date.to_formatted_s(:db)            # => "2007-11-10"
 | 
			
		||||
  #   date.to_s(:db)                      # => "2007-11-10"
 | 
			
		||||
  #
 | 
			
		||||
  #   date.to_formatted_s(:short)         # => "10 Nov"
 | 
			
		||||
  #   date.to_formatted_s(:number)        # => "20071110"
 | 
			
		||||
  #   date.to_formatted_s(:long)          # => "November 10, 2007"
 | 
			
		||||
  #   date.to_formatted_s(:long_ordinal)  # => "November 10th, 2007"
 | 
			
		||||
  #   date.to_formatted_s(:rfc822)        # => "10 Nov 2007"
 | 
			
		||||
  #   date.to_formatted_s(:iso8601)       # => "2007-11-10"
 | 
			
		||||
  #
 | 
			
		||||
  # == Adding your own date formats to to_formatted_s
 | 
			
		||||
  # You can add your own formats to the Date::DATE_FORMATS hash.
 | 
			
		||||
  # Use the format name as the hash key and either a strftime string
 | 
			
		||||
  # or Proc instance that takes a date argument as the value.
 | 
			
		||||
  #
 | 
			
		||||
  #   # config/initializers/date_formats.rb
 | 
			
		||||
  #   Date::DATE_FORMATS[:month_and_year] = '%B %Y'
 | 
			
		||||
  #   Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
 | 
			
		||||
  def to_formatted_s(format = :default)
 | 
			
		||||
    if formatter = DATE_FORMATS[format]
 | 
			
		||||
      if formatter.respond_to?(:call)
 | 
			
		||||
        formatter.call(self).to_s
 | 
			
		||||
      else
 | 
			
		||||
        strftime(formatter)
 | 
			
		||||
      end
 | 
			
		||||
    else
 | 
			
		||||
      to_default_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :to_default_s, :to_s
 | 
			
		||||
  alias_method :to_s, :to_formatted_s
 | 
			
		||||
 | 
			
		||||
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
 | 
			
		||||
  def readable_inspect
 | 
			
		||||
    strftime("%a, %d %b %Y")
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :default_inspect, :inspect
 | 
			
		||||
  alias_method :inspect, :readable_inspect
 | 
			
		||||
 | 
			
		||||
  silence_redefinition_of_method :to_time
 | 
			
		||||
 | 
			
		||||
  # Converts a Date instance to a Time, where the time is set to the beginning of the day.
 | 
			
		||||
  # The timezone can be either :local or :utc (default :local).
 | 
			
		||||
  #
 | 
			
		||||
  #   date = Date.new(2007, 11, 10)  # => Sat, 10 Nov 2007
 | 
			
		||||
  #
 | 
			
		||||
  #   date.to_time                   # => 2007-11-10 00:00:00 0800
 | 
			
		||||
  #   date.to_time(:local)           # => 2007-11-10 00:00:00 0800
 | 
			
		||||
  #
 | 
			
		||||
  #   date.to_time(:utc)             # => 2007-11-10 00:00:00 UTC
 | 
			
		||||
  #
 | 
			
		||||
  # NOTE: The :local timezone is Ruby's *process* timezone, i.e. ENV['TZ'].
 | 
			
		||||
  #       If the *application's* timezone is needed, then use +in_time_zone+ instead.
 | 
			
		||||
  def to_time(form = :local)
 | 
			
		||||
    raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
 | 
			
		||||
    ::Time.public_send(form, year, month, day)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  silence_redefinition_of_method :xmlschema
 | 
			
		||||
 | 
			
		||||
  # Returns a string which represents the time in used time zone as DateTime
 | 
			
		||||
  # defined by XML Schema:
 | 
			
		||||
  #
 | 
			
		||||
  #   date = Date.new(2015, 05, 23)  # => Sat, 23 May 2015
 | 
			
		||||
  #   date.xmlschema                 # => "2015-05-23T00:00:00+04:00"
 | 
			
		||||
  def xmlschema
 | 
			
		||||
    in_time_zone.xmlschema
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
require "active_support/core_ext/date_and_time/zones"
 | 
			
		||||
 | 
			
		||||
class Date
 | 
			
		||||
  include DateAndTime::Zones
 | 
			
		||||
end
 | 
			
		||||
@ -1,364 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/try"
 | 
			
		||||
require "active_support/core_ext/date_time/conversions"
 | 
			
		||||
 | 
			
		||||
module DateAndTime
 | 
			
		||||
  module Calculations
 | 
			
		||||
    DAYS_INTO_WEEK = {
 | 
			
		||||
      sunday: 0,
 | 
			
		||||
      monday: 1,
 | 
			
		||||
      tuesday: 2,
 | 
			
		||||
      wednesday: 3,
 | 
			
		||||
      thursday: 4,
 | 
			
		||||
      friday: 5,
 | 
			
		||||
      saturday: 6
 | 
			
		||||
    }
 | 
			
		||||
    WEEKEND_DAYS = [ 6, 0 ]
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing yesterday.
 | 
			
		||||
    def yesterday
 | 
			
		||||
      advance(days: -1)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing tomorrow.
 | 
			
		||||
    def tomorrow
 | 
			
		||||
      advance(days: 1)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time is today.
 | 
			
		||||
    def today?
 | 
			
		||||
      to_date == ::Date.current
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time is tomorrow.
 | 
			
		||||
    def tomorrow?
 | 
			
		||||
      to_date == ::Date.current.tomorrow
 | 
			
		||||
    end
 | 
			
		||||
    alias :next_day? :tomorrow?
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time is yesterday.
 | 
			
		||||
    def yesterday?
 | 
			
		||||
      to_date == ::Date.current.yesterday
 | 
			
		||||
    end
 | 
			
		||||
    alias :prev_day? :yesterday?
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time is in the past.
 | 
			
		||||
    def past?
 | 
			
		||||
      self < self.class.current
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time is in the future.
 | 
			
		||||
    def future?
 | 
			
		||||
      self > self.class.current
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time falls on a Saturday or Sunday.
 | 
			
		||||
    def on_weekend?
 | 
			
		||||
      WEEKEND_DAYS.include?(wday)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time does not fall on a Saturday or Sunday.
 | 
			
		||||
    def on_weekday?
 | 
			
		||||
      !WEEKEND_DAYS.include?(wday)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time falls before <tt>date_or_time</tt>.
 | 
			
		||||
    def before?(date_or_time)
 | 
			
		||||
      self < date_or_time
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the date/time falls after <tt>date_or_time</tt>.
 | 
			
		||||
    def after?(date_or_time)
 | 
			
		||||
      self > date_or_time
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of days ago.
 | 
			
		||||
    def days_ago(days)
 | 
			
		||||
      advance(days: -days)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of days in the future.
 | 
			
		||||
    def days_since(days)
 | 
			
		||||
      advance(days: days)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of weeks ago.
 | 
			
		||||
    def weeks_ago(weeks)
 | 
			
		||||
      advance(weeks: -weeks)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of weeks in the future.
 | 
			
		||||
    def weeks_since(weeks)
 | 
			
		||||
      advance(weeks: weeks)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of months ago.
 | 
			
		||||
    def months_ago(months)
 | 
			
		||||
      advance(months: -months)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of months in the future.
 | 
			
		||||
    def months_since(months)
 | 
			
		||||
      advance(months: months)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of years ago.
 | 
			
		||||
    def years_ago(years)
 | 
			
		||||
      advance(years: -years)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time the specified number of years in the future.
 | 
			
		||||
    def years_since(years)
 | 
			
		||||
      advance(years: years)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time at the start of the month.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today # => Thu, 18 Jun 2015
 | 
			
		||||
    #   today.beginning_of_month # => Mon, 01 Jun 2015
 | 
			
		||||
    #
 | 
			
		||||
    # +DateTime+ objects will have a time set to 0:00.
 | 
			
		||||
    #
 | 
			
		||||
    #   now = DateTime.current # => Thu, 18 Jun 2015 15:23:13 +0000
 | 
			
		||||
    #   now.beginning_of_month # => Mon, 01 Jun 2015 00:00:00 +0000
 | 
			
		||||
    def beginning_of_month
 | 
			
		||||
      first_hour(change(day: 1))
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_beginning_of_month :beginning_of_month
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time at the start of the quarter.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today # => Fri, 10 Jul 2015
 | 
			
		||||
    #   today.beginning_of_quarter # => Wed, 01 Jul 2015
 | 
			
		||||
    #
 | 
			
		||||
    # +DateTime+ objects will have a time set to 0:00.
 | 
			
		||||
    #
 | 
			
		||||
    #   now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
 | 
			
		||||
    #   now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
 | 
			
		||||
    def beginning_of_quarter
 | 
			
		||||
      first_quarter_month = month - (2 + month) % 3
 | 
			
		||||
      beginning_of_month.change(month: first_quarter_month)
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_beginning_of_quarter :beginning_of_quarter
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time at the end of the quarter.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today # => Fri, 10 Jul 2015
 | 
			
		||||
    #   today.end_of_quarter # => Wed, 30 Sep 2015
 | 
			
		||||
    #
 | 
			
		||||
    # +DateTime+ objects will have a time set to 23:59:59.
 | 
			
		||||
    #
 | 
			
		||||
    #   now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
 | 
			
		||||
    #   now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
 | 
			
		||||
    def end_of_quarter
 | 
			
		||||
      last_quarter_month = month + (12 - month) % 3
 | 
			
		||||
      beginning_of_month.change(month: last_quarter_month).end_of_month
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_end_of_quarter :end_of_quarter
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time at the beginning of the year.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today # => Fri, 10 Jul 2015
 | 
			
		||||
    #   today.beginning_of_year # => Thu, 01 Jan 2015
 | 
			
		||||
    #
 | 
			
		||||
    # +DateTime+ objects will have a time set to 0:00.
 | 
			
		||||
    #
 | 
			
		||||
    #   now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
 | 
			
		||||
    #   now.beginning_of_year # => Thu, 01 Jan 2015 00:00:00 +0000
 | 
			
		||||
    def beginning_of_year
 | 
			
		||||
      change(month: 1).beginning_of_month
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_beginning_of_year :beginning_of_year
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the given day in the next week.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today # => Thu, 07 May 2015
 | 
			
		||||
    #   today.next_week    # => Mon, 11 May 2015
 | 
			
		||||
    #
 | 
			
		||||
    # The +given_day_in_next_week+ defaults to the beginning of the week
 | 
			
		||||
    # which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
 | 
			
		||||
    # when set.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today       # => Thu, 07 May 2015
 | 
			
		||||
    #   today.next_week(:friday) # => Fri, 15 May 2015
 | 
			
		||||
    #
 | 
			
		||||
    # +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
 | 
			
		||||
    #
 | 
			
		||||
    #   now = DateTime.current # => Thu, 07 May 2015 13:31:16 +0000
 | 
			
		||||
    #   now.next_week      # => Mon, 11 May 2015 00:00:00 +0000
 | 
			
		||||
    def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false)
 | 
			
		||||
      result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
 | 
			
		||||
      same_time ? copy_time_to(result) : result
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the next weekday.
 | 
			
		||||
    def next_weekday
 | 
			
		||||
      if next_day.on_weekend?
 | 
			
		||||
        next_week(:monday, same_time: true)
 | 
			
		||||
      else
 | 
			
		||||
        next_day
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Short-hand for months_since(3)
 | 
			
		||||
    def next_quarter
 | 
			
		||||
      months_since(3)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the given day in the previous week.
 | 
			
		||||
    # Week is assumed to start on +start_day+, default is
 | 
			
		||||
    # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
 | 
			
		||||
    # DateTime objects have their time set to 0:00 unless +same_time+ is true.
 | 
			
		||||
    def prev_week(start_day = Date.beginning_of_week, same_time: false)
 | 
			
		||||
      result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
 | 
			
		||||
      same_time ? copy_time_to(result) : result
 | 
			
		||||
    end
 | 
			
		||||
    alias_method :last_week, :prev_week
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the previous weekday.
 | 
			
		||||
    def prev_weekday
 | 
			
		||||
      if prev_day.on_weekend?
 | 
			
		||||
        copy_time_to(beginning_of_week(:friday))
 | 
			
		||||
      else
 | 
			
		||||
        prev_day
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    alias_method :last_weekday, :prev_weekday
 | 
			
		||||
 | 
			
		||||
    # Short-hand for months_ago(1).
 | 
			
		||||
    def last_month
 | 
			
		||||
      months_ago(1)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Short-hand for months_ago(3).
 | 
			
		||||
    def prev_quarter
 | 
			
		||||
      months_ago(3)
 | 
			
		||||
    end
 | 
			
		||||
    alias_method :last_quarter, :prev_quarter
 | 
			
		||||
 | 
			
		||||
    # Short-hand for years_ago(1).
 | 
			
		||||
    def last_year
 | 
			
		||||
      years_ago(1)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the number of days to the start of the week on the given day.
 | 
			
		||||
    # Week is assumed to start on +start_day+, default is
 | 
			
		||||
    # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
 | 
			
		||||
    def days_to_week_start(start_day = Date.beginning_of_week)
 | 
			
		||||
      start_day_number = DAYS_INTO_WEEK.fetch(start_day)
 | 
			
		||||
      (wday - start_day_number) % 7
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the start of this week on the given day.
 | 
			
		||||
    # Week is assumed to start on +start_day+, default is
 | 
			
		||||
    # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
 | 
			
		||||
    # +DateTime+ objects have their time set to 0:00.
 | 
			
		||||
    def beginning_of_week(start_day = Date.beginning_of_week)
 | 
			
		||||
      result = days_ago(days_to_week_start(start_day))
 | 
			
		||||
      acts_like?(:time) ? result.midnight : result
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_beginning_of_week :beginning_of_week
 | 
			
		||||
 | 
			
		||||
    # Returns Monday of this week assuming that week starts on Monday.
 | 
			
		||||
    # +DateTime+ objects have their time set to 0:00.
 | 
			
		||||
    def monday
 | 
			
		||||
      beginning_of_week(:monday)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the end of this week on the given day.
 | 
			
		||||
    # Week is assumed to start on +start_day+, default is
 | 
			
		||||
    # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
 | 
			
		||||
    # DateTime objects have their time set to 23:59:59.
 | 
			
		||||
    def end_of_week(start_day = Date.beginning_of_week)
 | 
			
		||||
      last_hour(days_since(6 - days_to_week_start(start_day)))
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_end_of_week :end_of_week
 | 
			
		||||
 | 
			
		||||
    # Returns Sunday of this week assuming that week starts on Monday.
 | 
			
		||||
    # +DateTime+ objects have their time set to 23:59:59.
 | 
			
		||||
    def sunday
 | 
			
		||||
      end_of_week(:monday)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the end of the month.
 | 
			
		||||
    # DateTime objects will have a time set to 23:59:59.
 | 
			
		||||
    def end_of_month
 | 
			
		||||
      last_day = ::Time.days_in_month(month, year)
 | 
			
		||||
      last_hour(days_since(last_day - day))
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_end_of_month :end_of_month
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the end of the year.
 | 
			
		||||
    # DateTime objects will have a time set to 23:59:59.
 | 
			
		||||
    def end_of_year
 | 
			
		||||
      change(month: 12).end_of_month
 | 
			
		||||
    end
 | 
			
		||||
    alias :at_end_of_year :end_of_year
 | 
			
		||||
 | 
			
		||||
    # Returns a Range representing the whole day of the current date/time.
 | 
			
		||||
    def all_day
 | 
			
		||||
      beginning_of_day..end_of_day
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a Range representing the whole week of the current date/time.
 | 
			
		||||
    # Week starts on start_day, default is <tt>Date.beginning_of_week</tt> or <tt>config.beginning_of_week</tt> when set.
 | 
			
		||||
    def all_week(start_day = Date.beginning_of_week)
 | 
			
		||||
      beginning_of_week(start_day)..end_of_week(start_day)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a Range representing the whole month of the current date/time.
 | 
			
		||||
    def all_month
 | 
			
		||||
      beginning_of_month..end_of_month
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a Range representing the whole quarter of the current date/time.
 | 
			
		||||
    def all_quarter
 | 
			
		||||
      beginning_of_quarter..end_of_quarter
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a Range representing the whole year of the current date/time.
 | 
			
		||||
    def all_year
 | 
			
		||||
      beginning_of_year..end_of_year
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the next occurrence of the specified day of week.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today               # => Thu, 14 Dec 2017
 | 
			
		||||
    #   today.next_occurring(:monday)    # => Mon, 18 Dec 2017
 | 
			
		||||
    #   today.next_occurring(:thursday)  # => Thu, 21 Dec 2017
 | 
			
		||||
    def next_occurring(day_of_week)
 | 
			
		||||
      from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
 | 
			
		||||
      from_now += 7 unless from_now > 0
 | 
			
		||||
      advance(days: from_now)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a new date/time representing the previous occurrence of the specified day of week.
 | 
			
		||||
    #
 | 
			
		||||
    #   today = Date.today               # => Thu, 14 Dec 2017
 | 
			
		||||
    #   today.prev_occurring(:monday)    # => Mon, 11 Dec 2017
 | 
			
		||||
    #   today.prev_occurring(:thursday)  # => Thu, 07 Dec 2017
 | 
			
		||||
    def prev_occurring(day_of_week)
 | 
			
		||||
      ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
 | 
			
		||||
      ago += 7 unless ago > 0
 | 
			
		||||
      advance(days: -ago)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def first_hour(date_or_time)
 | 
			
		||||
        date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def last_hour(date_or_time)
 | 
			
		||||
        date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def days_span(day)
 | 
			
		||||
        (DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def copy_time_to(other)
 | 
			
		||||
        other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/module/attribute_accessors"
 | 
			
		||||
 | 
			
		||||
module DateAndTime
 | 
			
		||||
  module Compatibility
 | 
			
		||||
    # If true, +to_time+ preserves the timezone offset of receiver.
 | 
			
		||||
    #
 | 
			
		||||
    # NOTE: With Ruby 2.4+ the default for +to_time+ changed from
 | 
			
		||||
    # converting to the local system time, to preserving the offset
 | 
			
		||||
    # of the receiver. For backwards compatibility we're overriding
 | 
			
		||||
    # this behavior, but new apps will have an initializer that sets
 | 
			
		||||
    # this to true, because the new behavior is preferred.
 | 
			
		||||
    mattr_accessor :preserve_timezone, instance_writer: false, default: false
 | 
			
		||||
 | 
			
		||||
    # Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
 | 
			
		||||
    #
 | 
			
		||||
    # When `true`, it returns local times with an UTC offset, with `false` local
 | 
			
		||||
    # times are returned as UTC.
 | 
			
		||||
    #
 | 
			
		||||
    #   # Given this zone:
 | 
			
		||||
    #   zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
 | 
			
		||||
    #
 | 
			
		||||
    #   # With `utc_to_local_returns_utc_offset_times = false`, local time is converted to UTC:
 | 
			
		||||
    #   zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 UTC
 | 
			
		||||
    #
 | 
			
		||||
    #   # With `utc_to_local_returns_utc_offset_times = true`, local time is returned with UTC offset:
 | 
			
		||||
    #   zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 -0500
 | 
			
		||||
    mattr_accessor :utc_to_local_returns_utc_offset_times, instance_writer: false, default: false
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,40 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module DateAndTime
 | 
			
		||||
  module Zones
 | 
			
		||||
    # Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
 | 
			
		||||
    # if Time.zone_default is set. Otherwise, it returns the current time.
 | 
			
		||||
    #
 | 
			
		||||
    #   Time.zone = 'Hawaii'        # => 'Hawaii'
 | 
			
		||||
    #   Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
 | 
			
		||||
    #   Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
 | 
			
		||||
    #
 | 
			
		||||
    # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
 | 
			
		||||
    # instead of the operating system's time zone.
 | 
			
		||||
    #
 | 
			
		||||
    # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
 | 
			
		||||
    # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
 | 
			
		||||
    #
 | 
			
		||||
    #   Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
 | 
			
		||||
    #   Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
 | 
			
		||||
    def in_time_zone(zone = ::Time.zone)
 | 
			
		||||
      time_zone = ::Time.find_zone! zone
 | 
			
		||||
      time = acts_like?(:time) ? self : nil
 | 
			
		||||
 | 
			
		||||
      if time_zone
 | 
			
		||||
        time_with_zone(time, time_zone)
 | 
			
		||||
      else
 | 
			
		||||
        time || to_time
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def time_with_zone(time, zone)
 | 
			
		||||
        if time
 | 
			
		||||
          ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
 | 
			
		||||
        else
 | 
			
		||||
          ActiveSupport::TimeWithZone.new(nil, zone, to_time(:utc))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/date_time/acts_like"
 | 
			
		||||
require "active_support/core_ext/date_time/blank"
 | 
			
		||||
require "active_support/core_ext/date_time/calculations"
 | 
			
		||||
require "active_support/core_ext/date_time/compatibility"
 | 
			
		||||
require "active_support/core_ext/date_time/conversions"
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
require "active_support/core_ext/object/acts_like"
 | 
			
		||||
 | 
			
		||||
class DateTime
 | 
			
		||||
  # Duck-types as a Date-like class. See Object#acts_like?.
 | 
			
		||||
  def acts_like_date?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Duck-types as a Time-like class. See Object#acts_like?.
 | 
			
		||||
  def acts_like_time?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
 | 
			
		||||
class DateTime #:nodoc:
 | 
			
		||||
  # No DateTime is ever blank:
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.now.blank? # => false
 | 
			
		||||
  #
 | 
			
		||||
  # @return [false]
 | 
			
		||||
  def blank?
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,211 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
 | 
			
		||||
class DateTime
 | 
			
		||||
  class << self
 | 
			
		||||
    # Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or
 | 
			
		||||
    # <tt>config.time_zone</tt> are set, otherwise returns
 | 
			
		||||
    # <tt>Time.now.to_datetime</tt>.
 | 
			
		||||
    def current
 | 
			
		||||
      ::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the number of seconds since 00:00:00.
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.new(2012, 8, 29,  0,  0,  0).seconds_since_midnight # => 0
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399
 | 
			
		||||
  def seconds_since_midnight
 | 
			
		||||
    sec + (min * 60) + (hour * 3600)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the number of seconds until 23:59:59.
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.new(2012, 8, 29,  0,  0,  0).seconds_until_end_of_day # => 86399
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
 | 
			
		||||
  def seconds_until_end_of_day
 | 
			
		||||
    end_of_day.to_i - to_i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the fraction of a second as a +Rational+
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)
 | 
			
		||||
  def subsec
 | 
			
		||||
    sec_fraction
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime where one or more of the elements have been changed
 | 
			
		||||
  # according to the +options+ parameter. The time options (<tt>:hour</tt>,
 | 
			
		||||
  # <tt>:min</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
 | 
			
		||||
  # passed, then minute and sec is set to 0. If the hour and minute is passed,
 | 
			
		||||
  # then sec is set to 0. The +options+ parameter takes a hash with any of these
 | 
			
		||||
  # keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>,
 | 
			
		||||
  # <tt>:min</tt>, <tt>:sec</tt>, <tt>:offset</tt>, <tt>:start</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 22, 35, 0).change(day: 1)              # => DateTime.new(2012, 8, 1, 22, 35, 0)
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1)  # => DateTime.new(1981, 8, 1, 22, 35, 0)
 | 
			
		||||
  #   DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
 | 
			
		||||
  def change(options)
 | 
			
		||||
    if new_nsec = options[:nsec]
 | 
			
		||||
      raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
 | 
			
		||||
      new_fraction = Rational(new_nsec, 1000000000)
 | 
			
		||||
    else
 | 
			
		||||
      new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
 | 
			
		||||
      new_fraction = Rational(new_usec, 1000000)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    raise ArgumentError, "argument out of range" if new_fraction >= 1
 | 
			
		||||
 | 
			
		||||
    ::DateTime.civil(
 | 
			
		||||
      options.fetch(:year, year),
 | 
			
		||||
      options.fetch(:month, month),
 | 
			
		||||
      options.fetch(:day, day),
 | 
			
		||||
      options.fetch(:hour, hour),
 | 
			
		||||
      options.fetch(:min, options[:hour] ? 0 : min),
 | 
			
		||||
      options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
 | 
			
		||||
      options.fetch(:offset, offset),
 | 
			
		||||
      options.fetch(:start, start)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Uses Date to provide precise Time calculations for years, months, and days.
 | 
			
		||||
  # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
 | 
			
		||||
  # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
 | 
			
		||||
  # <tt>:minutes</tt>, <tt>:seconds</tt>.
 | 
			
		||||
  def advance(options)
 | 
			
		||||
    unless options[:weeks].nil?
 | 
			
		||||
      options[:weeks], partial_weeks = options[:weeks].divmod(1)
 | 
			
		||||
      options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    unless options[:days].nil?
 | 
			
		||||
      options[:days], partial_days = options[:days].divmod(1)
 | 
			
		||||
      options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    d = to_date.advance(options)
 | 
			
		||||
    datetime_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
 | 
			
		||||
    seconds_to_advance = \
 | 
			
		||||
      options.fetch(:seconds, 0) +
 | 
			
		||||
      options.fetch(:minutes, 0) * 60 +
 | 
			
		||||
      options.fetch(:hours, 0) * 3600
 | 
			
		||||
 | 
			
		||||
    if seconds_to_advance.zero?
 | 
			
		||||
      datetime_advanced_by_date
 | 
			
		||||
    else
 | 
			
		||||
      datetime_advanced_by_date.since(seconds_to_advance)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the time a number of seconds ago.
 | 
			
		||||
  # Do not use this method in combination with x.months, use months_ago instead!
 | 
			
		||||
  def ago(seconds)
 | 
			
		||||
    since(-seconds)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the time a number of seconds since the
 | 
			
		||||
  # instance time. Do not use this method in combination with x.months, use
 | 
			
		||||
  # months_since instead!
 | 
			
		||||
  def since(seconds)
 | 
			
		||||
    self + Rational(seconds, 86400)
 | 
			
		||||
  end
 | 
			
		||||
  alias :in :since
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the start of the day (0:00).
 | 
			
		||||
  def beginning_of_day
 | 
			
		||||
    change(hour: 0)
 | 
			
		||||
  end
 | 
			
		||||
  alias :midnight :beginning_of_day
 | 
			
		||||
  alias :at_midnight :beginning_of_day
 | 
			
		||||
  alias :at_beginning_of_day :beginning_of_day
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the middle of the day (12:00)
 | 
			
		||||
  def middle_of_day
 | 
			
		||||
    change(hour: 12)
 | 
			
		||||
  end
 | 
			
		||||
  alias :midday :middle_of_day
 | 
			
		||||
  alias :noon :middle_of_day
 | 
			
		||||
  alias :at_midday :middle_of_day
 | 
			
		||||
  alias :at_noon :middle_of_day
 | 
			
		||||
  alias :at_middle_of_day :middle_of_day
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the end of the day (23:59:59).
 | 
			
		||||
  def end_of_day
 | 
			
		||||
    change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_day :end_of_day
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the start of the hour (hh:00:00).
 | 
			
		||||
  def beginning_of_hour
 | 
			
		||||
    change(min: 0)
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_beginning_of_hour :beginning_of_hour
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the end of the hour (hh:59:59).
 | 
			
		||||
  def end_of_hour
 | 
			
		||||
    change(min: 59, sec: 59, usec: Rational(999999999, 1000))
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_hour :end_of_hour
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the start of the minute (hh:mm:00).
 | 
			
		||||
  def beginning_of_minute
 | 
			
		||||
    change(sec: 0)
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_beginning_of_minute :beginning_of_minute
 | 
			
		||||
 | 
			
		||||
  # Returns a new DateTime representing the end of the minute (hh:mm:59).
 | 
			
		||||
  def end_of_minute
 | 
			
		||||
    change(sec: 59, usec: Rational(999999999, 1000))
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_minute :end_of_minute
 | 
			
		||||
 | 
			
		||||
  # Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
 | 
			
		||||
  def localtime(utc_offset = nil)
 | 
			
		||||
    utc = new_offset(0)
 | 
			
		||||
 | 
			
		||||
    Time.utc(
 | 
			
		||||
      utc.year, utc.month, utc.day,
 | 
			
		||||
      utc.hour, utc.min, utc.sec + utc.sec_fraction
 | 
			
		||||
    ).getlocal(utc_offset)
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :getlocal, :localtime
 | 
			
		||||
 | 
			
		||||
  # Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24))     # => Mon, 21 Feb 2005 10:11:12 -0600
 | 
			
		||||
  #   DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
 | 
			
		||||
  def utc
 | 
			
		||||
    utc = new_offset(0)
 | 
			
		||||
 | 
			
		||||
    Time.utc(
 | 
			
		||||
      utc.year, utc.month, utc.day,
 | 
			
		||||
      utc.hour, utc.min, utc.sec + utc.sec_fraction
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :getgm, :utc
 | 
			
		||||
  alias_method :getutc, :utc
 | 
			
		||||
  alias_method :gmtime, :utc
 | 
			
		||||
 | 
			
		||||
  # Returns +true+ if <tt>offset == 0</tt>.
 | 
			
		||||
  def utc?
 | 
			
		||||
    offset == 0
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the offset value in seconds.
 | 
			
		||||
  def utc_offset
 | 
			
		||||
    (offset * 86400).to_i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Layers additional behavior on DateTime#<=> so that Time and
 | 
			
		||||
  # ActiveSupport::TimeWithZone instances can be compared with a DateTime.
 | 
			
		||||
  def <=>(other)
 | 
			
		||||
    if other.respond_to? :to_datetime
 | 
			
		||||
      super other.to_datetime rescue nil
 | 
			
		||||
    else
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,18 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/date_and_time/compatibility"
 | 
			
		||||
require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
 | 
			
		||||
class DateTime
 | 
			
		||||
  include DateAndTime::Compatibility
 | 
			
		||||
 | 
			
		||||
  silence_redefinition_of_method :to_time
 | 
			
		||||
 | 
			
		||||
  # Either return an instance of +Time+ with the same UTC offset
 | 
			
		||||
  # as +self+ or an instance of +Time+ representing the same time
 | 
			
		||||
  # in the local system timezone depending on the setting of
 | 
			
		||||
  # on the setting of +ActiveSupport.to_time_preserves_timezone+.
 | 
			
		||||
  def to_time
 | 
			
		||||
    preserve_timezone ? getlocal(utc_offset) : getlocal
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,106 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
require "active_support/inflector/methods"
 | 
			
		||||
require "active_support/core_ext/time/conversions"
 | 
			
		||||
require "active_support/core_ext/date_time/calculations"
 | 
			
		||||
require "active_support/values/time_zone"
 | 
			
		||||
 | 
			
		||||
class DateTime
 | 
			
		||||
  # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
 | 
			
		||||
  #
 | 
			
		||||
  # This method is aliased to <tt>to_s</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  # === Examples
 | 
			
		||||
  #   datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0)   # => Tue, 04 Dec 2007 00:00:00 +0000
 | 
			
		||||
  #
 | 
			
		||||
  #   datetime.to_formatted_s(:db)            # => "2007-12-04 00:00:00"
 | 
			
		||||
  #   datetime.to_s(:db)                      # => "2007-12-04 00:00:00"
 | 
			
		||||
  #   datetime.to_s(:number)                  # => "20071204000000"
 | 
			
		||||
  #   datetime.to_formatted_s(:short)         # => "04 Dec 00:00"
 | 
			
		||||
  #   datetime.to_formatted_s(:long)          # => "December 04, 2007 00:00"
 | 
			
		||||
  #   datetime.to_formatted_s(:long_ordinal)  # => "December 4th, 2007 00:00"
 | 
			
		||||
  #   datetime.to_formatted_s(:rfc822)        # => "Tue, 04 Dec 2007 00:00:00 +0000"
 | 
			
		||||
  #   datetime.to_formatted_s(:iso8601)       # => "2007-12-04T00:00:00+00:00"
 | 
			
		||||
  #
 | 
			
		||||
  # == Adding your own datetime formats to to_formatted_s
 | 
			
		||||
  # DateTime formats are shared with Time. You can add your own to the
 | 
			
		||||
  # Time::DATE_FORMATS hash. Use the format name as the hash key and
 | 
			
		||||
  # either a strftime string or Proc instance that takes a time or
 | 
			
		||||
  # datetime argument as the value.
 | 
			
		||||
  #
 | 
			
		||||
  #   # config/initializers/time_formats.rb
 | 
			
		||||
  #   Time::DATE_FORMATS[:month_and_year] = '%B %Y'
 | 
			
		||||
  #   Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
 | 
			
		||||
  def to_formatted_s(format = :default)
 | 
			
		||||
    if formatter = ::Time::DATE_FORMATS[format]
 | 
			
		||||
      formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
 | 
			
		||||
    else
 | 
			
		||||
      to_default_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
 | 
			
		||||
  alias_method :to_s, :to_formatted_s
 | 
			
		||||
 | 
			
		||||
  # Returns a formatted string of the offset from UTC, or an alternative
 | 
			
		||||
  # string if the time zone is already UTC.
 | 
			
		||||
  #
 | 
			
		||||
  #   datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
 | 
			
		||||
  #   datetime.formatted_offset         # => "-06:00"
 | 
			
		||||
  #   datetime.formatted_offset(false)  # => "-0600"
 | 
			
		||||
  def formatted_offset(colon = true, alternate_utc_string = nil)
 | 
			
		||||
    utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000".
 | 
			
		||||
  def readable_inspect
 | 
			
		||||
    to_s(:rfc822)
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :default_inspect, :inspect
 | 
			
		||||
  alias_method :inspect, :readable_inspect
 | 
			
		||||
 | 
			
		||||
  # Returns DateTime with local offset for given year if format is local else
 | 
			
		||||
  # offset is zero.
 | 
			
		||||
  #
 | 
			
		||||
  #   DateTime.civil_from_format :local, 2012
 | 
			
		||||
  #   # => Sun, 01 Jan 2012 00:00:00 +0300
 | 
			
		||||
  #   DateTime.civil_from_format :local, 2012, 12, 17
 | 
			
		||||
  #   # => Mon, 17 Dec 2012 00:00:00 +0000
 | 
			
		||||
  def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
 | 
			
		||||
    if utc_or_local.to_sym == :local
 | 
			
		||||
      offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
 | 
			
		||||
    else
 | 
			
		||||
      offset = 0
 | 
			
		||||
    end
 | 
			
		||||
    civil(year, month, day, hour, min, sec, offset)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts +self+ to a floating-point number of seconds, including fractional microseconds, since the Unix epoch.
 | 
			
		||||
  def to_f
 | 
			
		||||
    seconds_since_unix_epoch.to_f + sec_fraction
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts +self+ to an integer number of seconds since the Unix epoch.
 | 
			
		||||
  def to_i
 | 
			
		||||
    seconds_since_unix_epoch.to_i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the fraction of a second as microseconds
 | 
			
		||||
  def usec
 | 
			
		||||
    (sec_fraction * 1_000_000).to_i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the fraction of a second as nanoseconds
 | 
			
		||||
  def nsec
 | 
			
		||||
    (sec_fraction * 1_000_000_000).to_i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
    def offset_in_seconds
 | 
			
		||||
      (offset * 86400).to_i
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def seconds_since_unix_epoch
 | 
			
		||||
      (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/digest/uuid"
 | 
			
		||||
@ -1,54 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "securerandom"
 | 
			
		||||
require "digest"
 | 
			
		||||
 | 
			
		||||
module Digest
 | 
			
		||||
  module UUID
 | 
			
		||||
    DNS_NAMESPACE  = "k\xA7\xB8\x10\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
 | 
			
		||||
    URL_NAMESPACE  = "k\xA7\xB8\x11\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
 | 
			
		||||
    OID_NAMESPACE  = "k\xA7\xB8\x12\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
 | 
			
		||||
    X500_NAMESPACE = "k\xA7\xB8\x14\x9D\xAD\x11\xD1\x80\xB4\x00\xC0O\xD40\xC8" #:nodoc:
 | 
			
		||||
 | 
			
		||||
    # Generates a v5 non-random UUID (Universally Unique IDentifier).
 | 
			
		||||
    #
 | 
			
		||||
    # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
 | 
			
		||||
    # uuid_from_hash always generates the same UUID for a given name and namespace combination.
 | 
			
		||||
    #
 | 
			
		||||
    # See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt
 | 
			
		||||
    def self.uuid_from_hash(hash_class, uuid_namespace, name)
 | 
			
		||||
      if hash_class == Digest::MD5
 | 
			
		||||
        version = 3
 | 
			
		||||
      elsif hash_class == Digest::SHA1
 | 
			
		||||
        version = 5
 | 
			
		||||
      else
 | 
			
		||||
        raise ArgumentError, "Expected Digest::SHA1 or Digest::MD5, got #{hash_class.name}."
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      hash = hash_class.new
 | 
			
		||||
      hash.update(uuid_namespace)
 | 
			
		||||
      hash.update(name)
 | 
			
		||||
 | 
			
		||||
      ary = hash.digest.unpack("NnnnnN")
 | 
			
		||||
      ary[2] = (ary[2] & 0x0FFF) | (version << 12)
 | 
			
		||||
      ary[3] = (ary[3] & 0x3FFF) | 0x8000
 | 
			
		||||
 | 
			
		||||
      "%08x-%04x-%04x-%04x-%04x%08x" % ary
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Convenience method for uuid_from_hash using Digest::MD5.
 | 
			
		||||
    def self.uuid_v3(uuid_namespace, name)
 | 
			
		||||
      uuid_from_hash(Digest::MD5, uuid_namespace, name)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Convenience method for uuid_from_hash using Digest::SHA1.
 | 
			
		||||
    def self.uuid_v5(uuid_namespace, name)
 | 
			
		||||
      uuid_from_hash(Digest::SHA1, uuid_namespace, name)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Convenience method for SecureRandom.uuid.
 | 
			
		||||
    def self.uuid_v4
 | 
			
		||||
      SecureRandom.uuid
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/file/atomic"
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/hash/conversions"
 | 
			
		||||
require "active_support/core_ext/hash/deep_merge"
 | 
			
		||||
require "active_support/core_ext/hash/deep_transform_values"
 | 
			
		||||
require "active_support/core_ext/hash/except"
 | 
			
		||||
require "active_support/core_ext/hash/indifferent_access"
 | 
			
		||||
require "active_support/core_ext/hash/keys"
 | 
			
		||||
require "active_support/core_ext/hash/reverse_merge"
 | 
			
		||||
require "active_support/core_ext/hash/slice"
 | 
			
		||||
@ -1,263 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/xml_mini"
 | 
			
		||||
require "active_support/core_ext/object/blank"
 | 
			
		||||
require "active_support/core_ext/object/to_param"
 | 
			
		||||
require "active_support/core_ext/object/to_query"
 | 
			
		||||
require "active_support/core_ext/object/try"
 | 
			
		||||
require "active_support/core_ext/array/wrap"
 | 
			
		||||
require "active_support/core_ext/hash/reverse_merge"
 | 
			
		||||
require "active_support/core_ext/string/inflections"
 | 
			
		||||
 | 
			
		||||
class Hash
 | 
			
		||||
  # Returns a string containing an XML representation of its receiver:
 | 
			
		||||
  #
 | 
			
		||||
  #   { foo: 1, bar: 2 }.to_xml
 | 
			
		||||
  #   # =>
 | 
			
		||||
  #   # <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
  #   # <hash>
 | 
			
		||||
  #   #   <foo type="integer">1</foo>
 | 
			
		||||
  #   #   <bar type="integer">2</bar>
 | 
			
		||||
  #   # </hash>
 | 
			
		||||
  #
 | 
			
		||||
  # To do so, the method loops over the pairs and builds nodes that depend on
 | 
			
		||||
  # the _values_. Given a pair +key+, +value+:
 | 
			
		||||
  #
 | 
			
		||||
  # * If +value+ is a hash there's a recursive call with +key+ as <tt>:root</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  # * If +value+ is an array there's a recursive call with +key+ as <tt>:root</tt>,
 | 
			
		||||
  #   and +key+ singularized as <tt>:children</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  # * If +value+ is a callable object it must expect one or two arguments. Depending
 | 
			
		||||
  #   on the arity, the callable is invoked with the +options+ hash as first argument
 | 
			
		||||
  #   with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The
 | 
			
		||||
  #   callable can add nodes by using <tt>options[:builder]</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #     {foo: lambda { |options, key| options[:builder].b(key) }}.to_xml
 | 
			
		||||
  #     # => "<b>foo</b>"
 | 
			
		||||
  #
 | 
			
		||||
  # * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #     class Foo
 | 
			
		||||
  #       def to_xml(options)
 | 
			
		||||
  #         options[:builder].bar 'fooing!'
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  #     { foo: Foo.new }.to_xml(skip_instruct: true)
 | 
			
		||||
  #     # =>
 | 
			
		||||
  #     # <hash>
 | 
			
		||||
  #     #   <bar>fooing!</bar>
 | 
			
		||||
  #     # </hash>
 | 
			
		||||
  #
 | 
			
		||||
  # * Otherwise, a node with +key+ as tag is created with a string representation of
 | 
			
		||||
  #   +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
 | 
			
		||||
  #   Unless the option <tt>:skip_types</tt> exists and is true, an attribute "type" is
 | 
			
		||||
  #   added as well according to the following mapping:
 | 
			
		||||
  #
 | 
			
		||||
  #     XML_TYPE_NAMES = {
 | 
			
		||||
  #       "Symbol"     => "symbol",
 | 
			
		||||
  #       "Integer"    => "integer",
 | 
			
		||||
  #       "BigDecimal" => "decimal",
 | 
			
		||||
  #       "Float"      => "float",
 | 
			
		||||
  #       "TrueClass"  => "boolean",
 | 
			
		||||
  #       "FalseClass" => "boolean",
 | 
			
		||||
  #       "Date"       => "date",
 | 
			
		||||
  #       "DateTime"   => "dateTime",
 | 
			
		||||
  #       "Time"       => "dateTime"
 | 
			
		||||
  #     }
 | 
			
		||||
  #
 | 
			
		||||
  # By default the root node is "hash", but that's configurable via the <tt>:root</tt> option.
 | 
			
		||||
  #
 | 
			
		||||
  # The default XML builder is a fresh instance of <tt>Builder::XmlMarkup</tt>. You can
 | 
			
		||||
  # configure your own builder with the <tt>:builder</tt> option. The method also accepts
 | 
			
		||||
  # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
 | 
			
		||||
  def to_xml(options = {})
 | 
			
		||||
    require "active_support/builder" unless defined?(Builder::XmlMarkup)
 | 
			
		||||
 | 
			
		||||
    options = options.dup
 | 
			
		||||
    options[:indent]  ||= 2
 | 
			
		||||
    options[:root]    ||= "hash"
 | 
			
		||||
    options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
 | 
			
		||||
 | 
			
		||||
    builder = options[:builder]
 | 
			
		||||
    builder.instruct! unless options.delete(:skip_instruct)
 | 
			
		||||
 | 
			
		||||
    root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
 | 
			
		||||
 | 
			
		||||
    builder.tag!(root) do
 | 
			
		||||
      each { |key, value| ActiveSupport::XmlMini.to_tag(key, value, options) }
 | 
			
		||||
      yield builder if block_given?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    # Returns a Hash containing a collection of pairs when the key is the node name and the value is
 | 
			
		||||
    # its content
 | 
			
		||||
    #
 | 
			
		||||
    #   xml = <<-XML
 | 
			
		||||
    #     <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
    #       <hash>
 | 
			
		||||
    #         <foo type="integer">1</foo>
 | 
			
		||||
    #         <bar type="integer">2</bar>
 | 
			
		||||
    #       </hash>
 | 
			
		||||
    #   XML
 | 
			
		||||
    #
 | 
			
		||||
    #   hash = Hash.from_xml(xml)
 | 
			
		||||
    #   # => {"hash"=>{"foo"=>1, "bar"=>2}}
 | 
			
		||||
    #
 | 
			
		||||
    # +DisallowedType+ is raised if the XML contains attributes with <tt>type="yaml"</tt> or
 | 
			
		||||
    # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to
 | 
			
		||||
    # parse this XML.
 | 
			
		||||
    #
 | 
			
		||||
    # Custom +disallowed_types+ can also be passed in the form of an
 | 
			
		||||
    # array.
 | 
			
		||||
    #
 | 
			
		||||
    #   xml = <<-XML
 | 
			
		||||
    #     <?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
    #       <hash>
 | 
			
		||||
    #         <foo type="integer">1</foo>
 | 
			
		||||
    #         <bar type="string">"David"</bar>
 | 
			
		||||
    #       </hash>
 | 
			
		||||
    #   XML
 | 
			
		||||
    #
 | 
			
		||||
    #   hash = Hash.from_xml(xml, ['integer'])
 | 
			
		||||
    #   # => ActiveSupport::XMLConverter::DisallowedType: Disallowed type attribute: "integer"
 | 
			
		||||
    #
 | 
			
		||||
    # Note that passing custom disallowed types will override the default types,
 | 
			
		||||
    # which are Symbol and YAML.
 | 
			
		||||
    def from_xml(xml, disallowed_types = nil)
 | 
			
		||||
      ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Builds a Hash from XML just like <tt>Hash.from_xml</tt>, but also allows Symbol and YAML.
 | 
			
		||||
    def from_trusted_xml(xml)
 | 
			
		||||
      from_xml xml, []
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  class XMLConverter # :nodoc:
 | 
			
		||||
    # Raised if the XML contains attributes with type="yaml" or
 | 
			
		||||
    # type="symbol". Read Hash#from_xml for more details.
 | 
			
		||||
    class DisallowedType < StandardError
 | 
			
		||||
      def initialize(type)
 | 
			
		||||
        super "Disallowed type attribute: #{type.inspect}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    DISALLOWED_TYPES = %w(symbol yaml)
 | 
			
		||||
 | 
			
		||||
    def initialize(xml, disallowed_types = nil)
 | 
			
		||||
      @xml = normalize_keys(XmlMini.parse(xml))
 | 
			
		||||
      @disallowed_types = disallowed_types || DISALLOWED_TYPES
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_h
 | 
			
		||||
      deep_to_h(@xml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def normalize_keys(params)
 | 
			
		||||
        case params
 | 
			
		||||
        when Hash
 | 
			
		||||
          Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
 | 
			
		||||
        when Array
 | 
			
		||||
          params.map { |v| normalize_keys(v) }
 | 
			
		||||
        else
 | 
			
		||||
          params
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def deep_to_h(value)
 | 
			
		||||
        case value
 | 
			
		||||
        when Hash
 | 
			
		||||
          process_hash(value)
 | 
			
		||||
        when Array
 | 
			
		||||
          process_array(value)
 | 
			
		||||
        when String
 | 
			
		||||
          value
 | 
			
		||||
        else
 | 
			
		||||
          raise "can't typecast #{value.class.name} - #{value.inspect}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def process_hash(value)
 | 
			
		||||
        if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
 | 
			
		||||
          raise DisallowedType, value["type"]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if become_array?(value)
 | 
			
		||||
          _, entries = Array.wrap(value.detect { |k, v| not v.is_a?(String) })
 | 
			
		||||
          if entries.nil? || value["__content__"].try(:empty?)
 | 
			
		||||
            []
 | 
			
		||||
          else
 | 
			
		||||
            case entries
 | 
			
		||||
            when Array
 | 
			
		||||
              entries.collect { |v| deep_to_h(v) }
 | 
			
		||||
            when Hash
 | 
			
		||||
              [deep_to_h(entries)]
 | 
			
		||||
            else
 | 
			
		||||
              raise "can't typecast #{entries.inspect}"
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        elsif become_content?(value)
 | 
			
		||||
          process_content(value)
 | 
			
		||||
 | 
			
		||||
        elsif become_empty_string?(value)
 | 
			
		||||
          ""
 | 
			
		||||
        elsif become_hash?(value)
 | 
			
		||||
          xml_value = value.transform_values { |v| deep_to_h(v) }
 | 
			
		||||
 | 
			
		||||
          # Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
 | 
			
		||||
          # how multipart uploaded files from HTML appear
 | 
			
		||||
          xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def become_content?(value)
 | 
			
		||||
        value["type"] == "file" || (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def become_array?(value)
 | 
			
		||||
        value["type"] == "array"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def become_empty_string?(value)
 | 
			
		||||
        # { "string" => true }
 | 
			
		||||
        # No tests fail when the second term is removed.
 | 
			
		||||
        value["type"] == "string" && value["nil"] != "true"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def become_hash?(value)
 | 
			
		||||
        !nothing?(value) && !garbage?(value)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def nothing?(value)
 | 
			
		||||
        # blank or nil parsed values are represented by nil
 | 
			
		||||
        value.blank? || value["nil"] == "true"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def garbage?(value)
 | 
			
		||||
        # If the type is the only element which makes it then
 | 
			
		||||
        # this still makes the value nil, except if type is
 | 
			
		||||
        # an XML node(where type['value'] is a Hash)
 | 
			
		||||
        value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def process_content(value)
 | 
			
		||||
        content = value["__content__"]
 | 
			
		||||
        if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
 | 
			
		||||
          parser.arity == 1 ? parser.call(content) : parser.call(content, value)
 | 
			
		||||
        else
 | 
			
		||||
          content
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def process_array(value)
 | 
			
		||||
        value.map! { |i| deep_to_h(i) }
 | 
			
		||||
        value.length > 1 ? value : value.first
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/hash_with_indifferent_access"
 | 
			
		||||
 | 
			
		||||
class Hash
 | 
			
		||||
  # Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
 | 
			
		||||
  #
 | 
			
		||||
  #   { a: 1 }.with_indifferent_access['a'] # => 1
 | 
			
		||||
  def with_indifferent_access
 | 
			
		||||
    ActiveSupport::HashWithIndifferentAccess.new(self)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Called when object is nested under an object that receives
 | 
			
		||||
  # #with_indifferent_access. This method will be called on the current object
 | 
			
		||||
  # by the enclosing object and is aliased to #with_indifferent_access by
 | 
			
		||||
  # default. Subclasses of Hash may overwrite this method to return +self+ if
 | 
			
		||||
  # converting to an <tt>ActiveSupport::HashWithIndifferentAccess</tt> would not be
 | 
			
		||||
  # desirable.
 | 
			
		||||
  #
 | 
			
		||||
  #   b = { b: 1 }
 | 
			
		||||
  #   { a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
 | 
			
		||||
  #   # => {"b"=>1}
 | 
			
		||||
  alias nested_under_indifferent_access with_indifferent_access
 | 
			
		||||
end
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Hash
 | 
			
		||||
  # Merges the caller into +other_hash+. For example,
 | 
			
		||||
  #
 | 
			
		||||
  #   options = options.reverse_merge(size: 25, velocity: 10)
 | 
			
		||||
  #
 | 
			
		||||
  # is equivalent to
 | 
			
		||||
  #
 | 
			
		||||
  #   options = { size: 25, velocity: 10 }.merge(options)
 | 
			
		||||
  #
 | 
			
		||||
  # This is particularly useful for initializing an options hash
 | 
			
		||||
  # with default values.
 | 
			
		||||
  def reverse_merge(other_hash)
 | 
			
		||||
    other_hash.merge(self)
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :with_defaults, :reverse_merge
 | 
			
		||||
 | 
			
		||||
  # Destructive +reverse_merge+.
 | 
			
		||||
  def reverse_merge!(other_hash)
 | 
			
		||||
    replace(reverse_merge(other_hash))
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :reverse_update, :reverse_merge!
 | 
			
		||||
  alias_method :with_defaults!, :reverse_merge!
 | 
			
		||||
end
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/integer/multiple"
 | 
			
		||||
require "active_support/core_ext/integer/inflections"
 | 
			
		||||
require "active_support/core_ext/integer/time"
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/inflector"
 | 
			
		||||
 | 
			
		||||
class Integer
 | 
			
		||||
  # Ordinalize turns a number into an ordinal string used to denote the
 | 
			
		||||
  # position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
 | 
			
		||||
  #
 | 
			
		||||
  #  1.ordinalize     # => "1st"
 | 
			
		||||
  #  2.ordinalize     # => "2nd"
 | 
			
		||||
  #  1002.ordinalize  # => "1002nd"
 | 
			
		||||
  #  1003.ordinalize  # => "1003rd"
 | 
			
		||||
  #  -11.ordinalize   # => "-11th"
 | 
			
		||||
  #  -1001.ordinalize # => "-1001st"
 | 
			
		||||
  def ordinalize
 | 
			
		||||
    ActiveSupport::Inflector.ordinalize(self)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Ordinal returns the suffix used to denote the position
 | 
			
		||||
  # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
 | 
			
		||||
  #
 | 
			
		||||
  #  1.ordinal     # => "st"
 | 
			
		||||
  #  2.ordinal     # => "nd"
 | 
			
		||||
  #  1002.ordinal  # => "nd"
 | 
			
		||||
  #  1003.ordinal  # => "rd"
 | 
			
		||||
  #  -11.ordinal   # => "th"
 | 
			
		||||
  #  -1001.ordinal # => "st"
 | 
			
		||||
  def ordinal
 | 
			
		||||
    ActiveSupport::Inflector.ordinal(self)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,12 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Integer
 | 
			
		||||
  # Check whether the integer is evenly divisible by the argument.
 | 
			
		||||
  #
 | 
			
		||||
  #   0.multiple_of?(0)  # => true
 | 
			
		||||
  #   6.multiple_of?(5)  # => false
 | 
			
		||||
  #   10.multiple_of?(2) # => true
 | 
			
		||||
  def multiple_of?(number)
 | 
			
		||||
    number == 0 ? self == 0 : self % number == 0
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/duration"
 | 
			
		||||
require "active_support/core_ext/numeric/time"
 | 
			
		||||
 | 
			
		||||
class Integer
 | 
			
		||||
  # Returns a Duration instance matching the number of months provided.
 | 
			
		||||
  #
 | 
			
		||||
  #   2.months # => 2 months
 | 
			
		||||
  def months
 | 
			
		||||
    ActiveSupport::Duration.months(self)
 | 
			
		||||
  end
 | 
			
		||||
  alias :month :months
 | 
			
		||||
 | 
			
		||||
  # Returns a Duration instance matching the number of years provided.
 | 
			
		||||
  #
 | 
			
		||||
  #   2.years # => 2 years
 | 
			
		||||
  def years
 | 
			
		||||
    ActiveSupport::Duration.years(self)
 | 
			
		||||
  end
 | 
			
		||||
  alias :year :years
 | 
			
		||||
end
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/kernel/concern"
 | 
			
		||||
require "active_support/core_ext/kernel/reporting"
 | 
			
		||||
require "active_support/core_ext/kernel/singleton_class"
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/module/concerning"
 | 
			
		||||
 | 
			
		||||
module Kernel
 | 
			
		||||
  module_function
 | 
			
		||||
 | 
			
		||||
  # A shortcut to define a toplevel concern, not within a module.
 | 
			
		||||
  #
 | 
			
		||||
  # See Module::Concerning for more.
 | 
			
		||||
  def concern(topic, &module_definition)
 | 
			
		||||
    Object.concern topic, &module_definition
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module Kernel
 | 
			
		||||
  # class_eval on an object acts like singleton_class.class_eval.
 | 
			
		||||
  def class_eval(*args, &block)
 | 
			
		||||
    singleton_class.class_eval(*args, &block)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class LoadError
 | 
			
		||||
  # Returns true if the given path name (except perhaps for the ".rb"
 | 
			
		||||
  # extension) is the missing file which caused the exception to be raised.
 | 
			
		||||
  def is_missing?(location)
 | 
			
		||||
    location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/string/inflections"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module MarshalWithAutoloading # :nodoc:
 | 
			
		||||
    def load(source, proc = nil)
 | 
			
		||||
      super(source, proc)
 | 
			
		||||
    rescue ArgumentError, NameError => exc
 | 
			
		||||
      if exc.message.match(%r|undefined class/module (.+?)(?:::)?\z|)
 | 
			
		||||
        # try loading the class/module
 | 
			
		||||
        loaded = $1.constantize
 | 
			
		||||
 | 
			
		||||
        raise unless $1 == loaded.name
 | 
			
		||||
 | 
			
		||||
        # if it is an IO we need to go back to read the object
 | 
			
		||||
        source.rewind if source.respond_to?(:rewind)
 | 
			
		||||
        retry
 | 
			
		||||
      else
 | 
			
		||||
        raise exc
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Marshal.singleton_class.prepend(ActiveSupport::MarshalWithAutoloading)
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/module/aliasing"
 | 
			
		||||
require "active_support/core_ext/module/introspection"
 | 
			
		||||
require "active_support/core_ext/module/anonymous"
 | 
			
		||||
require "active_support/core_ext/module/attribute_accessors"
 | 
			
		||||
require "active_support/core_ext/module/attribute_accessors_per_thread"
 | 
			
		||||
require "active_support/core_ext/module/attr_internal"
 | 
			
		||||
require "active_support/core_ext/module/concerning"
 | 
			
		||||
require "active_support/core_ext/module/delegation"
 | 
			
		||||
require "active_support/core_ext/module/deprecation"
 | 
			
		||||
require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
require "active_support/core_ext/module/remove_method"
 | 
			
		||||
@ -1,65 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class NameError
 | 
			
		||||
  # Extract the name of the missing constant from the exception message.
 | 
			
		||||
  #
 | 
			
		||||
  #   begin
 | 
			
		||||
  #     HelloWorld
 | 
			
		||||
  #   rescue NameError => e
 | 
			
		||||
  #     e.missing_name
 | 
			
		||||
  #   end
 | 
			
		||||
  #   # => "HelloWorld"
 | 
			
		||||
  def missing_name
 | 
			
		||||
    # Since ruby v2.3.0 `did_you_mean` gem is loaded by default.
 | 
			
		||||
    # It extends NameError#message with spell corrections which are SLOW.
 | 
			
		||||
    # We should use original_message message instead.
 | 
			
		||||
    message = respond_to?(:original_message) ? original_message : self.message
 | 
			
		||||
    return unless message.start_with?("uninitialized constant ")
 | 
			
		||||
 | 
			
		||||
    receiver = begin
 | 
			
		||||
      self.receiver
 | 
			
		||||
    rescue ArgumentError
 | 
			
		||||
      nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if receiver == Object
 | 
			
		||||
      name.to_s
 | 
			
		||||
    elsif receiver
 | 
			
		||||
      "#{real_mod_name(receiver)}::#{self.name}"
 | 
			
		||||
    else
 | 
			
		||||
      if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
 | 
			
		||||
        match[1]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Was this exception raised because the given name was missing?
 | 
			
		||||
  #
 | 
			
		||||
  #   begin
 | 
			
		||||
  #     HelloWorld
 | 
			
		||||
  #   rescue NameError => e
 | 
			
		||||
  #     e.missing_name?("HelloWorld")
 | 
			
		||||
  #   end
 | 
			
		||||
  #   # => true
 | 
			
		||||
  def missing_name?(name)
 | 
			
		||||
    if name.is_a? Symbol
 | 
			
		||||
      self.name == name
 | 
			
		||||
    else
 | 
			
		||||
      missing_name == name.to_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
    UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
 | 
			
		||||
    private_constant :UNBOUND_METHOD_MODULE_NAME
 | 
			
		||||
 | 
			
		||||
    if UnboundMethod.method_defined?(:bind_call)
 | 
			
		||||
      def real_mod_name(mod)
 | 
			
		||||
        UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
 | 
			
		||||
      end
 | 
			
		||||
    else
 | 
			
		||||
      def real_mod_name(mod)
 | 
			
		||||
        UNBOUND_METHOD_MODULE_NAME.bind(mod).call
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/numeric/bytes"
 | 
			
		||||
require "active_support/core_ext/numeric/time"
 | 
			
		||||
require "active_support/core_ext/numeric/conversions"
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/acts_like"
 | 
			
		||||
require "active_support/core_ext/object/blank"
 | 
			
		||||
require "active_support/core_ext/object/duplicable"
 | 
			
		||||
require "active_support/core_ext/object/deep_dup"
 | 
			
		||||
require "active_support/core_ext/object/try"
 | 
			
		||||
require "active_support/core_ext/object/inclusion"
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/conversions"
 | 
			
		||||
require "active_support/core_ext/object/instance_variables"
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/json"
 | 
			
		||||
require "active_support/core_ext/object/to_param"
 | 
			
		||||
require "active_support/core_ext/object/to_query"
 | 
			
		||||
require "active_support/core_ext/object/with_options"
 | 
			
		||||
@ -1,21 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  # A duck-type assistant method. For example, Active Support extends Date
 | 
			
		||||
  # to define an <tt>acts_like_date?</tt> method, and extends Time to define
 | 
			
		||||
  # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and
 | 
			
		||||
  # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that
 | 
			
		||||
  # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method.
 | 
			
		||||
  def acts_like?(duck)
 | 
			
		||||
    case duck
 | 
			
		||||
    when :time
 | 
			
		||||
      respond_to? :acts_like_time?
 | 
			
		||||
    when :date
 | 
			
		||||
      respond_to? :acts_like_date?
 | 
			
		||||
    when :string
 | 
			
		||||
      respond_to? :acts_like_string?
 | 
			
		||||
    else
 | 
			
		||||
      respond_to? :"acts_like_#{duck}?"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/to_param"
 | 
			
		||||
require "active_support/core_ext/object/to_query"
 | 
			
		||||
require "active_support/core_ext/array/conversions"
 | 
			
		||||
require "active_support/core_ext/hash/conversions"
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  # Returns true if this object is included in the argument. Argument must be
 | 
			
		||||
  # any object which responds to +#include?+. Usage:
 | 
			
		||||
  #
 | 
			
		||||
  #   characters = ["Konata", "Kagami", "Tsukasa"]
 | 
			
		||||
  #   "Konata".in?(characters) # => true
 | 
			
		||||
  #
 | 
			
		||||
  # This will throw an +ArgumentError+ if the argument doesn't respond
 | 
			
		||||
  # to +#include?+.
 | 
			
		||||
  def in?(another_object)
 | 
			
		||||
    another_object.include?(self)
 | 
			
		||||
  rescue NoMethodError
 | 
			
		||||
    raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the receiver if it's included in the argument otherwise returns +nil+.
 | 
			
		||||
  # Argument must be any object which responds to +#include?+. Usage:
 | 
			
		||||
  #
 | 
			
		||||
  #   params[:bucket_type].presence_in %w( project calendar )
 | 
			
		||||
  #
 | 
			
		||||
  # This will throw an +ArgumentError+ if the argument doesn't respond to +#include?+.
 | 
			
		||||
  #
 | 
			
		||||
  # @return [Object]
 | 
			
		||||
  def presence_in(another_object)
 | 
			
		||||
    in?(another_object) ? self : nil
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  # Returns a hash with string keys that maps instance variable names without "@" to their
 | 
			
		||||
  # corresponding values.
 | 
			
		||||
  #
 | 
			
		||||
  #   class C
 | 
			
		||||
  #     def initialize(x, y)
 | 
			
		||||
  #       @x, @y = x, y
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
 | 
			
		||||
  def instance_values
 | 
			
		||||
    Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns an array of instance variable names as strings including "@".
 | 
			
		||||
  #
 | 
			
		||||
  #   class C
 | 
			
		||||
  #     def initialize(x, y)
 | 
			
		||||
  #       @x, @y = x, y
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   C.new(0, 1).instance_variable_names # => ["@y", "@x"]
 | 
			
		||||
  def instance_variable_names
 | 
			
		||||
    instance_variables.map(&:to_s)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,239 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
# Hack to load json gem first so we can overwrite its to_json.
 | 
			
		||||
require "json"
 | 
			
		||||
require "bigdecimal"
 | 
			
		||||
require "ipaddr"
 | 
			
		||||
require "uri/generic"
 | 
			
		||||
require "pathname"
 | 
			
		||||
require "active_support/core_ext/big_decimal/conversions" # for #to_s
 | 
			
		||||
require "active_support/core_ext/hash/except"
 | 
			
		||||
require "active_support/core_ext/hash/slice"
 | 
			
		||||
require "active_support/core_ext/object/instance_variables"
 | 
			
		||||
require "time"
 | 
			
		||||
require "active_support/core_ext/time/conversions"
 | 
			
		||||
require "active_support/core_ext/date_time/conversions"
 | 
			
		||||
require "active_support/core_ext/date/conversions"
 | 
			
		||||
 | 
			
		||||
#--
 | 
			
		||||
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
 | 
			
		||||
# their default behavior. That said, we need to define the basic to_json method in all of them,
 | 
			
		||||
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
 | 
			
		||||
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
 | 
			
		||||
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
 | 
			
		||||
#
 | 
			
		||||
# On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
 | 
			
		||||
# JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
 | 
			
		||||
# passes a ::JSON::State object as the only argument to to_json, we can detect that and forward the
 | 
			
		||||
# calls to the original to_json method.
 | 
			
		||||
#
 | 
			
		||||
# It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
 | 
			
		||||
# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
 | 
			
		||||
# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
 | 
			
		||||
# should give exactly the same results with or without active support.
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module ToJsonWithActiveSupportEncoder # :nodoc:
 | 
			
		||||
    def to_json(options = nil)
 | 
			
		||||
      if options.is_a?(::JSON::State)
 | 
			
		||||
        # Called from JSON.{generate,dump}, forward it to JSON gem's to_json
 | 
			
		||||
        super(options)
 | 
			
		||||
      else
 | 
			
		||||
        # to_json is being invoked directly, use ActiveSupport's encoder
 | 
			
		||||
        ActiveSupport::JSON.encode(self, options)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
[Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass|
 | 
			
		||||
  klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    if respond_to?(:to_hash)
 | 
			
		||||
      to_hash.as_json(options)
 | 
			
		||||
    else
 | 
			
		||||
      instance_values.as_json(options)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Struct #:nodoc:
 | 
			
		||||
  def as_json(options = nil)
 | 
			
		||||
    Hash[members.zip(values)].as_json(options)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class TrueClass
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class FalseClass
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class NilClass
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Symbol
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Numeric
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Float
 | 
			
		||||
  # Encoding Infinity or NaN to JSON should return "null". The default returns
 | 
			
		||||
  # "Infinity" or "NaN" which are not valid JSON.
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    finite? ? self : nil
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class BigDecimal
 | 
			
		||||
  # A BigDecimal would be naturally represented as a JSON number. Most libraries,
 | 
			
		||||
  # however, parse non-integer JSON numbers directly as floats. Clients using
 | 
			
		||||
  # those libraries would get in general a wrong number and no way to recover
 | 
			
		||||
  # other than manually inspecting the string with the JSON code itself.
 | 
			
		||||
  #
 | 
			
		||||
  # That's why a JSON string is returned. The JSON literal is not numeric, but
 | 
			
		||||
  # if the other end knows by contract that the data is supposed to be a
 | 
			
		||||
  # BigDecimal, it still has the chance to post-process the string and get the
 | 
			
		||||
  # real value.
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    finite? ? to_s : nil
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Regexp
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module Enumerable
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    to_a.as_json(options)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class IO
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Range
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    map { |v| options ? v.as_json(options.dup) : v.as_json }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Hash
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    # create a subset of the hash by applying :only or :except
 | 
			
		||||
    subset = if options
 | 
			
		||||
      if attrs = options[:only]
 | 
			
		||||
        slice(*Array(attrs))
 | 
			
		||||
      elsif attrs = options[:except]
 | 
			
		||||
        except(*Array(attrs))
 | 
			
		||||
      else
 | 
			
		||||
        self
 | 
			
		||||
      end
 | 
			
		||||
    else
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    result = {}
 | 
			
		||||
    subset.each do |k, v|
 | 
			
		||||
      result[k.to_s] = options ? v.as_json(options.dup) : v.as_json
 | 
			
		||||
    end
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    if ActiveSupport::JSON::Encoding.use_standard_json_time_format
 | 
			
		||||
      xmlschema(ActiveSupport::JSON::Encoding.time_precision)
 | 
			
		||||
    else
 | 
			
		||||
      %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Date
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    if ActiveSupport::JSON::Encoding.use_standard_json_time_format
 | 
			
		||||
      strftime("%Y-%m-%d")
 | 
			
		||||
    else
 | 
			
		||||
      strftime("%Y/%m/%d")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class DateTime
 | 
			
		||||
  def as_json(options = nil) #:nodoc:
 | 
			
		||||
    if ActiveSupport::JSON::Encoding.use_standard_json_time_format
 | 
			
		||||
      xmlschema(ActiveSupport::JSON::Encoding.time_precision)
 | 
			
		||||
    else
 | 
			
		||||
      strftime("%Y/%m/%d %H:%M:%S %z")
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class URI::Generic #:nodoc:
 | 
			
		||||
  def as_json(options = nil)
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Pathname #:nodoc:
 | 
			
		||||
  def as_json(options = nil)
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class IPAddr # :nodoc:
 | 
			
		||||
  def as_json(options = nil)
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Process::Status #:nodoc:
 | 
			
		||||
  def as_json(options = nil)
 | 
			
		||||
    { exitstatus: exitstatus, pid: pid }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Exception
 | 
			
		||||
  def as_json(options = nil)
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/to_query"
 | 
			
		||||
@ -1,89 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "cgi"
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  # Alias of <tt>to_s</tt>.
 | 
			
		||||
  def to_param
 | 
			
		||||
    to_s
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts an object into a string suitable for use as a URL query string,
 | 
			
		||||
  # using the given <tt>key</tt> as the param name.
 | 
			
		||||
  def to_query(key)
 | 
			
		||||
    "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class NilClass
 | 
			
		||||
  # Returns +self+.
 | 
			
		||||
  def to_param
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class TrueClass
 | 
			
		||||
  # Returns +self+.
 | 
			
		||||
  def to_param
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class FalseClass
 | 
			
		||||
  # Returns +self+.
 | 
			
		||||
  def to_param
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Array
 | 
			
		||||
  # Calls <tt>to_param</tt> on all its elements and joins the result with
 | 
			
		||||
  # slashes. This is used by <tt>url_for</tt> in Action Pack.
 | 
			
		||||
  def to_param
 | 
			
		||||
    collect(&:to_param).join "/"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts an array into a string suitable for use as a URL query string,
 | 
			
		||||
  # using the given +key+ as the param name.
 | 
			
		||||
  #
 | 
			
		||||
  #   ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
 | 
			
		||||
  def to_query(key)
 | 
			
		||||
    prefix = "#{key}[]"
 | 
			
		||||
 | 
			
		||||
    if empty?
 | 
			
		||||
      nil.to_query(prefix)
 | 
			
		||||
    else
 | 
			
		||||
      collect { |value| value.to_query(prefix) }.join "&"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Hash
 | 
			
		||||
  # Returns a string representation of the receiver suitable for use as a URL
 | 
			
		||||
  # query string:
 | 
			
		||||
  #
 | 
			
		||||
  #   {name: 'David', nationality: 'Danish'}.to_query
 | 
			
		||||
  #   # => "name=David&nationality=Danish"
 | 
			
		||||
  #
 | 
			
		||||
  # An optional namespace can be passed to enclose key names:
 | 
			
		||||
  #
 | 
			
		||||
  #   {name: 'David', nationality: 'Danish'}.to_query('user')
 | 
			
		||||
  #   # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
 | 
			
		||||
  #
 | 
			
		||||
  # The string pairs "key=value" that conform the query string
 | 
			
		||||
  # are sorted lexicographically in ascending order.
 | 
			
		||||
  #
 | 
			
		||||
  # This method is also aliased as +to_param+.
 | 
			
		||||
  def to_query(namespace = nil)
 | 
			
		||||
    query = collect do |key, value|
 | 
			
		||||
      unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
 | 
			
		||||
        value.to_query(namespace ? "#{namespace}[#{key}]" : key)
 | 
			
		||||
      end
 | 
			
		||||
    end.compact
 | 
			
		||||
 | 
			
		||||
    query.sort! unless namespace.to_s.include?("[]")
 | 
			
		||||
    query.join("&")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  alias_method :to_param, :to_query
 | 
			
		||||
end
 | 
			
		||||
@ -1,82 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/option_merger"
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  # An elegant way to factor duplication out of options passed to a series of
 | 
			
		||||
  # method calls. Each method called in the block, with the block variable as
 | 
			
		||||
  # the receiver, will have its options merged with the default +options+ hash
 | 
			
		||||
  # provided. Each method called on the block variable must take an options
 | 
			
		||||
  # hash as its final argument.
 | 
			
		||||
  #
 | 
			
		||||
  # Without <tt>with_options</tt>, this code contains duplication:
 | 
			
		||||
  #
 | 
			
		||||
  #   class Account < ActiveRecord::Base
 | 
			
		||||
  #     has_many :customers, dependent: :destroy
 | 
			
		||||
  #     has_many :products,  dependent: :destroy
 | 
			
		||||
  #     has_many :invoices,  dependent: :destroy
 | 
			
		||||
  #     has_many :expenses,  dependent: :destroy
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # Using <tt>with_options</tt>, we can remove the duplication:
 | 
			
		||||
  #
 | 
			
		||||
  #   class Account < ActiveRecord::Base
 | 
			
		||||
  #     with_options dependent: :destroy do |assoc|
 | 
			
		||||
  #       assoc.has_many :customers
 | 
			
		||||
  #       assoc.has_many :products
 | 
			
		||||
  #       assoc.has_many :invoices
 | 
			
		||||
  #       assoc.has_many :expenses
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # It can also be used with an explicit receiver:
 | 
			
		||||
  #
 | 
			
		||||
  #   I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
 | 
			
		||||
  #     subject i18n.t :subject
 | 
			
		||||
  #     body    i18n.t :body, user_name: user.name
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # When you don't pass an explicit receiver, it executes the whole block
 | 
			
		||||
  # in merging options context:
 | 
			
		||||
  #
 | 
			
		||||
  #   class Account < ActiveRecord::Base
 | 
			
		||||
  #     with_options dependent: :destroy do
 | 
			
		||||
  #       has_many :customers
 | 
			
		||||
  #       has_many :products
 | 
			
		||||
  #       has_many :invoices
 | 
			
		||||
  #       has_many :expenses
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
 | 
			
		||||
  #
 | 
			
		||||
  # NOTE: Each nesting level will merge inherited defaults in addition to their own.
 | 
			
		||||
  #
 | 
			
		||||
  #   class Post < ActiveRecord::Base
 | 
			
		||||
  #     with_options if: :persisted?, length: { minimum: 50 } do
 | 
			
		||||
  #       validates :content, if: -> { content.present? }
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # The code is equivalent to:
 | 
			
		||||
  #
 | 
			
		||||
  #   validates :content, length: { minimum: 50 }, if: -> { content.present? }
 | 
			
		||||
  #
 | 
			
		||||
  # Hence the inherited default for +if+ key is ignored.
 | 
			
		||||
  #
 | 
			
		||||
  # NOTE: You cannot call class methods implicitly inside of with_options.
 | 
			
		||||
  # You can access these methods using the class name instead:
 | 
			
		||||
  #
 | 
			
		||||
  #   class Phone < ActiveRecord::Base
 | 
			
		||||
  #     enum phone_number_type: { home: 0, office: 1, mobile: 2 }
 | 
			
		||||
  #
 | 
			
		||||
  #     with_options presence: true do
 | 
			
		||||
  #       validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  def with_options(options, &block)
 | 
			
		||||
    option_merger = ActiveSupport::OptionMerger.new(self, options)
 | 
			
		||||
    block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/range/conversions"
 | 
			
		||||
require "active_support/core_ext/range/compare_range"
 | 
			
		||||
require "active_support/core_ext/range/include_time_with_zone"
 | 
			
		||||
require "active_support/core_ext/range/overlaps"
 | 
			
		||||
require "active_support/core_ext/range/each"
 | 
			
		||||
@ -1,82 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module CompareWithRange
 | 
			
		||||
    # Extends the default Range#=== to support range comparisons.
 | 
			
		||||
    #  (1..5) === (1..5)  # => true
 | 
			
		||||
    #  (1..5) === (2..3)  # => true
 | 
			
		||||
    #  (1..5) === (1...6) # => true
 | 
			
		||||
    #  (1..5) === (2..6)  # => false
 | 
			
		||||
    #
 | 
			
		||||
    # The native Range#=== behavior is untouched.
 | 
			
		||||
    #  ('a'..'f') === ('c') # => true
 | 
			
		||||
    #  (5..9) === (11) # => false
 | 
			
		||||
    #
 | 
			
		||||
    # The given range must be fully bounded, with both start and end.
 | 
			
		||||
    def ===(value)
 | 
			
		||||
      if value.is_a?(::Range)
 | 
			
		||||
        is_backwards_op = value.exclude_end? ? :>= : :>
 | 
			
		||||
        return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
 | 
			
		||||
        # 1...10 includes 1..9 but it does not include 1..10.
 | 
			
		||||
        # 1..10 includes 1...11 but it does not include 1...12.
 | 
			
		||||
        operator = exclude_end? && !value.exclude_end? ? :< : :<=
 | 
			
		||||
        value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
 | 
			
		||||
        super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Extends the default Range#include? to support range comparisons.
 | 
			
		||||
    #  (1..5).include?(1..5)  # => true
 | 
			
		||||
    #  (1..5).include?(2..3)  # => true
 | 
			
		||||
    #  (1..5).include?(1...6) # => true
 | 
			
		||||
    #  (1..5).include?(2..6)  # => false
 | 
			
		||||
    #
 | 
			
		||||
    # The native Range#include? behavior is untouched.
 | 
			
		||||
    #  ('a'..'f').include?('c') # => true
 | 
			
		||||
    #  (5..9).include?(11) # => false
 | 
			
		||||
    #
 | 
			
		||||
    # The given range must be fully bounded, with both start and end.
 | 
			
		||||
    def include?(value)
 | 
			
		||||
      if value.is_a?(::Range)
 | 
			
		||||
        is_backwards_op = value.exclude_end? ? :>= : :>
 | 
			
		||||
        return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
 | 
			
		||||
        # 1...10 includes 1..9 but it does not include 1..10.
 | 
			
		||||
        # 1..10 includes 1...11 but it does not include 1...12.
 | 
			
		||||
        operator = exclude_end? && !value.exclude_end? ? :< : :<=
 | 
			
		||||
        value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
 | 
			
		||||
        super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Extends the default Range#cover? to support range comparisons.
 | 
			
		||||
    #  (1..5).cover?(1..5)  # => true
 | 
			
		||||
    #  (1..5).cover?(2..3)  # => true
 | 
			
		||||
    #  (1..5).cover?(1...6) # => true
 | 
			
		||||
    #  (1..5).cover?(2..6)  # => false
 | 
			
		||||
    #
 | 
			
		||||
    # The native Range#cover? behavior is untouched.
 | 
			
		||||
    #  ('a'..'f').cover?('c') # => true
 | 
			
		||||
    #  (5..9).cover?(11) # => false
 | 
			
		||||
    #
 | 
			
		||||
    # The given range must be fully bounded, with both start and end.
 | 
			
		||||
    def cover?(value)
 | 
			
		||||
      if value.is_a?(::Range)
 | 
			
		||||
        is_backwards_op = value.exclude_end? ? :>= : :>
 | 
			
		||||
        return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
 | 
			
		||||
        # 1...10 covers 1..9 but it does not cover 1..10.
 | 
			
		||||
        # 1..10 covers 1...11 but it does not cover 1...12.
 | 
			
		||||
        operator = exclude_end? && !value.exclude_end? ? :< : :<=
 | 
			
		||||
        value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
 | 
			
		||||
        super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Range.prepend(ActiveSupport::CompareWithRange)
 | 
			
		||||
@ -1,41 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module RangeWithFormat
 | 
			
		||||
    RANGE_FORMATS = {
 | 
			
		||||
      db: -> (start, stop) do
 | 
			
		||||
        case start
 | 
			
		||||
        when String then "BETWEEN '#{start}' AND '#{stop}'"
 | 
			
		||||
        else
 | 
			
		||||
          "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
 | 
			
		||||
    #
 | 
			
		||||
    #   range = (1..100)           # => 1..100
 | 
			
		||||
    #
 | 
			
		||||
    #   range.to_s                 # => "1..100"
 | 
			
		||||
    #   range.to_s(:db)            # => "BETWEEN '1' AND '100'"
 | 
			
		||||
    #
 | 
			
		||||
    # == Adding your own range formats to to_s
 | 
			
		||||
    # You can add your own formats to the Range::RANGE_FORMATS hash.
 | 
			
		||||
    # Use the format name as the hash key and a Proc instance.
 | 
			
		||||
    #
 | 
			
		||||
    #   # config/initializers/range_formats.rb
 | 
			
		||||
    #   Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
 | 
			
		||||
    def to_s(format = :default)
 | 
			
		||||
      if formatter = RANGE_FORMATS[format]
 | 
			
		||||
        formatter.call(first, last)
 | 
			
		||||
      else
 | 
			
		||||
        super()
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    alias_method :to_default_s, :to_s
 | 
			
		||||
    alias_method :to_formatted_s, :to_s
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Range.prepend(ActiveSupport::RangeWithFormat)
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/time_with_zone"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module EachTimeWithZone #:nodoc:
 | 
			
		||||
    def each(&block)
 | 
			
		||||
      ensure_iteration_allowed
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def step(n = 1, &block)
 | 
			
		||||
      ensure_iteration_allowed
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def ensure_iteration_allowed
 | 
			
		||||
        raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone)
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Range.prepend(ActiveSupport::EachTimeWithZone)
 | 
			
		||||
@ -1,28 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/time_with_zone"
 | 
			
		||||
require "active_support/deprecation"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  module IncludeTimeWithZone #:nodoc:
 | 
			
		||||
    # Extends the default Range#include? to support ActiveSupport::TimeWithZone.
 | 
			
		||||
    #
 | 
			
		||||
    #   (1.hour.ago..1.hour.from_now).include?(Time.current) # => true
 | 
			
		||||
    #
 | 
			
		||||
    def include?(value)
 | 
			
		||||
      if self.begin.is_a?(TimeWithZone) || self.end.is_a?(TimeWithZone)
 | 
			
		||||
        ActiveSupport::Deprecation.warn(<<-MSG.squish)
 | 
			
		||||
          Using `Range#include?` to check the inclusion of a value in
 | 
			
		||||
          a date time range is deprecated.
 | 
			
		||||
          It is recommended to use `Range#cover?` instead of `Range#include?` to
 | 
			
		||||
          check the inclusion of a value in a date time range.
 | 
			
		||||
        MSG
 | 
			
		||||
        cover?(value)
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Range.prepend(ActiveSupport::IncludeTimeWithZone)
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Range
 | 
			
		||||
  # Compare two ranges and see if they overlap each other
 | 
			
		||||
  #  (1..5).overlaps?(4..6) # => true
 | 
			
		||||
  #  (1..5).overlaps?(7..9) # => false
 | 
			
		||||
  def overlaps?(other)
 | 
			
		||||
    cover?(other.first) || other.cover?(first)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Regexp
 | 
			
		||||
  # Returns +true+ if the regexp has the multiline flag set.
 | 
			
		||||
  #
 | 
			
		||||
  #   (/./).multiline?  # => false
 | 
			
		||||
  #   (/./m).multiline? # => true
 | 
			
		||||
  #
 | 
			
		||||
  #   Regexp.new(".").multiline?                    # => false
 | 
			
		||||
  #   Regexp.new(".", Regexp::MULTILINE).multiline? # => true
 | 
			
		||||
  def multiline?
 | 
			
		||||
    options & MULTILINE == MULTILINE
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,45 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "securerandom"
 | 
			
		||||
 | 
			
		||||
module SecureRandom
 | 
			
		||||
  BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
 | 
			
		||||
  BASE36_ALPHABET = ("0".."9").to_a + ("a".."z").to_a
 | 
			
		||||
 | 
			
		||||
  # SecureRandom.base58 generates a random base58 string.
 | 
			
		||||
  #
 | 
			
		||||
  # The argument _n_ specifies the length of the random string to be generated.
 | 
			
		||||
  #
 | 
			
		||||
  # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
 | 
			
		||||
  #
 | 
			
		||||
  # The result may contain alphanumeric characters except 0, O, I and l.
 | 
			
		||||
  #
 | 
			
		||||
  #   p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
 | 
			
		||||
  #   p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
 | 
			
		||||
  def self.base58(n = 16)
 | 
			
		||||
    SecureRandom.random_bytes(n).unpack("C*").map do |byte|
 | 
			
		||||
      idx = byte % 64
 | 
			
		||||
      idx = SecureRandom.random_number(58) if idx >= 58
 | 
			
		||||
      BASE58_ALPHABET[idx]
 | 
			
		||||
    end.join
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # SecureRandom.base36 generates a random base36 string in lowercase.
 | 
			
		||||
  #
 | 
			
		||||
  # The argument _n_ specifies the length of the random string to be generated.
 | 
			
		||||
  #
 | 
			
		||||
  # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
 | 
			
		||||
  # This method can be used over +base58+ if a deterministic case key is necessary.
 | 
			
		||||
  #
 | 
			
		||||
  # The result will contain alphanumeric characters in lowercase.
 | 
			
		||||
  #
 | 
			
		||||
  #   p SecureRandom.base36 # => "4kugl2pdqmscqtje"
 | 
			
		||||
  #   p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
 | 
			
		||||
  def self.base36(n = 16)
 | 
			
		||||
    SecureRandom.random_bytes(n).unpack("C*").map do |byte|
 | 
			
		||||
      idx = byte % 64
 | 
			
		||||
      idx = SecureRandom.random_number(36) if idx >= 36
 | 
			
		||||
      BASE36_ALPHABET[idx]
 | 
			
		||||
    end.join
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/string/conversions"
 | 
			
		||||
require "active_support/core_ext/string/filters"
 | 
			
		||||
require "active_support/core_ext/string/multibyte"
 | 
			
		||||
require "active_support/core_ext/string/starts_ends_with"
 | 
			
		||||
require "active_support/core_ext/string/inflections"
 | 
			
		||||
require "active_support/core_ext/string/access"
 | 
			
		||||
require "active_support/core_ext/string/behavior"
 | 
			
		||||
require "active_support/core_ext/string/output_safety"
 | 
			
		||||
require "active_support/core_ext/string/exclude"
 | 
			
		||||
require "active_support/core_ext/string/strip"
 | 
			
		||||
require "active_support/core_ext/string/inquiry"
 | 
			
		||||
require "active_support/core_ext/string/indent"
 | 
			
		||||
require "active_support/core_ext/string/zones"
 | 
			
		||||
@ -1,95 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # If you pass a single integer, returns a substring of one character at that
 | 
			
		||||
  # position. The first character of the string is at position 0, the next at
 | 
			
		||||
  # position 1, and so on. If a range is supplied, a substring containing
 | 
			
		||||
  # characters at offsets given by the range is returned. In both cases, if an
 | 
			
		||||
  # offset is negative, it is counted from the end of the string. Returns +nil+
 | 
			
		||||
  # if the initial offset falls outside the string. Returns an empty string if
 | 
			
		||||
  # the beginning of the range is greater than the end of the string.
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.at(0)      # => "h"
 | 
			
		||||
  #   str.at(1..3)   # => "ell"
 | 
			
		||||
  #   str.at(-2)     # => "l"
 | 
			
		||||
  #   str.at(-2..-1) # => "lo"
 | 
			
		||||
  #   str.at(5)      # => nil
 | 
			
		||||
  #   str.at(5..-1)  # => ""
 | 
			
		||||
  #
 | 
			
		||||
  # If a Regexp is given, the matching portion of the string is returned.
 | 
			
		||||
  # If a String is given, that given string is returned if it occurs in
 | 
			
		||||
  # the string. In both cases, +nil+ is returned if there is no match.
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.at(/lo/) # => "lo"
 | 
			
		||||
  #   str.at(/ol/) # => nil
 | 
			
		||||
  #   str.at("lo") # => "lo"
 | 
			
		||||
  #   str.at("ol") # => nil
 | 
			
		||||
  def at(position)
 | 
			
		||||
    self[position]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a substring from the given position to the end of the string.
 | 
			
		||||
  # If the position is negative, it is counted from the end of the string.
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.from(0)  # => "hello"
 | 
			
		||||
  #   str.from(3)  # => "lo"
 | 
			
		||||
  #   str.from(-2) # => "lo"
 | 
			
		||||
  #
 | 
			
		||||
  # You can mix it with +to+ method and do fun things like:
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.from(0).to(-1) # => "hello"
 | 
			
		||||
  #   str.from(1).to(-2) # => "ell"
 | 
			
		||||
  def from(position)
 | 
			
		||||
    self[position, length]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a substring from the beginning of the string to the given position.
 | 
			
		||||
  # If the position is negative, it is counted from the end of the string.
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.to(0)  # => "h"
 | 
			
		||||
  #   str.to(3)  # => "hell"
 | 
			
		||||
  #   str.to(-2) # => "hell"
 | 
			
		||||
  #
 | 
			
		||||
  # You can mix it with +from+ method and do fun things like:
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.from(0).to(-1) # => "hello"
 | 
			
		||||
  #   str.from(1).to(-2) # => "ell"
 | 
			
		||||
  def to(position)
 | 
			
		||||
    position += size if position < 0
 | 
			
		||||
    self[0, position + 1] || +""
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the first character. If a limit is supplied, returns a substring
 | 
			
		||||
  # from the beginning of the string until it reaches the limit value. If the
 | 
			
		||||
  # given limit is greater than or equal to the string length, returns a copy of self.
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.first    # => "h"
 | 
			
		||||
  #   str.first(1) # => "h"
 | 
			
		||||
  #   str.first(2) # => "he"
 | 
			
		||||
  #   str.first(0) # => ""
 | 
			
		||||
  #   str.first(6) # => "hello"
 | 
			
		||||
  def first(limit = 1)
 | 
			
		||||
    self[0, limit] || raise(ArgumentError, "negative limit")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the last character of the string. If a limit is supplied, returns a substring
 | 
			
		||||
  # from the end of the string until it reaches the limit value (counting backwards). If
 | 
			
		||||
  # the given limit is greater than or equal to the string length, returns a copy of self.
 | 
			
		||||
  #
 | 
			
		||||
  #   str = "hello"
 | 
			
		||||
  #   str.last    # => "o"
 | 
			
		||||
  #   str.last(1) # => "o"
 | 
			
		||||
  #   str.last(2) # => "lo"
 | 
			
		||||
  #   str.last(0) # => ""
 | 
			
		||||
  #   str.last(6) # => "hello"
 | 
			
		||||
  def last(limit = 1)
 | 
			
		||||
    self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
 | 
			
		||||
  def acts_like_string?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,60 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "date"
 | 
			
		||||
require "active_support/core_ext/time/calculations"
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # Converts a string to a Time value.
 | 
			
		||||
  # The +form+ can be either :utc or :local (default :local).
 | 
			
		||||
  #
 | 
			
		||||
  # The time is parsed using Time.parse method.
 | 
			
		||||
  # If +form+ is :local, then the time is in the system timezone.
 | 
			
		||||
  # If the date part is missing then the current date is used and if
 | 
			
		||||
  # the time part is missing then it is assumed to be 00:00:00.
 | 
			
		||||
  #
 | 
			
		||||
  #   "13-12-2012".to_time               # => 2012-12-13 00:00:00 +0100
 | 
			
		||||
  #   "06:12".to_time                    # => 2012-12-13 06:12:00 +0100
 | 
			
		||||
  #   "2012-12-13 06:12".to_time         # => 2012-12-13 06:12:00 +0100
 | 
			
		||||
  #   "2012-12-13T06:12".to_time         # => 2012-12-13 06:12:00 +0100
 | 
			
		||||
  #   "2012-12-13T06:12".to_time(:utc)   # => 2012-12-13 06:12:00 UTC
 | 
			
		||||
  #   "12/13/2012".to_time               # => ArgumentError: argument out of range
 | 
			
		||||
  #   "1604326192".to_time               # => ArgumentError: argument out of range
 | 
			
		||||
  def to_time(form = :local)
 | 
			
		||||
    parts = Date._parse(self, false)
 | 
			
		||||
    used_keys = %i(year mon mday hour min sec sec_fraction offset)
 | 
			
		||||
    return if (parts.keys & used_keys).empty?
 | 
			
		||||
 | 
			
		||||
    now = Time.now
 | 
			
		||||
    time = Time.new(
 | 
			
		||||
      parts.fetch(:year, now.year),
 | 
			
		||||
      parts.fetch(:mon, now.month),
 | 
			
		||||
      parts.fetch(:mday, now.day),
 | 
			
		||||
      parts.fetch(:hour, 0),
 | 
			
		||||
      parts.fetch(:min, 0),
 | 
			
		||||
      parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
 | 
			
		||||
      parts.fetch(:offset, form == :utc ? 0 : nil)
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    form == :utc ? time.utc : time.to_time
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts a string to a Date value.
 | 
			
		||||
  #
 | 
			
		||||
  #   "1-1-2012".to_date   # => Sun, 01 Jan 2012
 | 
			
		||||
  #   "01/01/2012".to_date # => Sun, 01 Jan 2012
 | 
			
		||||
  #   "2012-12-13".to_date # => Thu, 13 Dec 2012
 | 
			
		||||
  #   "12/13/2012".to_date # => ArgumentError: invalid date
 | 
			
		||||
  def to_date
 | 
			
		||||
    ::Date.parse(self, false) unless blank?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Converts a string to a DateTime value.
 | 
			
		||||
  #
 | 
			
		||||
  #   "1-1-2012".to_datetime            # => Sun, 01 Jan 2012 00:00:00 +0000
 | 
			
		||||
  #   "01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
 | 
			
		||||
  #   "2012-12-13 12:50".to_datetime    # => Thu, 13 Dec 2012 12:50:00 +0000
 | 
			
		||||
  #   "12/13/2012".to_datetime          # => ArgumentError: invalid date
 | 
			
		||||
  def to_datetime
 | 
			
		||||
    ::DateTime.parse(self, false) unless blank?
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/string_inquirer"
 | 
			
		||||
require "active_support/environment_inquirer"
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
 | 
			
		||||
  # which gives you a prettier way to test for equality.
 | 
			
		||||
  #
 | 
			
		||||
  #   env = 'production'.inquiry
 | 
			
		||||
  #   env.production?  # => true
 | 
			
		||||
  #   env.development? # => false
 | 
			
		||||
  def inquiry
 | 
			
		||||
    ActiveSupport::StringInquirer.new(self)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,347 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "erb"
 | 
			
		||||
require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
require "active_support/multibyte/unicode"
 | 
			
		||||
 | 
			
		||||
class ERB
 | 
			
		||||
  module Util
 | 
			
		||||
    HTML_ESCAPE = { "&" => "&",  ">" => ">",   "<" => "<", '"' => """, "'" => "'" }
 | 
			
		||||
    JSON_ESCAPE = { "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
 | 
			
		||||
    HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
 | 
			
		||||
    JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
 | 
			
		||||
 | 
			
		||||
    # Following XML requirements: https://www.w3.org/TR/REC-xml/#NT-Name
 | 
			
		||||
    TAG_NAME_START_REGEXP_SET = "@:A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \
 | 
			
		||||
                                "\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \
 | 
			
		||||
                                "\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}"
 | 
			
		||||
    TAG_NAME_START_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}]/
 | 
			
		||||
    TAG_NAME_FOLLOWING_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}]/
 | 
			
		||||
    TAG_NAME_REPLACEMENT_CHAR = "_"
 | 
			
		||||
 | 
			
		||||
    # A utility method for escaping HTML tag characters.
 | 
			
		||||
    # This method is also aliased as <tt>h</tt>.
 | 
			
		||||
    #
 | 
			
		||||
    #   puts html_escape('is a > 0 & a < 10?')
 | 
			
		||||
    #   # => is a > 0 & a < 10?
 | 
			
		||||
    def html_escape(s)
 | 
			
		||||
      unwrapped_html_escape(s).html_safe
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    silence_redefinition_of_method :h
 | 
			
		||||
    alias h html_escape
 | 
			
		||||
 | 
			
		||||
    module_function :h
 | 
			
		||||
 | 
			
		||||
    singleton_class.silence_redefinition_of_method :html_escape
 | 
			
		||||
    module_function :html_escape
 | 
			
		||||
 | 
			
		||||
    # HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
 | 
			
		||||
    # This method is not for public consumption! Seriously!
 | 
			
		||||
    def unwrapped_html_escape(s) # :nodoc:
 | 
			
		||||
      s = s.to_s
 | 
			
		||||
      if s.html_safe?
 | 
			
		||||
        s
 | 
			
		||||
      else
 | 
			
		||||
        CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    module_function :unwrapped_html_escape
 | 
			
		||||
 | 
			
		||||
    # A utility method for escaping HTML without affecting existing escaped entities.
 | 
			
		||||
    #
 | 
			
		||||
    #   html_escape_once('1 < 2 & 3')
 | 
			
		||||
    #   # => "1 < 2 & 3"
 | 
			
		||||
    #
 | 
			
		||||
    #   html_escape_once('<< Accept & Checkout')
 | 
			
		||||
    #   # => "<< Accept & Checkout"
 | 
			
		||||
    def html_escape_once(s)
 | 
			
		||||
      result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
 | 
			
		||||
      s.html_safe? ? result.html_safe : result
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module_function :html_escape_once
 | 
			
		||||
 | 
			
		||||
    # A utility method for escaping HTML entities in JSON strings. Specifically, the
 | 
			
		||||
    # &, > and < characters are replaced with their equivalent unicode escaped form -
 | 
			
		||||
    # \u0026, \u003e, and \u003c. The Unicode sequences \u2028 and \u2029 are also
 | 
			
		||||
    # escaped as they are treated as newline characters in some JavaScript engines.
 | 
			
		||||
    # These sequences have identical meaning as the original characters inside the
 | 
			
		||||
    # context of a JSON string, so assuming the input is a valid and well-formed
 | 
			
		||||
    # JSON value, the output will have equivalent meaning when parsed:
 | 
			
		||||
    #
 | 
			
		||||
    #   json = JSON.generate({ name: "</script><script>alert('PWNED!!!')</script>"})
 | 
			
		||||
    #   # => "{\"name\":\"</script><script>alert('PWNED!!!')</script>\"}"
 | 
			
		||||
    #
 | 
			
		||||
    #   json_escape(json)
 | 
			
		||||
    #   # => "{\"name\":\"\\u003C/script\\u003E\\u003Cscript\\u003Ealert('PWNED!!!')\\u003C/script\\u003E\"}"
 | 
			
		||||
    #
 | 
			
		||||
    #   JSON.parse(json) == JSON.parse(json_escape(json))
 | 
			
		||||
    #   # => true
 | 
			
		||||
    #
 | 
			
		||||
    # The intended use case for this method is to escape JSON strings before including
 | 
			
		||||
    # them inside a script tag to avoid XSS vulnerability:
 | 
			
		||||
    #
 | 
			
		||||
    #   <script>
 | 
			
		||||
    #     var currentUser = <%= raw json_escape(current_user.to_json) %>;
 | 
			
		||||
    #   </script>
 | 
			
		||||
    #
 | 
			
		||||
    # It is necessary to +raw+ the result of +json_escape+, so that quotation marks
 | 
			
		||||
    # don't get converted to <tt>"</tt> entities. +json_escape+ doesn't
 | 
			
		||||
    # automatically flag the result as HTML safe, since the raw value is unsafe to
 | 
			
		||||
    # use inside HTML attributes.
 | 
			
		||||
    #
 | 
			
		||||
    # If your JSON is being used downstream for insertion into the DOM, be aware of
 | 
			
		||||
    # whether or not it is being inserted via <tt>html()</tt>. Most jQuery plugins do this.
 | 
			
		||||
    # If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
 | 
			
		||||
    # content returned by your JSON.
 | 
			
		||||
    #
 | 
			
		||||
    # If you need to output JSON elsewhere in your HTML, you can just do something
 | 
			
		||||
    # like this, as any unsafe characters (including quotation marks) will be
 | 
			
		||||
    # automatically escaped for you:
 | 
			
		||||
    #
 | 
			
		||||
    #   <div data-user-info="<%= current_user.to_json %>">...</div>
 | 
			
		||||
    #
 | 
			
		||||
    # WARNING: this helper only works with valid JSON. Using this on non-JSON values
 | 
			
		||||
    # will open up serious XSS vulnerabilities. For example, if you replace the
 | 
			
		||||
    # +current_user.to_json+ in the example above with user input instead, the browser
 | 
			
		||||
    # will happily eval() that string as JavaScript.
 | 
			
		||||
    #
 | 
			
		||||
    # The escaping performed in this method is identical to those performed in the
 | 
			
		||||
    # Active Support JSON encoder when +ActiveSupport.escape_html_entities_in_json+ is
 | 
			
		||||
    # set to true. Because this transformation is idempotent, this helper can be
 | 
			
		||||
    # applied even if +ActiveSupport.escape_html_entities_in_json+ is already true.
 | 
			
		||||
    #
 | 
			
		||||
    # Therefore, when you are unsure if +ActiveSupport.escape_html_entities_in_json+
 | 
			
		||||
    # is enabled, or if you are unsure where your JSON string originated from, it
 | 
			
		||||
    # is recommended that you always apply this helper (other libraries, such as the
 | 
			
		||||
    # JSON gem, do not provide this kind of protection by default; also some gems
 | 
			
		||||
    # might override +to_json+ to bypass Active Support's encoder).
 | 
			
		||||
    def json_escape(s)
 | 
			
		||||
      result = s.to_s.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE)
 | 
			
		||||
      s.html_safe? ? result.html_safe : result
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module_function :json_escape
 | 
			
		||||
 | 
			
		||||
    # A utility method for escaping XML names of tags and names of attributes.
 | 
			
		||||
    #
 | 
			
		||||
    #   xml_name_escape('1 < 2 & 3')
 | 
			
		||||
    #   # => "1___2___3"
 | 
			
		||||
    #
 | 
			
		||||
    # It follows the requirements of the specification: https://www.w3.org/TR/REC-xml/#NT-Name
 | 
			
		||||
    def xml_name_escape(name)
 | 
			
		||||
      name = name.to_s
 | 
			
		||||
      return "" if name.blank?
 | 
			
		||||
 | 
			
		||||
      starting_char = name[0].gsub(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
 | 
			
		||||
 | 
			
		||||
      return starting_char if name.size == 1
 | 
			
		||||
 | 
			
		||||
      following_chars = name[1..-1].gsub(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
 | 
			
		||||
 | 
			
		||||
      starting_char + following_chars
 | 
			
		||||
    end
 | 
			
		||||
    module_function :xml_name_escape
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  def html_safe?
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Numeric
 | 
			
		||||
  def html_safe?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module ActiveSupport #:nodoc:
 | 
			
		||||
  class SafeBuffer < String
 | 
			
		||||
    UNSAFE_STRING_METHODS = %w(
 | 
			
		||||
      capitalize chomp chop delete delete_prefix delete_suffix
 | 
			
		||||
      downcase lstrip next reverse rstrip scrub slice squeeze strip
 | 
			
		||||
      succ swapcase tr tr_s unicode_normalize upcase
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub)
 | 
			
		||||
 | 
			
		||||
    alias_method :original_concat, :concat
 | 
			
		||||
    private :original_concat
 | 
			
		||||
 | 
			
		||||
    # Raised when <tt>ActiveSupport::SafeBuffer#safe_concat</tt> is called on unsafe buffers.
 | 
			
		||||
    class SafeConcatError < StandardError
 | 
			
		||||
      def initialize
 | 
			
		||||
        super "Could not concatenate to the buffer because it is not html safe."
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [](*args)
 | 
			
		||||
      if html_safe?
 | 
			
		||||
        new_string = super
 | 
			
		||||
 | 
			
		||||
        return unless new_string
 | 
			
		||||
 | 
			
		||||
        new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
 | 
			
		||||
        new_safe_buffer.instance_variable_set :@html_safe, true
 | 
			
		||||
        new_safe_buffer
 | 
			
		||||
      else
 | 
			
		||||
        to_str[*args]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def safe_concat(value)
 | 
			
		||||
      raise SafeConcatError unless html_safe?
 | 
			
		||||
      original_concat(value)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize(str = "")
 | 
			
		||||
      @html_safe = true
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_copy(other)
 | 
			
		||||
      super
 | 
			
		||||
      @html_safe = other.html_safe?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clone_empty
 | 
			
		||||
      self[0, 0]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def concat(value)
 | 
			
		||||
      super(html_escape_interpolated_argument(value))
 | 
			
		||||
    end
 | 
			
		||||
    alias << concat
 | 
			
		||||
 | 
			
		||||
    def bytesplice(*args, value)
 | 
			
		||||
      super(*args, implicit_html_escape_interpolated_argument(value))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def insert(index, value)
 | 
			
		||||
      super(index, html_escape_interpolated_argument(value))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def prepend(value)
 | 
			
		||||
      super(html_escape_interpolated_argument(value))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def replace(value)
 | 
			
		||||
      super(html_escape_interpolated_argument(value))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def []=(*args)
 | 
			
		||||
      if args.length == 3
 | 
			
		||||
        super(args[0], args[1], html_escape_interpolated_argument(args[2]))
 | 
			
		||||
      else
 | 
			
		||||
        super(args[0], html_escape_interpolated_argument(args[1]))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def +(other)
 | 
			
		||||
      dup.concat(other)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def *(*)
 | 
			
		||||
      new_string = super
 | 
			
		||||
      new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
 | 
			
		||||
      new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
 | 
			
		||||
      new_safe_buffer
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def %(args)
 | 
			
		||||
      case args
 | 
			
		||||
      when Hash
 | 
			
		||||
        escaped_args = args.transform_values { |arg| html_escape_interpolated_argument(arg) }
 | 
			
		||||
      else
 | 
			
		||||
        escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      self.class.new(super(escaped_args))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def html_safe?
 | 
			
		||||
      defined?(@html_safe) && @html_safe
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_s
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_param
 | 
			
		||||
      to_str
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def encode_with(coder)
 | 
			
		||||
      coder.represent_object nil, to_str
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    UNSAFE_STRING_METHODS.each do |unsafe_method|
 | 
			
		||||
      if unsafe_method.respond_to?(unsafe_method)
 | 
			
		||||
        class_eval <<-EOT, __FILE__, __LINE__ + 1
 | 
			
		||||
          def #{unsafe_method}(*args, &block)       # def capitalize(*args, &block)
 | 
			
		||||
            to_str.#{unsafe_method}(*args, &block)  #   to_str.capitalize(*args, &block)
 | 
			
		||||
          end                                       # end
 | 
			
		||||
 | 
			
		||||
          def #{unsafe_method}!(*args)              # def capitalize!(*args)
 | 
			
		||||
            @html_safe = false                      #   @html_safe = false
 | 
			
		||||
            super                                   #   super
 | 
			
		||||
          end                                       # end
 | 
			
		||||
        EOT
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
 | 
			
		||||
      if unsafe_method.respond_to?(unsafe_method)
 | 
			
		||||
        class_eval <<-EOT, __FILE__, __LINE__ + 1
 | 
			
		||||
          def #{unsafe_method}(*args, &block)             # def gsub(*args, &block)
 | 
			
		||||
            if block                                      #   if block
 | 
			
		||||
              to_str.#{unsafe_method}(*args) { |*params|  #     to_str.gsub(*args) { |*params|
 | 
			
		||||
                set_block_back_references(block, $~)      #       set_block_back_references(block, $~)
 | 
			
		||||
                block.call(*params)                       #       block.call(*params)
 | 
			
		||||
              }                                           #     }
 | 
			
		||||
            else                                          #   else
 | 
			
		||||
              to_str.#{unsafe_method}(*args)              #     to_str.gsub(*args)
 | 
			
		||||
            end                                           #   end
 | 
			
		||||
          end                                             # end
 | 
			
		||||
 | 
			
		||||
          def #{unsafe_method}!(*args, &block)            # def gsub!(*args, &block)
 | 
			
		||||
            @html_safe = false                            #   @html_safe = false
 | 
			
		||||
            if block                                      #   if block
 | 
			
		||||
              super(*args) { |*params|                    #     super(*args) { |*params|
 | 
			
		||||
                set_block_back_references(block, $~)      #       set_block_back_references(block, $~)
 | 
			
		||||
                block.call(*params)                       #       block.call(*params)
 | 
			
		||||
              }                                           #     }
 | 
			
		||||
            else                                          #   else
 | 
			
		||||
              super                                       #     super
 | 
			
		||||
            end                                           #   end
 | 
			
		||||
          end                                             # end
 | 
			
		||||
        EOT
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def html_escape_interpolated_argument(arg)
 | 
			
		||||
        (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def set_block_back_references(block, match_data)
 | 
			
		||||
        block.binding.eval("proc { |m| $~ = m }").call(match_data)
 | 
			
		||||
      rescue ArgumentError
 | 
			
		||||
        # Can't create binding from C level Proc
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # Marks a string as trusted safe. It will be inserted into HTML with no
 | 
			
		||||
  # additional escaping performed. It is your responsibility to ensure that the
 | 
			
		||||
  # string contains no malicious content. This method is equivalent to the
 | 
			
		||||
  # +raw+ helper in views. It is recommended that you use +sanitize+ instead of
 | 
			
		||||
  # this method. It should never be called on user input.
 | 
			
		||||
  def html_safe
 | 
			
		||||
    ActiveSupport::SafeBuffer.new(self)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  alias :starts_with? :start_with?
 | 
			
		||||
  alias :ends_with? :end_with?
 | 
			
		||||
end
 | 
			
		||||
@ -1,27 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # Strips indentation in heredocs.
 | 
			
		||||
  #
 | 
			
		||||
  # For example in
 | 
			
		||||
  #
 | 
			
		||||
  #   if options[:usage]
 | 
			
		||||
  #     puts <<-USAGE.strip_heredoc
 | 
			
		||||
  #       This command does such and such.
 | 
			
		||||
  #
 | 
			
		||||
  #       Supported options are:
 | 
			
		||||
  #         -h         This message
 | 
			
		||||
  #         ...
 | 
			
		||||
  #     USAGE
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # the user would see the usage message aligned against the left margin.
 | 
			
		||||
  #
 | 
			
		||||
  # Technically, it looks for the least indented non-empty line
 | 
			
		||||
  # in the whole string, and removes that amount of leading whitespace.
 | 
			
		||||
  def strip_heredoc
 | 
			
		||||
    gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
 | 
			
		||||
      stripped.freeze if frozen?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/string/conversions"
 | 
			
		||||
require "active_support/core_ext/time/zones"
 | 
			
		||||
 | 
			
		||||
class String
 | 
			
		||||
  # Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default
 | 
			
		||||
  # is set, otherwise converts String to a Time via String#to_time
 | 
			
		||||
  def in_time_zone(zone = ::Time.zone)
 | 
			
		||||
    if zone
 | 
			
		||||
      ::Time.find_zone!(zone).parse(self)
 | 
			
		||||
    else
 | 
			
		||||
      to_time
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/symbol/starts_ends_with"
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Symbol
 | 
			
		||||
  def start_with?(*prefixes)
 | 
			
		||||
    to_s.start_with?(*prefixes)
 | 
			
		||||
  end unless method_defined?(:start_with?)
 | 
			
		||||
 | 
			
		||||
  def end_with?(*suffixes)
 | 
			
		||||
    to_s.end_with?(*suffixes)
 | 
			
		||||
  end unless method_defined?(:end_with?)
 | 
			
		||||
 | 
			
		||||
  alias :starts_with? :start_with?
 | 
			
		||||
  alias :ends_with? :end_with?
 | 
			
		||||
end
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/time/acts_like"
 | 
			
		||||
require "active_support/core_ext/time/calculations"
 | 
			
		||||
require "active_support/core_ext/time/compatibility"
 | 
			
		||||
require "active_support/core_ext/time/conversions"
 | 
			
		||||
require "active_support/core_ext/time/zones"
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/object/acts_like"
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  # Duck-types as a Time-like class. See Object#acts_like?.
 | 
			
		||||
  def acts_like_time?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,365 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/duration"
 | 
			
		||||
require "active_support/core_ext/time/conversions"
 | 
			
		||||
require "active_support/time_with_zone"
 | 
			
		||||
require "active_support/core_ext/time/zones"
 | 
			
		||||
require "active_support/core_ext/date_and_time/calculations"
 | 
			
		||||
require "active_support/core_ext/date/calculations"
 | 
			
		||||
require "active_support/core_ext/module/remove_method"
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  include DateAndTime::Calculations
 | 
			
		||||
 | 
			
		||||
  COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
 | 
			
		||||
 | 
			
		||||
  class << self
 | 
			
		||||
    # Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
 | 
			
		||||
    def ===(other)
 | 
			
		||||
      super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the number of days in the given month.
 | 
			
		||||
    # If no year is specified, it will use the current year.
 | 
			
		||||
    def days_in_month(month, year = current.year)
 | 
			
		||||
      if month == 2 && ::Date.gregorian_leap?(year)
 | 
			
		||||
        29
 | 
			
		||||
      else
 | 
			
		||||
        COMMON_YEAR_DAYS_IN_MONTH[month]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the number of days in the given year.
 | 
			
		||||
    # If no year is specified, it will use the current year.
 | 
			
		||||
    def days_in_year(year = current.year)
 | 
			
		||||
      days_in_month(2, year) + 337
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns <tt>Time.zone.now</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns <tt>Time.now</tt>.
 | 
			
		||||
    def current
 | 
			
		||||
      ::Time.zone ? ::Time.zone.now : ::Time.now
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
 | 
			
		||||
    # instances can be used when called with a single argument
 | 
			
		||||
    def at_with_coercion(*args)
 | 
			
		||||
      return at_without_coercion(*args) if args.size != 1
 | 
			
		||||
 | 
			
		||||
      # Time.at can be called with a time or numerical value
 | 
			
		||||
      time_or_number = args.first
 | 
			
		||||
 | 
			
		||||
      if time_or_number.is_a?(ActiveSupport::TimeWithZone)
 | 
			
		||||
        at_without_coercion(time_or_number.to_r).getlocal
 | 
			
		||||
      elsif time_or_number.is_a?(DateTime)
 | 
			
		||||
        at_without_coercion(time_or_number.to_f).getlocal
 | 
			
		||||
      else
 | 
			
		||||
        at_without_coercion(time_or_number)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    ruby2_keywords(:at_with_coercion) if respond_to?(:ruby2_keywords, true)
 | 
			
		||||
    alias_method :at_without_coercion, :at
 | 
			
		||||
    alias_method :at, :at_with_coercion
 | 
			
		||||
 | 
			
		||||
    # Creates a +Time+ instance from an RFC 3339 string.
 | 
			
		||||
    #
 | 
			
		||||
    #   Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000
 | 
			
		||||
    #
 | 
			
		||||
    # If the time or offset components are missing then an +ArgumentError+ will be raised.
 | 
			
		||||
    #
 | 
			
		||||
    #   Time.rfc3339('1999-12-31') # => ArgumentError: invalid date
 | 
			
		||||
    def rfc3339(str)
 | 
			
		||||
      parts = Date._rfc3339(str)
 | 
			
		||||
 | 
			
		||||
      raise ArgumentError, "invalid date" if parts.empty?
 | 
			
		||||
 | 
			
		||||
      Time.new(
 | 
			
		||||
        parts.fetch(:year),
 | 
			
		||||
        parts.fetch(:mon),
 | 
			
		||||
        parts.fetch(:mday),
 | 
			
		||||
        parts.fetch(:hour),
 | 
			
		||||
        parts.fetch(:min),
 | 
			
		||||
        parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
 | 
			
		||||
        parts.fetch(:offset)
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the number of seconds since 00:00:00.
 | 
			
		||||
  #
 | 
			
		||||
  #   Time.new(2012, 8, 29,  0,  0,  0).seconds_since_midnight # => 0.0
 | 
			
		||||
  #   Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
 | 
			
		||||
  #   Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
 | 
			
		||||
  def seconds_since_midnight
 | 
			
		||||
    to_i - change(hour: 0).to_i + (usec / 1.0e+6)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the number of seconds until 23:59:59.
 | 
			
		||||
  #
 | 
			
		||||
  #   Time.new(2012, 8, 29,  0,  0,  0).seconds_until_end_of_day # => 86399
 | 
			
		||||
  #   Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
 | 
			
		||||
  #   Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
 | 
			
		||||
  def seconds_until_end_of_day
 | 
			
		||||
    end_of_day.to_i - to_i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the fraction of a second as a +Rational+
 | 
			
		||||
  #
 | 
			
		||||
  #   Time.new(2012, 8, 29, 0, 0, 0.5).sec_fraction # => (1/2)
 | 
			
		||||
  def sec_fraction
 | 
			
		||||
    subsec
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  unless Time.method_defined?(:floor)
 | 
			
		||||
    def floor(precision = 0)
 | 
			
		||||
      change(nsec: 0) + subsec.floor(precision)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Restricted Ruby version due to a bug in `Time#ceil`
 | 
			
		||||
  # See https://bugs.ruby-lang.org/issues/17025 for more details
 | 
			
		||||
  if RUBY_VERSION <= "2.8"
 | 
			
		||||
    remove_possible_method :ceil
 | 
			
		||||
    def ceil(precision = 0)
 | 
			
		||||
      change(nsec: 0) + subsec.ceil(precision)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time where one or more of the elements have been changed according
 | 
			
		||||
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
 | 
			
		||||
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
 | 
			
		||||
  # the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
 | 
			
		||||
  # and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
 | 
			
		||||
  # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
 | 
			
		||||
  # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
 | 
			
		||||
  # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
 | 
			
		||||
  #
 | 
			
		||||
  #   Time.new(2012, 8, 29, 22, 35, 0).change(day: 1)              # => Time.new(2012, 8, 1, 22, 35, 0)
 | 
			
		||||
  #   Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1)  # => Time.new(1981, 8, 1, 22, 35, 0)
 | 
			
		||||
  #   Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
 | 
			
		||||
  def change(options)
 | 
			
		||||
    new_year   = options.fetch(:year, year)
 | 
			
		||||
    new_month  = options.fetch(:month, month)
 | 
			
		||||
    new_day    = options.fetch(:day, day)
 | 
			
		||||
    new_hour   = options.fetch(:hour, hour)
 | 
			
		||||
    new_min    = options.fetch(:min, options[:hour] ? 0 : min)
 | 
			
		||||
    new_sec    = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
 | 
			
		||||
    new_offset = options.fetch(:offset, nil)
 | 
			
		||||
 | 
			
		||||
    if new_nsec = options[:nsec]
 | 
			
		||||
      raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
 | 
			
		||||
      new_usec = Rational(new_nsec, 1000)
 | 
			
		||||
    else
 | 
			
		||||
      new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    raise ArgumentError, "argument out of range" if new_usec >= 1000000
 | 
			
		||||
 | 
			
		||||
    new_sec += Rational(new_usec, 1000000)
 | 
			
		||||
 | 
			
		||||
    if new_offset
 | 
			
		||||
      ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
 | 
			
		||||
    elsif utc?
 | 
			
		||||
      ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
 | 
			
		||||
    elsif zone&.respond_to?(:utc_to_local)
 | 
			
		||||
      ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
 | 
			
		||||
    elsif zone
 | 
			
		||||
      ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
 | 
			
		||||
    else
 | 
			
		||||
      ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Uses Date to provide precise Time calculations for years, months, and days
 | 
			
		||||
  # according to the proleptic Gregorian calendar. The +options+ parameter
 | 
			
		||||
  # takes a hash with any of these keys: <tt>:years</tt>, <tt>:months</tt>,
 | 
			
		||||
  # <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>, <tt>:minutes</tt>,
 | 
			
		||||
  # <tt>:seconds</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700
 | 
			
		||||
  #   Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700
 | 
			
		||||
  #   Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1)   # => 2015-08-01 15:35:00 -0700
 | 
			
		||||
  #   Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1)    # => 2015-08-02 14:35:00 -0700
 | 
			
		||||
  #   Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1)   # => 2015-08-08 14:35:00 -0700
 | 
			
		||||
  def advance(options)
 | 
			
		||||
    unless options[:weeks].nil?
 | 
			
		||||
      options[:weeks], partial_weeks = options[:weeks].divmod(1)
 | 
			
		||||
      options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    unless options[:days].nil?
 | 
			
		||||
      options[:days], partial_days = options[:days].divmod(1)
 | 
			
		||||
      options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    d = to_date.gregorian.advance(options)
 | 
			
		||||
    time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
 | 
			
		||||
    seconds_to_advance = \
 | 
			
		||||
      options.fetch(:seconds, 0) +
 | 
			
		||||
      options.fetch(:minutes, 0) * 60 +
 | 
			
		||||
      options.fetch(:hours, 0) * 3600
 | 
			
		||||
 | 
			
		||||
    if seconds_to_advance.zero?
 | 
			
		||||
      time_advanced_by_date
 | 
			
		||||
    else
 | 
			
		||||
      time_advanced_by_date.since(seconds_to_advance)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
 | 
			
		||||
  def ago(seconds)
 | 
			
		||||
    since(-seconds)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the time a number of seconds since the instance time
 | 
			
		||||
  def since(seconds)
 | 
			
		||||
    self + seconds
 | 
			
		||||
  rescue
 | 
			
		||||
    to_datetime.since(seconds)
 | 
			
		||||
  end
 | 
			
		||||
  alias :in :since
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the start of the day (0:00)
 | 
			
		||||
  def beginning_of_day
 | 
			
		||||
    change(hour: 0)
 | 
			
		||||
  end
 | 
			
		||||
  alias :midnight :beginning_of_day
 | 
			
		||||
  alias :at_midnight :beginning_of_day
 | 
			
		||||
  alias :at_beginning_of_day :beginning_of_day
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the middle of the day (12:00)
 | 
			
		||||
  def middle_of_day
 | 
			
		||||
    change(hour: 12)
 | 
			
		||||
  end
 | 
			
		||||
  alias :midday :middle_of_day
 | 
			
		||||
  alias :noon :middle_of_day
 | 
			
		||||
  alias :at_midday :middle_of_day
 | 
			
		||||
  alias :at_noon :middle_of_day
 | 
			
		||||
  alias :at_middle_of_day :middle_of_day
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the end of the day, 23:59:59.999999
 | 
			
		||||
  def end_of_day
 | 
			
		||||
    change(
 | 
			
		||||
      hour: 23,
 | 
			
		||||
      min: 59,
 | 
			
		||||
      sec: 59,
 | 
			
		||||
      usec: Rational(999999999, 1000)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_day :end_of_day
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the start of the hour (x:00)
 | 
			
		||||
  def beginning_of_hour
 | 
			
		||||
    change(min: 0)
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_beginning_of_hour :beginning_of_hour
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the end of the hour, x:59:59.999999
 | 
			
		||||
  def end_of_hour
 | 
			
		||||
    change(
 | 
			
		||||
      min: 59,
 | 
			
		||||
      sec: 59,
 | 
			
		||||
      usec: Rational(999999999, 1000)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_hour :end_of_hour
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the start of the minute (x:xx:00)
 | 
			
		||||
  def beginning_of_minute
 | 
			
		||||
    change(sec: 0)
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_beginning_of_minute :beginning_of_minute
 | 
			
		||||
 | 
			
		||||
  # Returns a new Time representing the end of the minute, x:xx:59.999999
 | 
			
		||||
  def end_of_minute
 | 
			
		||||
    change(
 | 
			
		||||
      sec: 59,
 | 
			
		||||
      usec: Rational(999999999, 1000)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
  alias :at_end_of_minute :end_of_minute
 | 
			
		||||
 | 
			
		||||
  def plus_with_duration(other) #:nodoc:
 | 
			
		||||
    if ActiveSupport::Duration === other
 | 
			
		||||
      other.since(self)
 | 
			
		||||
    else
 | 
			
		||||
      plus_without_duration(other)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :plus_without_duration, :+
 | 
			
		||||
  alias_method :+, :plus_with_duration
 | 
			
		||||
 | 
			
		||||
  def minus_with_duration(other) #:nodoc:
 | 
			
		||||
    if ActiveSupport::Duration === other
 | 
			
		||||
      other.until(self)
 | 
			
		||||
    else
 | 
			
		||||
      minus_without_duration(other)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :minus_without_duration, :-
 | 
			
		||||
  alias_method :-, :minus_with_duration
 | 
			
		||||
 | 
			
		||||
  # Time#- can also be used to determine the number of seconds between two Time instances.
 | 
			
		||||
  # We're layering on additional behavior so that ActiveSupport::TimeWithZone instances
 | 
			
		||||
  # are coerced into values that Time#- will recognize
 | 
			
		||||
  def minus_with_coercion(other)
 | 
			
		||||
    other = other.comparable_time if other.respond_to?(:comparable_time)
 | 
			
		||||
    other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :minus_without_coercion, :-
 | 
			
		||||
  alias_method :-, :minus_with_coercion
 | 
			
		||||
 | 
			
		||||
  # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
 | 
			
		||||
  # can be chronologically compared with a Time
 | 
			
		||||
  def compare_with_coercion(other)
 | 
			
		||||
    # we're avoiding Time#to_datetime and Time#to_time because they're expensive
 | 
			
		||||
    if other.class == Time
 | 
			
		||||
      compare_without_coercion(other)
 | 
			
		||||
    elsif other.is_a?(Time)
 | 
			
		||||
      compare_without_coercion(other.to_time)
 | 
			
		||||
    else
 | 
			
		||||
      to_datetime <=> other
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :compare_without_coercion, :<=>
 | 
			
		||||
  alias_method :<=>, :compare_with_coercion
 | 
			
		||||
 | 
			
		||||
  # Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances
 | 
			
		||||
  # can be eql? to an equivalent Time
 | 
			
		||||
  def eql_with_coercion(other)
 | 
			
		||||
    # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison
 | 
			
		||||
    other = other.comparable_time if other.respond_to?(:comparable_time)
 | 
			
		||||
    eql_without_coercion(other)
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :eql_without_coercion, :eql?
 | 
			
		||||
  alias_method :eql?, :eql_with_coercion
 | 
			
		||||
 | 
			
		||||
  # Returns a new time the specified number of days ago.
 | 
			
		||||
  def prev_day(days = 1)
 | 
			
		||||
    advance(days: -days)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new time the specified number of days in the future.
 | 
			
		||||
  def next_day(days = 1)
 | 
			
		||||
    advance(days: days)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new time the specified number of months ago.
 | 
			
		||||
  def prev_month(months = 1)
 | 
			
		||||
    advance(months: -months)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new time the specified number of months in the future.
 | 
			
		||||
  def next_month(months = 1)
 | 
			
		||||
    advance(months: months)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new time the specified number of years ago.
 | 
			
		||||
  def prev_year(years = 1)
 | 
			
		||||
    advance(years: -years)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns a new time the specified number of years in the future.
 | 
			
		||||
  def next_year(years = 1)
 | 
			
		||||
    advance(years: years)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/date_and_time/compatibility"
 | 
			
		||||
require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  include DateAndTime::Compatibility
 | 
			
		||||
 | 
			
		||||
  silence_redefinition_of_method :to_time
 | 
			
		||||
 | 
			
		||||
  # Either return +self+ or the time in the local system timezone depending
 | 
			
		||||
  # on the setting of +ActiveSupport.to_time_preserves_timezone+.
 | 
			
		||||
  def to_time
 | 
			
		||||
    preserve_timezone ? self : getlocal
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,74 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "time"
 | 
			
		||||
require "active_support/inflector/methods"
 | 
			
		||||
require "active_support/values/time_zone"
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  DATE_FORMATS = {
 | 
			
		||||
    db: "%Y-%m-%d %H:%M:%S",
 | 
			
		||||
    inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
 | 
			
		||||
    number: "%Y%m%d%H%M%S",
 | 
			
		||||
    nsec: "%Y%m%d%H%M%S%9N",
 | 
			
		||||
    usec: "%Y%m%d%H%M%S%6N",
 | 
			
		||||
    time: "%H:%M",
 | 
			
		||||
    short: "%d %b %H:%M",
 | 
			
		||||
    long: "%B %d, %Y %H:%M",
 | 
			
		||||
    long_ordinal: lambda { |time|
 | 
			
		||||
      day_format = ActiveSupport::Inflector.ordinalize(time.day)
 | 
			
		||||
      time.strftime("%B #{day_format}, %Y %H:%M")
 | 
			
		||||
    },
 | 
			
		||||
    rfc822: lambda { |time|
 | 
			
		||||
      offset_format = time.formatted_offset(false)
 | 
			
		||||
      time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
 | 
			
		||||
    },
 | 
			
		||||
    iso8601: lambda { |time| time.iso8601 }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # Converts to a formatted string. See DATE_FORMATS for built-in formats.
 | 
			
		||||
  #
 | 
			
		||||
  # This method is aliased to <tt>to_s</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  #   time = Time.now                    # => 2007-01-18 06:10:17 -06:00
 | 
			
		||||
  #
 | 
			
		||||
  #   time.to_formatted_s(:time)         # => "06:10"
 | 
			
		||||
  #   time.to_s(:time)                   # => "06:10"
 | 
			
		||||
  #
 | 
			
		||||
  #   time.to_formatted_s(:db)           # => "2007-01-18 06:10:17"
 | 
			
		||||
  #   time.to_formatted_s(:number)       # => "20070118061017"
 | 
			
		||||
  #   time.to_formatted_s(:short)        # => "18 Jan 06:10"
 | 
			
		||||
  #   time.to_formatted_s(:long)         # => "January 18, 2007 06:10"
 | 
			
		||||
  #   time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
 | 
			
		||||
  #   time.to_formatted_s(:rfc822)       # => "Thu, 18 Jan 2007 06:10:17 -0600"
 | 
			
		||||
  #   time.to_formatted_s(:iso8601)      # => "2007-01-18T06:10:17-06:00"
 | 
			
		||||
  #
 | 
			
		||||
  # == Adding your own time formats to +to_formatted_s+
 | 
			
		||||
  # You can add your own formats to the Time::DATE_FORMATS hash.
 | 
			
		||||
  # Use the format name as the hash key and either a strftime string
 | 
			
		||||
  # or Proc instance that takes a time argument as the value.
 | 
			
		||||
  #
 | 
			
		||||
  #   # config/initializers/time_formats.rb
 | 
			
		||||
  #   Time::DATE_FORMATS[:month_and_year] = '%B %Y'
 | 
			
		||||
  #   Time::DATE_FORMATS[:short_ordinal]  = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
 | 
			
		||||
  def to_formatted_s(format = :default)
 | 
			
		||||
    if formatter = DATE_FORMATS[format]
 | 
			
		||||
      formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
 | 
			
		||||
    else
 | 
			
		||||
      to_default_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  alias_method :to_default_s, :to_s
 | 
			
		||||
  alias_method :to_s, :to_formatted_s
 | 
			
		||||
 | 
			
		||||
  # Returns a formatted string of the offset from UTC, or an alternative
 | 
			
		||||
  # string if the time zone is already UTC.
 | 
			
		||||
  #
 | 
			
		||||
  #   Time.local(2000).formatted_offset        # => "-06:00"
 | 
			
		||||
  #   Time.local(2000).formatted_offset(false) # => "-0600"
 | 
			
		||||
  def formatted_offset(colon = true, alternate_utc_string = nil)
 | 
			
		||||
    utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Aliased to +xmlschema+ for compatibility with +DateTime+
 | 
			
		||||
  alias_method :rfc3339, :xmlschema
 | 
			
		||||
end
 | 
			
		||||
@ -1,113 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/time_with_zone"
 | 
			
		||||
require "active_support/core_ext/time/acts_like"
 | 
			
		||||
require "active_support/core_ext/date_and_time/zones"
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  include DateAndTime::Zones
 | 
			
		||||
  class << self
 | 
			
		||||
    attr_accessor :zone_default
 | 
			
		||||
 | 
			
		||||
    # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
 | 
			
		||||
    # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
 | 
			
		||||
    def zone
 | 
			
		||||
      Thread.current[:time_zone] || zone_default
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
 | 
			
		||||
    #
 | 
			
		||||
    # This method accepts any of the following:
 | 
			
		||||
    #
 | 
			
		||||
    # * A Rails TimeZone object.
 | 
			
		||||
    # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
 | 
			
		||||
    # * A TZInfo::Timezone object.
 | 
			
		||||
    # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
 | 
			
		||||
    #
 | 
			
		||||
    # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis and reset it when the request is done.
 | 
			
		||||
    # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
 | 
			
		||||
    #
 | 
			
		||||
    #   class ApplicationController < ActionController::Base
 | 
			
		||||
    #     around_action :set_time_zone
 | 
			
		||||
    #
 | 
			
		||||
    #     def set_time_zone
 | 
			
		||||
    #       if logged_in?
 | 
			
		||||
    #         Time.use_zone(current_user.time_zone) { yield }
 | 
			
		||||
    #       else
 | 
			
		||||
    #         yield
 | 
			
		||||
    #       end
 | 
			
		||||
    #     end
 | 
			
		||||
    #   end
 | 
			
		||||
    def zone=(time_zone)
 | 
			
		||||
      Thread.current[:time_zone] = find_zone!(time_zone)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Allows override of <tt>Time.zone</tt> locally inside supplied block;
 | 
			
		||||
    # resets <tt>Time.zone</tt> to existing value when done.
 | 
			
		||||
    #
 | 
			
		||||
    #   class ApplicationController < ActionController::Base
 | 
			
		||||
    #     around_action :set_time_zone
 | 
			
		||||
    #
 | 
			
		||||
    #     private
 | 
			
		||||
    #
 | 
			
		||||
    #     def set_time_zone
 | 
			
		||||
    #       Time.use_zone(current_user.timezone) { yield }
 | 
			
		||||
    #     end
 | 
			
		||||
    #   end
 | 
			
		||||
    #
 | 
			
		||||
    # NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
 | 
			
		||||
    # objects that have already been created, e.g. any model timestamp
 | 
			
		||||
    # attributes that have been read before the block will remain in
 | 
			
		||||
    # the application's default timezone.
 | 
			
		||||
    def use_zone(time_zone)
 | 
			
		||||
      new_zone = find_zone!(time_zone)
 | 
			
		||||
      begin
 | 
			
		||||
        old_zone, ::Time.zone = ::Time.zone, new_zone
 | 
			
		||||
        yield
 | 
			
		||||
      ensure
 | 
			
		||||
        ::Time.zone = old_zone
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a TimeZone instance matching the time zone provided.
 | 
			
		||||
    # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
 | 
			
		||||
    # Raises an +ArgumentError+ for invalid time zones.
 | 
			
		||||
    #
 | 
			
		||||
    #   Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
 | 
			
		||||
    #   Time.find_zone! "EST"              # => #<ActiveSupport::TimeZone @name="EST" ...>
 | 
			
		||||
    #   Time.find_zone! -5.hours           # => #<ActiveSupport::TimeZone @name="Bogota" ...>
 | 
			
		||||
    #   Time.find_zone! nil                # => nil
 | 
			
		||||
    #   Time.find_zone! false              # => false
 | 
			
		||||
    #   Time.find_zone! "NOT-A-TIMEZONE"   # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
 | 
			
		||||
    def find_zone!(time_zone)
 | 
			
		||||
      if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
 | 
			
		||||
        time_zone
 | 
			
		||||
      else
 | 
			
		||||
        # Look up the timezone based on the identifier (unless we've been
 | 
			
		||||
        # passed a TZInfo::Timezone)
 | 
			
		||||
        unless time_zone.respond_to?(:period_for_local)
 | 
			
		||||
          time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
 | 
			
		||||
        if time_zone.is_a?(ActiveSupport::TimeZone)
 | 
			
		||||
          time_zone
 | 
			
		||||
        else
 | 
			
		||||
          ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    rescue TZInfo::InvalidTimezoneIdentifier
 | 
			
		||||
      raise ArgumentError, "Invalid Timezone: #{time_zone}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a TimeZone instance matching the time zone provided.
 | 
			
		||||
    # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
 | 
			
		||||
    # Returns +nil+ for invalid time zones.
 | 
			
		||||
    #
 | 
			
		||||
    #   Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
 | 
			
		||||
    #   Time.find_zone "NOT-A-TIMEZONE"   # => nil
 | 
			
		||||
    def find_zone(time_zone)
 | 
			
		||||
      find_zone!(time_zone) rescue nil
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,29 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "uri"
 | 
			
		||||
 | 
			
		||||
if RUBY_VERSION < "2.6.0"
 | 
			
		||||
  require "active_support/core_ext/module/redefine_method"
 | 
			
		||||
  URI::Parser.class_eval do
 | 
			
		||||
    silence_redefinition_of_method :unescape
 | 
			
		||||
    def unescape(str, escaped = /%[a-fA-F\d]{2}/)
 | 
			
		||||
      # TODO: Are we actually sure that ASCII == UTF-8?
 | 
			
		||||
      # YK: My initial experiments say yes, but let's be sure please
 | 
			
		||||
      enc = str.encoding
 | 
			
		||||
      enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
 | 
			
		||||
      str.dup.force_encoding(Encoding::ASCII_8BIT).gsub(escaped) { |match| [match[1, 2].hex].pack("C") }.force_encoding(enc)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module URI
 | 
			
		||||
  class << self
 | 
			
		||||
    def parser
 | 
			
		||||
      ActiveSupport::Deprecation.warn(<<-MSG.squish)
 | 
			
		||||
        URI.parser is deprecated and will be removed in Rails 7.0.
 | 
			
		||||
        Use `URI::DEFAULT_PARSER` instead.
 | 
			
		||||
      MSG
 | 
			
		||||
      URI::DEFAULT_PARSER
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,210 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/callbacks"
 | 
			
		||||
require "active_support/core_ext/enumerable"
 | 
			
		||||
require "active_support/core_ext/module/delegation"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
 | 
			
		||||
  # before and after each request. This allows you to keep all the per-request attributes easily
 | 
			
		||||
  # available to the whole system.
 | 
			
		||||
  #
 | 
			
		||||
  # The following full app-like example demonstrates how to use a Current class to
 | 
			
		||||
  # facilitate easy access to the global, per-request attributes without passing them deeply
 | 
			
		||||
  # around everywhere:
 | 
			
		||||
  #
 | 
			
		||||
  #   # app/models/current.rb
 | 
			
		||||
  #   class Current < ActiveSupport::CurrentAttributes
 | 
			
		||||
  #     attribute :account, :user
 | 
			
		||||
  #     attribute :request_id, :user_agent, :ip_address
 | 
			
		||||
  #
 | 
			
		||||
  #     resets { Time.zone = nil }
 | 
			
		||||
  #
 | 
			
		||||
  #     def user=(user)
 | 
			
		||||
  #       super
 | 
			
		||||
  #       self.account = user.account
 | 
			
		||||
  #       Time.zone    = user.time_zone
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   # app/controllers/concerns/authentication.rb
 | 
			
		||||
  #   module Authentication
 | 
			
		||||
  #     extend ActiveSupport::Concern
 | 
			
		||||
  #
 | 
			
		||||
  #     included do
 | 
			
		||||
  #       before_action :authenticate
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  #     private
 | 
			
		||||
  #       def authenticate
 | 
			
		||||
  #         if authenticated_user = User.find_by(id: cookies.encrypted[:user_id])
 | 
			
		||||
  #           Current.user = authenticated_user
 | 
			
		||||
  #         else
 | 
			
		||||
  #           redirect_to new_session_url
 | 
			
		||||
  #         end
 | 
			
		||||
  #       end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   # app/controllers/concerns/set_current_request_details.rb
 | 
			
		||||
  #   module SetCurrentRequestDetails
 | 
			
		||||
  #     extend ActiveSupport::Concern
 | 
			
		||||
  #
 | 
			
		||||
  #     included do
 | 
			
		||||
  #       before_action do
 | 
			
		||||
  #         Current.request_id = request.uuid
 | 
			
		||||
  #         Current.user_agent = request.user_agent
 | 
			
		||||
  #         Current.ip_address = request.ip
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class ApplicationController < ActionController::Base
 | 
			
		||||
  #     include Authentication
 | 
			
		||||
  #     include SetCurrentRequestDetails
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class MessagesController < ApplicationController
 | 
			
		||||
  #     def create
 | 
			
		||||
  #       Current.account.messages.create(message_params)
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class Message < ApplicationRecord
 | 
			
		||||
  #     belongs_to :creator, default: -> { Current.user }
 | 
			
		||||
  #     after_create { |message| Event.create(record: message) }
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   class Event < ApplicationRecord
 | 
			
		||||
  #     before_create do
 | 
			
		||||
  #       self.request_id = Current.request_id
 | 
			
		||||
  #       self.user_agent = Current.user_agent
 | 
			
		||||
  #       self.ip_address = Current.ip_address
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  # A word of caution: It's easy to overdo a global singleton like Current and tangle your model as a result.
 | 
			
		||||
  # Current should only be used for a few, top-level globals, like account, user, and request details.
 | 
			
		||||
  # The attributes stuck in Current should be used by more or less all actions on all requests. If you start
 | 
			
		||||
  # sticking controller-specific attributes in there, you're going to create a mess.
 | 
			
		||||
  class CurrentAttributes
 | 
			
		||||
    include ActiveSupport::Callbacks
 | 
			
		||||
    define_callbacks :reset
 | 
			
		||||
 | 
			
		||||
    class << self
 | 
			
		||||
      # Returns singleton instance for this class in this thread. If none exists, one is created.
 | 
			
		||||
      def instance
 | 
			
		||||
        current_instances[current_instances_key] ||= new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Declares one or more attributes that will be given both class and instance accessor methods.
 | 
			
		||||
      def attribute(*names)
 | 
			
		||||
        generated_attribute_methods.module_eval do
 | 
			
		||||
          names.each do |name|
 | 
			
		||||
            define_method(name) do
 | 
			
		||||
              attributes[name.to_sym]
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            define_method("#{name}=") do |attribute|
 | 
			
		||||
              attributes[name.to_sym] = attribute
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        names.each do |name|
 | 
			
		||||
          define_singleton_method(name) do
 | 
			
		||||
            instance.public_send(name)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          define_singleton_method("#{name}=") do |attribute|
 | 
			
		||||
            instance.public_send("#{name}=", attribute)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Calls this block before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
 | 
			
		||||
      def before_reset(&block)
 | 
			
		||||
        set_callback :reset, :before, &block
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
 | 
			
		||||
      def resets(&block)
 | 
			
		||||
        set_callback :reset, :after, &block
 | 
			
		||||
      end
 | 
			
		||||
      alias_method :after_reset, :resets
 | 
			
		||||
 | 
			
		||||
      delegate :set, :reset, to: :instance
 | 
			
		||||
 | 
			
		||||
      def reset_all # :nodoc:
 | 
			
		||||
        current_instances.each_value(&:reset)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def clear_all # :nodoc:
 | 
			
		||||
        reset_all
 | 
			
		||||
        current_instances.clear
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
        def generated_attribute_methods
 | 
			
		||||
          @generated_attribute_methods ||= Module.new.tap { |mod| include mod }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def current_instances
 | 
			
		||||
          Thread.current[:current_attributes_instances] ||= {}
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def current_instances_key
 | 
			
		||||
          @current_instances_key ||= name.to_sym
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def method_missing(name, *args, &block)
 | 
			
		||||
          # Caches the method definition as a singleton method of the receiver.
 | 
			
		||||
          #
 | 
			
		||||
          # By letting #delegate handle it, we avoid an enclosure that'll capture args.
 | 
			
		||||
          singleton_class.delegate name, to: :instance
 | 
			
		||||
 | 
			
		||||
          send(name, *args, &block)
 | 
			
		||||
        end
 | 
			
		||||
        ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    attr_accessor :attributes
 | 
			
		||||
 | 
			
		||||
    def initialize
 | 
			
		||||
      @attributes = {}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Expose one or more attributes within a block. Old values are returned after the block concludes.
 | 
			
		||||
    # Example demonstrating the common use of needing to set Current attributes outside the request-cycle:
 | 
			
		||||
    #
 | 
			
		||||
    #   class Chat::PublicationJob < ApplicationJob
 | 
			
		||||
    #     def perform(attributes, room_number, creator)
 | 
			
		||||
    #       Current.set(person: creator) do
 | 
			
		||||
    #         Chat::Publisher.publish(attributes: attributes, room_number: room_number)
 | 
			
		||||
    #       end
 | 
			
		||||
    #     end
 | 
			
		||||
    #   end
 | 
			
		||||
    def set(set_attributes)
 | 
			
		||||
      old_attributes = compute_attributes(set_attributes.keys)
 | 
			
		||||
      assign_attributes(set_attributes)
 | 
			
		||||
      yield
 | 
			
		||||
    ensure
 | 
			
		||||
      assign_attributes(old_attributes)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
 | 
			
		||||
    def reset
 | 
			
		||||
      run_callbacks :reset do
 | 
			
		||||
        self.attributes = {}
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
      def assign_attributes(new_attributes)
 | 
			
		||||
        new_attributes.each { |key, value| public_send("#{key}=", value) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def compute_attributes(keys)
 | 
			
		||||
        keys.index_with { |key| public_send(key) }
 | 
			
		||||
      end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,13 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport::CurrentAttributes::TestHelper # :nodoc:
 | 
			
		||||
  def before_setup
 | 
			
		||||
    ActiveSupport::CurrentAttributes.reset_all
 | 
			
		||||
    super
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def after_teardown
 | 
			
		||||
    super
 | 
			
		||||
    ActiveSupport::CurrentAttributes.reset_all
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,51 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "singleton"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # \Deprecation specifies the API used by Rails to deprecate methods, instance
 | 
			
		||||
  # variables, objects and constants.
 | 
			
		||||
  class Deprecation
 | 
			
		||||
    # active_support.rb sets an autoload for ActiveSupport::Deprecation.
 | 
			
		||||
    #
 | 
			
		||||
    # If these requires were at the top of the file the constant would not be
 | 
			
		||||
    # defined by the time their files were loaded. Since some of them reopen
 | 
			
		||||
    # ActiveSupport::Deprecation its autoload would be triggered, resulting in
 | 
			
		||||
    # a circular require warning for active_support/deprecation.rb.
 | 
			
		||||
    #
 | 
			
		||||
    # So, we define the constant first, and load dependencies later.
 | 
			
		||||
    require "active_support/deprecation/instance_delegator"
 | 
			
		||||
    require "active_support/deprecation/behaviors"
 | 
			
		||||
    require "active_support/deprecation/reporting"
 | 
			
		||||
    require "active_support/deprecation/disallowed"
 | 
			
		||||
    require "active_support/deprecation/constant_accessor"
 | 
			
		||||
    require "active_support/deprecation/method_wrappers"
 | 
			
		||||
    require "active_support/deprecation/proxy_wrappers"
 | 
			
		||||
    require "active_support/core_ext/module/deprecation"
 | 
			
		||||
    require "concurrent/atomic/thread_local_var"
 | 
			
		||||
 | 
			
		||||
    include Singleton
 | 
			
		||||
    include InstanceDelegator
 | 
			
		||||
    include Behavior
 | 
			
		||||
    include Reporting
 | 
			
		||||
    include Disallowed
 | 
			
		||||
    include MethodWrapper
 | 
			
		||||
 | 
			
		||||
    # The version number in which the deprecated behavior will be removed, by default.
 | 
			
		||||
    attr_accessor :deprecation_horizon
 | 
			
		||||
 | 
			
		||||
    # It accepts two parameters on initialization. The first is a version of library
 | 
			
		||||
    # and the second is a library name.
 | 
			
		||||
    #
 | 
			
		||||
    #   ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
 | 
			
		||||
    def initialize(deprecation_horizon = "7.0", gem_name = "Rails")
 | 
			
		||||
      self.gem_name = gem_name
 | 
			
		||||
      self.deprecation_horizon = deprecation_horizon
 | 
			
		||||
      # By default, warnings are not silenced and debugging is off.
 | 
			
		||||
      self.silenced = false
 | 
			
		||||
      self.debug = false
 | 
			
		||||
      @silenced_thread = Concurrent::ThreadLocalVar.new(false)
 | 
			
		||||
      @explicitly_allowed_warnings = Concurrent::ThreadLocalVar.new(nil)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,122 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/notifications"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  # Raised when <tt>ActiveSupport::Deprecation::Behavior#behavior</tt> is set with <tt>:raise</tt>.
 | 
			
		||||
  # You would set <tt>:raise</tt>, as a behavior to raise errors and proactively report exceptions from deprecations.
 | 
			
		||||
  class DeprecationException < StandardError
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Deprecation
 | 
			
		||||
    # Default warning behaviors per Rails.env.
 | 
			
		||||
    DEFAULT_BEHAVIORS = {
 | 
			
		||||
      raise: ->(message, callstack, deprecation_horizon, gem_name) {
 | 
			
		||||
        e = DeprecationException.new(message)
 | 
			
		||||
        e.set_backtrace(callstack.map(&:to_s))
 | 
			
		||||
        raise e
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      stderr: ->(message, callstack, deprecation_horizon, gem_name) {
 | 
			
		||||
        $stderr.puts(message)
 | 
			
		||||
        $stderr.puts callstack.join("\n  ") if debug
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      log: ->(message, callstack, deprecation_horizon, gem_name) {
 | 
			
		||||
        logger =
 | 
			
		||||
            if defined?(Rails.logger) && Rails.logger
 | 
			
		||||
              Rails.logger
 | 
			
		||||
            else
 | 
			
		||||
              require "active_support/logger"
 | 
			
		||||
              ActiveSupport::Logger.new($stderr)
 | 
			
		||||
            end
 | 
			
		||||
        logger.warn message
 | 
			
		||||
        logger.debug callstack.join("\n  ") if debug
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      notify: ->(message, callstack, deprecation_horizon, gem_name) {
 | 
			
		||||
        notification_name = "deprecation.#{gem_name.underscore.tr('/', '_')}"
 | 
			
		||||
        ActiveSupport::Notifications.instrument(notification_name,
 | 
			
		||||
                                                message: message,
 | 
			
		||||
                                                callstack: callstack,
 | 
			
		||||
                                                gem_name: gem_name,
 | 
			
		||||
                                                deprecation_horizon: deprecation_horizon)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      silence: ->(message, callstack, deprecation_horizon, gem_name) { },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Behavior module allows to determine how to display deprecation messages.
 | 
			
		||||
    # You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
 | 
			
		||||
    # constant. Available behaviors are:
 | 
			
		||||
    #
 | 
			
		||||
    # [+raise+]   Raise <tt>ActiveSupport::DeprecationException</tt>.
 | 
			
		||||
    # [+stderr+]  Log all deprecation warnings to <tt>$stderr</tt>.
 | 
			
		||||
    # [+log+]     Log all deprecation warnings to +Rails.logger+.
 | 
			
		||||
    # [+notify+]  Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
 | 
			
		||||
    # [+silence+] Do nothing.
 | 
			
		||||
    #
 | 
			
		||||
    # Setting behaviors only affects deprecations that happen after boot time.
 | 
			
		||||
    # For more information you can read the documentation of the +behavior=+ method.
 | 
			
		||||
    module Behavior
 | 
			
		||||
      # Whether to print a backtrace along with the warning.
 | 
			
		||||
      attr_accessor :debug
 | 
			
		||||
 | 
			
		||||
      # Returns the current behavior or if one isn't set, defaults to +:stderr+.
 | 
			
		||||
      def behavior
 | 
			
		||||
        @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns the current behavior for disallowed deprecations or if one isn't set, defaults to +:raise+.
 | 
			
		||||
      def disallowed_behavior
 | 
			
		||||
        @disallowed_behavior ||= [DEFAULT_BEHAVIORS[:raise]]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Sets the behavior to the specified value. Can be a single value, array,
 | 
			
		||||
      # or an object that responds to +call+.
 | 
			
		||||
      #
 | 
			
		||||
      # Available behaviors:
 | 
			
		||||
      #
 | 
			
		||||
      # [+raise+]   Raise <tt>ActiveSupport::DeprecationException</tt>.
 | 
			
		||||
      # [+stderr+]  Log all deprecation warnings to <tt>$stderr</tt>.
 | 
			
		||||
      # [+log+]     Log all deprecation warnings to +Rails.logger+.
 | 
			
		||||
      # [+notify+]  Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
 | 
			
		||||
      # [+silence+] Do nothing.
 | 
			
		||||
      #
 | 
			
		||||
      # Setting behaviors only affects deprecations that happen after boot time.
 | 
			
		||||
      # Deprecation warnings raised by gems are not affected by this setting
 | 
			
		||||
      # because they happen before Rails boots up.
 | 
			
		||||
      #
 | 
			
		||||
      #   ActiveSupport::Deprecation.behavior = :stderr
 | 
			
		||||
      #   ActiveSupport::Deprecation.behavior = [:stderr, :log]
 | 
			
		||||
      #   ActiveSupport::Deprecation.behavior = MyCustomHandler
 | 
			
		||||
      #   ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
 | 
			
		||||
      #     # custom stuff
 | 
			
		||||
      #   }
 | 
			
		||||
      def behavior=(behavior)
 | 
			
		||||
        @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Sets the behavior for disallowed deprecations (those configured by
 | 
			
		||||
      # ActiveSupport::Deprecation.disallowed_warnings=) to the specified
 | 
			
		||||
      # value. As with +behavior=+, this can be a single value, array, or an
 | 
			
		||||
      # object that responds to +call+.
 | 
			
		||||
      def disallowed_behavior=(behavior)
 | 
			
		||||
        @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
        def arity_coerce(behavior)
 | 
			
		||||
          unless behavior.respond_to?(:call)
 | 
			
		||||
            raise ArgumentError, "#{behavior.inspect} is not a valid deprecation behavior."
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if behavior.arity == 4 || behavior.arity == -1
 | 
			
		||||
            behavior
 | 
			
		||||
          else
 | 
			
		||||
            -> message, callstack, _, _ { behavior.call(message, callstack) }
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  class Deprecation
 | 
			
		||||
    # DeprecatedConstantAccessor transforms a constant into a deprecated one by
 | 
			
		||||
    # hooking +const_missing+.
 | 
			
		||||
    #
 | 
			
		||||
    # It takes the names of an old (deprecated) constant and of a new constant
 | 
			
		||||
    # (both in string form) and optionally a deprecator. The deprecator defaults
 | 
			
		||||
    # to +ActiveSupport::Deprecator+ if none is specified.
 | 
			
		||||
    #
 | 
			
		||||
    # The deprecated constant now returns the same object as the new one rather
 | 
			
		||||
    # than a proxy object, so it can be used transparently in +rescue+ blocks
 | 
			
		||||
    # etc.
 | 
			
		||||
    #
 | 
			
		||||
    #   PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
 | 
			
		||||
    #
 | 
			
		||||
    #   # (In a later update, the original implementation of `PLANETS` has been removed.)
 | 
			
		||||
    #
 | 
			
		||||
    #   PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
 | 
			
		||||
    #   include ActiveSupport::Deprecation::DeprecatedConstantAccessor
 | 
			
		||||
    #   deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
 | 
			
		||||
    #
 | 
			
		||||
    #   PLANETS.map { |planet| planet.capitalize }
 | 
			
		||||
    #   # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
 | 
			
		||||
    #        (Backtrace information…)
 | 
			
		||||
    #        ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
 | 
			
		||||
    module DeprecatedConstantAccessor
 | 
			
		||||
      def self.included(base)
 | 
			
		||||
        require "active_support/inflector/methods"
 | 
			
		||||
 | 
			
		||||
        extension = Module.new do
 | 
			
		||||
          def const_missing(missing_const_name)
 | 
			
		||||
            if class_variable_defined?(:@@_deprecated_constants)
 | 
			
		||||
              if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
 | 
			
		||||
                replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
 | 
			
		||||
                return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
            super
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
 | 
			
		||||
            class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
 | 
			
		||||
            class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        base.singleton_class.prepend extension
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,56 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  class Deprecation
 | 
			
		||||
    module Disallowed
 | 
			
		||||
      # Sets the criteria used to identify deprecation messages which should be
 | 
			
		||||
      # disallowed. Can be an array containing strings, symbols, or regular
 | 
			
		||||
      # expressions. (Symbols are treated as strings). These are compared against
 | 
			
		||||
      # the text of the generated deprecation warning.
 | 
			
		||||
      #
 | 
			
		||||
      # Additionally the scalar symbol +:all+ may be used to treat all
 | 
			
		||||
      # deprecations as disallowed.
 | 
			
		||||
      #
 | 
			
		||||
      # Deprecations matching a substring or regular expression will be handled
 | 
			
		||||
      # using the configured +ActiveSupport::Deprecation.disallowed_behavior+
 | 
			
		||||
      # rather than +ActiveSupport::Deprecation.behavior+
 | 
			
		||||
      attr_writer :disallowed_warnings
 | 
			
		||||
 | 
			
		||||
      # Returns the configured criteria used to identify deprecation messages
 | 
			
		||||
      # which should be treated as disallowed.
 | 
			
		||||
      def disallowed_warnings
 | 
			
		||||
        @disallowed_warnings ||= []
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
        def deprecation_disallowed?(message)
 | 
			
		||||
          disallowed = ActiveSupport::Deprecation.disallowed_warnings
 | 
			
		||||
          return false if explicitly_allowed?(message)
 | 
			
		||||
          return true if disallowed == :all
 | 
			
		||||
          disallowed.any? do |rule|
 | 
			
		||||
            case rule
 | 
			
		||||
            when String, Symbol
 | 
			
		||||
              message.include?(rule.to_s)
 | 
			
		||||
            when Regexp
 | 
			
		||||
              rule.match?(message)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def explicitly_allowed?(message)
 | 
			
		||||
          allowances = @explicitly_allowed_warnings.value
 | 
			
		||||
          return false unless allowances
 | 
			
		||||
          return true if allowances == :all
 | 
			
		||||
          allowances = [allowances] unless allowances.kind_of?(Array)
 | 
			
		||||
          allowances.any? do |rule|
 | 
			
		||||
            case rule
 | 
			
		||||
            when String, Symbol
 | 
			
		||||
              message.include?(rule.to_s)
 | 
			
		||||
            when Regexp
 | 
			
		||||
              rule.match?(message)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "active_support/core_ext/module/delegation"
 | 
			
		||||
 | 
			
		||||
module ActiveSupport
 | 
			
		||||
  class Deprecation
 | 
			
		||||
    module InstanceDelegator # :nodoc:
 | 
			
		||||
      def self.included(base)
 | 
			
		||||
        base.extend(ClassMethods)
 | 
			
		||||
        base.singleton_class.prepend(OverrideDelegators)
 | 
			
		||||
        base.public_class_method :new
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      module ClassMethods # :nodoc:
 | 
			
		||||
        def include(included_module)
 | 
			
		||||
          included_module.instance_methods.each { |m| method_added(m) }
 | 
			
		||||
          super
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def method_added(method_name)
 | 
			
		||||
          singleton_class.delegate(method_name, to: :instance)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      module OverrideDelegators # :nodoc:
 | 
			
		||||
        def warn(message = nil, callstack = nil)
 | 
			
		||||
          callstack ||= caller_locations(2)
 | 
			
		||||
          super
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
 | 
			
		||||
          caller_backtrace ||= caller_locations(2)
 | 
			
		||||
          super
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user