brew vendor-gems: commit updates.

This commit is contained in:
BrewTestBot 2020-12-10 06:38:17 +00:00
parent 1849ccfbe0
commit af9fc474f2
301 changed files with 8663 additions and 7509 deletions

View File

@ -6,10 +6,9 @@ path = File.expand_path('..', __FILE__)
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.7/lib/concurrent-ruby"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.8.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.14.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.8/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-2.0.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.4.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.3.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/bindata-2.4.8/lib"
$:.unshift "#{path}/"

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
require "active_support/deprecation"
ActiveSupport::Deprecation.warn "Ruby 2.5+ (required by Rails 6) provides Array#append and Array#prepend natively, so requiring active_support/core_ext/array/prepend_and_append is no longer necessary. Requiring it will raise LoadError in Rails 6.1."

View File

@ -1,54 +0,0 @@
# frozen_string_literal: true
class Class
begin
# Test if this Ruby supports each_object against singleton_class
ObjectSpace.each_object(Numeric.singleton_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
descendants = []
ObjectSpace.each_object(singleton_class) do |k|
next if k.singleton_class?
descendants.unshift k unless k == self
end
descendants
end
rescue StandardError # JRuby 9.0.4.0 and earlier
def descendants
descendants = []
ObjectSpace.each_object(Class) do |k|
descendants.unshift k if k < self
end
descendants.uniq!
descendants
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
subclasses, chain = [], descendants
chain.each do |k|
subclasses << k unless chain.any? { |c| c > k }
end
subclasses
end
end

View File

@ -1,16 +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
end
end

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
require "active_support/deprecation"
ActiveSupport::Deprecation.warn "Ruby 2.5+ (required by Rails 6) provides Hash#compact and Hash#compact! natively, so requiring active_support/core_ext/hash/compact is no longer necessary. Requiring it will raise LoadError in Rails 6.1."

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
require "active_support/deprecation"
ActiveSupport::Deprecation.warn "Ruby 2.5+ (required by Rails 6) provides Hash#transform_values natively, so requiring active_support/core_ext/hash/transform_values is no longer necessary. Requiring it will raise LoadError in Rails 6.1."

View File

@ -1,6 +0,0 @@
# frozen_string_literal: true
require "active_support/core_ext/module/anonymous"
require "active_support/core_ext/string/inflections"
ActiveSupport::Deprecation.warn("reachable is deprecated and will be removed from the framework.")

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
require "active_support/deprecation"
ActiveSupport::Deprecation.warn "Ruby 2.5+ (required by Rails 6) provides Numeric#positive? and Numeric#negative? natively, so requiring active_support/core_ext/numeric/inquiry is no longer necessary. Requiring it will raise LoadError in Rails 6.1."

View File

@ -1,9 +0,0 @@
# frozen_string_literal: true
require "active_support/deprecation"
ActiveSupport::Deprecation.warn "You have required `active_support/core_ext/range/include_range`. " \
"This file will be removed in Rails 6.1. You should require `active_support/core_ext/range/compare_range` " \
"instead."
require "active_support/core_ext/range/compare_range"

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
class Regexp #:nodoc:
def multiline?
options & MULTILINE == MULTILINE
end
end

View File

@ -1,6 +0,0 @@
# frozen_string_literal: true
class String
alias_method :starts_with?, :start_with?
alias_method :ends_with?, :end_with?
end

View File

@ -1,234 +0,0 @@
# frozen_string_literal: true
require "set"
require "pathname"
require "concurrent/atomic/atomic_boolean"
module ActiveSupport
# Allows you to "listen" to changes in a file system.
# The evented file updater does not hit disk when checking for updates
# instead it uses platform specific file system events to trigger a change
# in state.
#
# The file checker takes an array of files to watch or a hash specifying directories
# and file extensions to watch. It also takes a block that is called when
# EventedFileUpdateChecker#execute is run or when EventedFileUpdateChecker#execute_if_updated
# is run and there have been changes to the file system.
#
# Note: Forking will cause the first call to `updated?` to return `true`.
#
# Example:
#
# checker = ActiveSupport::EventedFileUpdateChecker.new(["/tmp/foo"]) { puts "changed" }
# checker.updated?
# # => false
# checker.execute_if_updated
# # => nil
#
# FileUtils.touch("/tmp/foo")
#
# checker.updated?
# # => true
# checker.execute_if_updated
# # => "changed"
#
class EventedFileUpdateChecker #:nodoc: all
def initialize(files, dirs = {}, &block)
unless block
raise ArgumentError, "A block is required to initialize an EventedFileUpdateChecker"
end
@ph = PathHelper.new
@files = files.map { |f| @ph.xpath(f) }.to_set
@dirs = {}
dirs.each do |dir, exts|
@dirs[@ph.xpath(dir)] = Array(exts).map { |ext| @ph.normalize_extension(ext) }
end
@block = block
@updated = Concurrent::AtomicBoolean.new(false)
@lcsp = @ph.longest_common_subpath(@dirs.keys)
@pid = Process.pid
@boot_mutex = Mutex.new
dtw = directories_to_watch
@dtw, @missing = dtw.partition(&:exist?)
if @dtw.any?
# Loading listen triggers warnings. These are originated by a legit
# usage of attr_* macros for private attributes, but adds a lot of noise
# to our test suite. Thus, we lazy load it and disable warnings locally.
silence_warnings do
require "listen"
rescue LoadError => e
raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
end
end
boot!
end
def updated?
@boot_mutex.synchronize do
if @pid != Process.pid
boot!
@pid = Process.pid
@updated.make_true
end
end
if @missing.any?(&:exist?)
@boot_mutex.synchronize do
appeared, @missing = @missing.partition(&:exist?)
shutdown!
@dtw += appeared
boot!
@updated.make_true
end
end
@updated.true?
end
def execute
@updated.make_false
@block.call
end
def execute_if_updated
if updated?
yield if block_given?
execute
true
end
end
private
def boot!
normalize_dirs!
unless @dtw.empty?
Listen.to(*@dtw, &method(:changed)).start
end
end
def shutdown!
Listen.stop
end
def normalize_dirs!
@dirs.transform_keys! do |dir|
dir.exist? ? dir.realpath : dir
end
end
def changed(modified, added, removed)
unless updated?
@updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
end
end
def watching?(file)
file = @ph.xpath(file)
if @files.member?(file)
true
elsif file.directory?
false
else
ext = @ph.normalize_extension(file.extname)
file.dirname.ascend do |dir|
matching = @dirs[dir]
if matching && (matching.empty? || matching.include?(ext))
break true
elsif dir == @lcsp || dir.root?
break false
end
end
end
end
def directories_to_watch
dtw = @files.map(&:dirname) + @dirs.keys
dtw.compact!
dtw.uniq!
normalized_gem_paths = Gem.path.map { |path| File.join path, "" }
dtw = dtw.reject do |path|
normalized_gem_paths.any? { |gem_path| path.to_s.start_with?(gem_path) }
end
@ph.filter_out_descendants(dtw)
end
class PathHelper
def xpath(path)
Pathname.new(path).expand_path
end
def normalize_extension(ext)
ext.to_s.sub(/\A\./, "")
end
# Given a collection of Pathname objects returns the longest subpath
# common to all of them, or +nil+ if there is none.
def longest_common_subpath(paths)
return if paths.empty?
lcsp = Pathname.new(paths[0])
paths[1..-1].each do |path|
until ascendant_of?(lcsp, path)
if lcsp.root?
# If we get here a root directory is not an ascendant of path.
# This may happen if there are paths in different drives on
# Windows.
return
else
lcsp = lcsp.parent
end
end
end
lcsp
end
# Returns the deepest existing ascendant, which could be the argument itself.
def existing_parent(dir)
dir.ascend do |ascendant|
break ascendant if ascendant.directory?
end
end
# Filters out directories which are descendants of others in the collection (stable).
def filter_out_descendants(dirs)
return dirs if dirs.length < 2
dirs_sorted_by_nparts = dirs.sort_by { |dir| dir.each_filename.to_a.length }
descendants = []
until dirs_sorted_by_nparts.empty?
dir = dirs_sorted_by_nparts.shift
dirs_sorted_by_nparts.reject! do |possible_descendant|
ascendant_of?(dir, possible_descendant) && descendants << possible_descendant
end
end
# Array#- preserves order.
dirs - descendants
end
private
def ascendant_of?(base, other)
base != other && other.ascend do |ascendant|
break true if base == ascendant
end
end
end
end
end

View File

@ -1,45 +0,0 @@
# frozen_string_literal: true
require "active_support/concern"
require "active_support/core_ext/module/attribute_accessors"
require "active_support/logger_thread_safe_level"
module LoggerSilence
extend ActiveSupport::Concern
included do
ActiveSupport::Deprecation.warn(
"Including LoggerSilence is deprecated and will be removed in Rails 6.1. " \
"Please use `ActiveSupport::LoggerSilence` instead"
)
include ActiveSupport::LoggerSilence
end
end
module ActiveSupport
module LoggerSilence
extend ActiveSupport::Concern
included do
cattr_accessor :silencer, default: true
include ActiveSupport::LoggerThreadSafeLevel
end
# Silences the logger for the duration of the block.
def silence(temporary_level = Logger::ERROR)
if silencer
begin
old_local_level = local_level
self.local_level = temporary_level
yield self
ensure
self.local_level = old_local_level
end
else
yield self
end
end
end
end

View File

@ -1,56 +0,0 @@
# frozen_string_literal: true
require "active_support/concern"
require "active_support/core_ext/module/attribute_accessors"
require "concurrent"
require "fiber"
module ActiveSupport
module LoggerThreadSafeLevel # :nodoc:
extend ActiveSupport::Concern
included do
cattr_accessor :local_levels, default: Concurrent::Map.new(initial_capacity: 2), instance_accessor: false
end
Logger::Severity.constants.each do |severity|
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
def #{severity.downcase}? # def debug?
Logger::#{severity} >= level # DEBUG >= level
end # end
EOT
end
def after_initialize
ActiveSupport::Deprecation.warn(
"Logger don't need to call #after_initialize directly anymore. It will be deprecated without replacement in " \
"Rails 6.1."
)
end
def local_log_id
Fiber.current.__id__
end
def local_level
self.class.local_levels[local_log_id]
end
def local_level=(level)
if level
self.class.local_levels[local_log_id] = level
else
self.class.local_levels.delete(local_log_id)
end
end
def level
local_level || super
end
def add(severity, message = nil, progname = nil, &block) # :nodoc:
return true if @logdev.nil? || (severity || UNKNOWN) < level
super
end
end
end

View File

@ -1,31 +0,0 @@
# frozen_string_literal: true
require "digest/sha2"
module ActiveSupport
module SecurityUtils
# Constant time string comparison, for fixed length strings.
#
# The values compared should be of fixed length, such as strings
# that have already been processed by HMAC. Raises in case of length mismatch.
def fixed_length_secure_compare(a, b)
raise ArgumentError, "string length mismatch." unless a.bytesize == b.bytesize
l = a.unpack "C#{a.bytesize}"
res = 0
b.each_byte { |byte| res |= byte ^ l.shift }
res == 0
end
module_function :fixed_length_secure_compare
# Constant time string comparison, for variable length strings.
#
# The values are first processed by SHA256, so that we don't leak length info
# via timing attacks.
def secure_compare(a, b)
fixed_length_secure_compare(::Digest::SHA256.digest(a), ::Digest::SHA256.digest(b)) && a == b
end
module_function :secure_compare
end
end

View File

@ -1,5 +1,7 @@
# 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:
@ -34,11 +36,11 @@ module ActiveSupport
private
def respond_to_missing?(name, include_private = false)
(name[-1] == "?") || super
name.end_with?("?") || super
end
def method_missing(name, *args)
if name[-1] == "?"
if name.end_with?("?")
any?(name[0..-2])
else
super

View File

@ -16,7 +16,7 @@ module ActiveSupport
#
# bc = ActiveSupport::BacktraceCleaner.new
# bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
# bc.add_silencer { |line| line =~ /puma|rubygems/ } # skip any lines from puma or rubygems
# 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)
@ -65,7 +65,7 @@ module ActiveSupport
# 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| line =~ /puma/ }
# backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
def add_silencer(&block)
@silencers << block
end
@ -91,7 +91,7 @@ module ActiveSupport
gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
return if gems_paths.empty?
gems_regexp = %r{(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
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

View File

@ -41,7 +41,7 @@ module ActiveSupport
result = nil
ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
logger.send(options[:level], "%s (%.1fms)" % [ message, ms ])
logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
result
else
yield

View File

@ -4,10 +4,7 @@ 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/kernel/reporting"
require "active_support/core_ext/kernel/singleton_class"
require "active_support/core_ext/string/filters"
require "active_support/deprecation"
require "thread"
module ActiveSupport
@ -103,32 +100,6 @@ module ActiveSupport
env = Filters::Environment.new(self, false, nil)
next_sequence = callbacks.compile
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 && skipped.first
break env.value
end
end
# Common case: no 'around' callbacks defined
if next_sequence.final?
next_sequence.invoke_before(env)
@ -136,6 +107,33 @@ module ActiveSupport
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
@ -145,7 +143,7 @@ module ActiveSupport
# 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)
def halted_callback_hook(filter, name)
end
module Conditionals # :nodoc:
@ -161,17 +159,17 @@ module ActiveSupport
Environment = Struct.new(:target, :halted, :value)
class Before
def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter)
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)
halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
else
halting(callback_sequence, user_callback, halted_lambda, filter)
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)
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
@ -181,7 +179,7 @@ module ActiveSupport
result_lambda = -> { user_callback.call target, value }
env.halted = halted_lambda.call(target, result_lambda)
if env.halted
target.send :halted_callback_hook, filter
target.send :halted_callback_hook, filter, name
end
end
@ -190,7 +188,7 @@ module ActiveSupport
end
private_class_method :halting_and_conditional
def self.halting(callback_sequence, user_callback, halted_lambda, filter)
def self.halting(callback_sequence, user_callback, halted_lambda, filter, name)
callback_sequence.before do |env|
target = env.target
value = env.value
@ -199,9 +197,8 @@ module ActiveSupport
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
target.send :halted_callback_hook, filter, name
end
end
@ -300,8 +297,8 @@ module ActiveSupport
@kind = kind
@filter = filter
@key = compute_identifier filter
@if = check_conditionals(Array(options[:if]))
@unless = check_conditionals(Array(options[:unless]))
@if = check_conditionals(options[:if])
@unless = check_conditionals(options[:unless])
end
def filter; @key; end
@ -339,7 +336,7 @@ module ActiveSupport
case kind
when :before
Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter)
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
@ -352,7 +349,13 @@ module ActiveSupport
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
@ -361,7 +364,7 @@ module ActiveSupport
MSG
end
conditionals
conditionals.freeze
end
def compute_identifier(filter)
@ -403,21 +406,17 @@ module ActiveSupport
# The actual invocation is left up to the caller to minimize
# call stack pollution.
def expand(target, value, block)
result = @arguments.map { |arg|
expanded = [@override_target || target, @override_block || block, @method_name]
@arguments.each do |arg|
case arg
when :value; value
when :target; target
when :block; block || raise(ArgumentError)
when :value then expanded << value
when :target then expanded << target
when :block then expanded << (block || raise(ArgumentError))
end
}
end
result.unshift @method_name
result.unshift @override_block || block
result.unshift @override_target || target
# target, block, method, *arguments = result
# target.send(method, *arguments, &block)
result
expanded
end
# Return a lambda that will make this call when given the input
@ -845,8 +844,18 @@ module ActiveSupport
__callbacks[name.to_sym]
end
def set_callbacks(name, callbacks) # :nodoc:
self.__callbacks = __callbacks.merge(name.to_sym => callbacks)
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

View File

@ -19,7 +19,7 @@ module ActiveSupport
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
# written as:
#
# require 'active_support/concern'
# require "active_support/concern"
#
# module M
# extend ActiveSupport::Concern
@ -76,7 +76,7 @@ module ActiveSupport
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
# module dependencies are properly resolved:
#
# require 'active_support/concern'
# require "active_support/concern"
#
# module Foo
# extend ActiveSupport::Concern
@ -99,6 +99,14 @@ module ActiveSupport
# 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
@ -106,6 +114,12 @@ module ActiveSupport
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
@ -123,6 +137,19 @@ module ActiveSupport
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.
@ -140,6 +167,23 @@ module ActiveSupport
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.
#

View File

@ -5,7 +5,7 @@ require "active_support/ordered_options"
module ActiveSupport
# Configurable provides a <tt>config</tt> method to store and retrieve
# configuration options as an <tt>OrderedHash</tt>.
# configuration options as an <tt>OrderedOptions</tt>.
module Configurable
extend ActiveSupport::Concern
@ -124,9 +124,9 @@ module ActiveSupport
private :config_accessor
end
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
# Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
#
# require 'active_support/configurable'
# require "active_support/configurable"
#
# class User
# include ActiveSupport::Configurable

View File

@ -0,0 +1,46 @@
# 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)
YAML.load(render(context), **options) || {}
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

View File

@ -10,7 +10,7 @@ class << Benchmark
#
# Benchmark.ms { User.all }
# # => 0.074
def ms
1000 * realtime { yield }
def ms(&block)
1000 * realtime(&block)
end
end

View File

@ -1,8 +1,6 @@
# frozen_string_literal: true
require "active_support/core_ext/kernel/singleton_class"
require "active_support/core_ext/module/redefine_method"
require "active_support/core_ext/array/extract_options"
class Class
# Declare a class-level attribute whose value is inheritable by subclasses.
@ -84,58 +82,50 @@ class Class
# 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
)
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|
singleton_class.silence_redefinition_of_method(name)
define_singleton_method(name) { default }
singleton_class.silence_redefinition_of_method("#{name}?")
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
ivar = "@#{name}".to_sym
singleton_class.silence_redefinition_of_method("#{name}=")
define_singleton_method("#{name}=") do |val|
redefine_singleton_method(name) { val }
if singleton_class?
class_eval do
redefine_method(name) do
if instance_variable_defined? ivar
instance_variable_get ivar
else
singleton_class.send name
end
end
end
end
val
unless name.is_a?(Symbol) || name.is_a?(String)
raise TypeError, "#{name.inspect} is not a symbol nor a string"
end
if instance_reader
redefine_method(name) do
if instance_variable_defined?(ivar)
instance_variable_get ivar
else
self.class.public_send name
end
class_methods << <<~RUBY # In case the method exists and is not public
silence_redefinition_of_method def #{name}
end
RUBY
redefine_method("#{name}?") { !!public_send(name) } if instance_predicate
end
methods << <<~RUBY if instance_reader
silence_redefinition_of_method def #{name}
defined?(@#{name}) ? @#{name} : self.class.#{name}
end
RUBY
if instance_writer
redefine_method("#{name}=") do |val|
instance_variable_set ivar, val
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

View File

@ -0,0 +1,33 @@
# 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

View File

@ -10,6 +10,7 @@ class Date
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)
@ -80,7 +81,7 @@ class Date
# 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.send(form, year, month, day)
::Time.public_send(form, year, month, day)
end
silence_redefinition_of_method :xmlschema

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
require "active_support/core_ext/object/try"
require "active_support/core_ext/date_time/conversions"
module DateAndTime
module Calculations
@ -30,6 +31,18 @@ module DateAndTime
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

View File

@ -0,0 +1,31 @@
# 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

View File

@ -44,7 +44,8 @@ module Enumerable
end
end
# Convert an enumerable to a hash keying it by the block return value.
# Convert an enumerable to a hash, using the block result as the key and the
# element as the value.
#
# people.index_by(&:login)
# # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
@ -61,12 +62,19 @@ module Enumerable
end
end
# Convert an enumerable to a hash keying it with the enumerable items and with the values returned in the block.
# Convert an enumerable to a hash, using the element as the key and the block
# result as the value.
#
# post = Post.new(title: "hey there", body: "what's up?")
#
# %i( title body ).index_with { |attr_name| post.public_send(attr_name) }
# # => { title: "hey there", body: "what's up?" }
#
# If an argument is passed instead of a block, it will be used as the value
# for all elements:
#
# %i( created_at updated_at ).index_with(Time.now)
# # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
def index_with(default = INDEX_WITH_DEFAULT)
if block_given?
result = {}
@ -134,7 +142,7 @@ module Enumerable
excluding(*elements)
end
# Convert an enumerable to an array based on the given key.
# Extract the given key from each element in the enumerable.
#
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
# # => ["David", "Rafael", "Aaron"]
@ -145,9 +153,62 @@ module Enumerable
if keys.many?
map { |element| keys.map { |key| element[key] } }
else
map { |element| element[keys.first] }
key = keys.first
map { |element| element[key] }
end
end
# Extract the given key from the first element in the enumerable.
#
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name)
# # => "David"
#
# [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name)
# # => [1, "David"]
def pick(*keys)
return if none?
if keys.many?
keys.map { |key| first[key] }
else
first[keys.first]
end
end
# Returns a new +Array+ without the blank items.
# Uses Object#blank? for determining if an item is blank.
#
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
# # => [1, 2, true]
#
# Set.new([nil, "", 1, 2])
# # => [2, 1] (or [1, 2])
#
# When called on a +Hash+, returns a new +Hash+ without the blank values.
#
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
# #=> { b: 1, f: true }
def compact_blank
reject(&:blank?)
end
end
class Hash
# Hash#reject has its own definition, so this needs one too.
def compact_blank #:nodoc:
reject { |_k, v| v.blank? }
end
# Removes all blank values from the +Hash+ in place and returns self.
# Uses Object#blank? for determining if a value is blank.
#
# h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
# h.compact_blank!
# # => { b: 1, f: true }
def compact_blank!
# use delete_if rather than reject! because it always returns self even if nothing changed
delete_if { |_k, v| v.blank? }
end
end
class Range #:nodoc:
@ -185,4 +246,15 @@ class Array #:nodoc:
super
end
end
# Removes all blank elements from the +Array+ in place and returns self.
# Uses Object#blank? for determining if an item is blank.
#
# a = [1, "", nil, 2, " ", [], {}, false, true]
# a.compact_blank!
# # => [1, 2, true]
def compact_blank!
# use delete_if rather than reject! because it always returns self even if nothing changed
delete_if(&:blank?)
end
end

View File

@ -1,10 +1,10 @@
# frozen_string_literal: true
require "active_support/xml_mini"
require "active_support/time"
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"
@ -208,7 +208,7 @@ module ActiveSupport
elsif become_empty_string?(value)
""
elsif become_hash?(value)
xml_value = Hash[value.map { |k, v| [k, deep_to_h(v)] }]
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

View File

@ -21,7 +21,7 @@ class Hash
end
private
# support methods for deep transforming nested hashes and arrays
# Support methods for deep transforming nested hashes and arrays.
def _deep_transform_values_in_object(object, &block)
case object
when Hash

View File

@ -11,7 +11,7 @@ class Hash
# @person.update(params[:person].except(:admin))
def except(*keys)
slice(*self.keys - keys)
end
end unless method_defined?(:except)
# Removes the given keys from hash and returns it.
# hash = { a: true, b: false, c: nil }

View File

@ -112,7 +112,7 @@ class Hash
end
private
# support methods for deep transforming nested hashes and arrays
# Support methods for deep transforming nested hashes and arrays.
def _deep_transform_keys_in_object(object, &block)
case object
when Hash

View File

@ -18,8 +18,9 @@ class Hash
# Removes and returns the key/value pairs matching the given keys.
#
# { a: 1, b: 2, c: 3, d: 4 }.extract!(:a, :b) # => {:a=>1, :b=>2}
# { a: 1, b: 2 }.extract!(:a, :x) # => {:a=>1}
# hash = { a: 1, b: 2, c: 3, d: 4 }
# hash.extract!(:a, :b) # => {:a=>1, :b=>2}
# hash # => {:c=>3, :d=>4}
def extract!(*keys)
keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
end

View File

@ -4,6 +4,6 @@ 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.sub(/\.rb$/, "") == path.to_s.sub(/\.rb$/, "")
location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
end
end

View File

@ -1,5 +1,7 @@
# frozen_string_literal: true
require "active_support/core_ext/string/inflections"
module ActiveSupport
module MarshalWithAutoloading # :nodoc:
def load(source, proc = nil)

View File

@ -28,9 +28,9 @@ class Module
end
def attr_internal_define(attr_name, type)
internal_name = attr_internal_ivar_name(attr_name).sub(/\A@/, "")
internal_name = attr_internal_ivar_name(attr_name).delete_prefix("@")
# use native attr_* methods as they are faster on some Ruby implementations
send("attr_#{type}", internal_name)
public_send("attr_#{type}", internal_name)
attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
alias_method attr_name, internal_name
remove_method internal_name

View File

@ -48,28 +48,25 @@ class Module
# end
#
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil)
def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil)
raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
location ||= caller_locations(1, 1).first
definition = []
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@#{sym} = nil unless defined? @@#{sym}
def self.#{sym}
@@#{sym}
end
EOS
definition << "def self.#{sym}; @@#{sym}; end"
if instance_reader && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}
@@#{sym}
end
EOS
definition << "def #{sym}; @@#{sym}; end"
end
sym_default_value = (block_given? && default.nil?) ? yield : default
class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil?
class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
end
module_eval(definition.join(";"), location.path, location.lineno)
end
alias :cattr_reader :mattr_reader
@ -115,28 +112,24 @@ class Module
# end
#
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil)
def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil)
raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
location ||= caller_locations(1, 1).first
definition = []
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@#{sym} = nil unless defined? @@#{sym}
def self.#{sym}=(obj)
@@#{sym} = obj
end
EOS
definition << "def self.#{sym}=(val); @@#{sym} = val; end"
if instance_writer && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
@@#{sym} = obj
end
EOS
definition << "def #{sym}=(val); @@#{sym} = val; end"
end
sym_default_value = (block_given? && default.nil?) ? yield : default
send("#{sym}=", sym_default_value) unless sym_default_value.nil?
class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
end
module_eval(definition.join(";"), location.path, location.lineno)
end
alias :cattr_writer :mattr_writer
@ -205,8 +198,9 @@ class Module
#
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, &blk)
mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default)
location = caller_locations(1, 1).first
mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, location: location, &blk)
mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default, location: location)
end
alias :cattr_accessor :mattr_accessor
end

View File

@ -33,7 +33,7 @@ class Module
# end
#
# Current.new.user # => NoMethodError
def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true) # :nodoc:
def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil) # :nodoc:
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
@ -52,6 +52,8 @@ class Module
end
EOS
end
Thread.current["attr_" + name + "_#{sym}"] = default unless default.nil?
end
end
alias :thread_cattr_reader :thread_mattr_reader
@ -74,7 +76,7 @@ class Module
# end
#
# Current.new.user = "DHH" # => NoMethodError
def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true) # :nodoc:
def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil) # :nodoc:
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
@ -93,6 +95,8 @@ class Module
end
EOS
end
public_send("#{sym}=", default) unless default.nil?
end
end
alias :thread_cattr_writer :thread_mattr_writer
@ -136,8 +140,8 @@ class Module
#
# Current.new.user = "DHH" # => NoMethodError
# Current.new.user # => NoMethodError
def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true)
thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor)
def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default)
thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
end
alias :thread_cattr_accessor :thread_mattr_accessor

View File

@ -104,10 +104,16 @@ class Module
# * grok the behavior of our class in one glance,
# * clean up monolithic junk-drawer classes by separating their concerns, and
# * stop leaning on protected/private for crude "this is internal stuff" modularity.
#
# === Prepending concerning
#
# <tt>concerning</tt> supports a <tt>prepend: true</tt> argument which will <tt>prepend</tt> the
# concern instead of using <tt>include</tt> for it.
module Concerning
# Define a new concern and mix it in.
def concerning(topic, &block)
include concern(topic, &block)
def concerning(topic, prepend: false, &block)
method = prepend ? :prepend : :include
__send__(method, concern(topic, &block))
end
# A low-cruft shortcut to define a concern.

View File

@ -170,7 +170,7 @@ class Module
# The target method must be public, otherwise it will raise +NoMethodError+.
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
unless to
raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter)."
raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
end
if prefix == true && /^[^a-z_]/.match?(to)
@ -190,7 +190,13 @@ class Module
to = to.to_s
to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
method_names = methods.map do |method|
method_def = []
method_names = []
methods.map do |method|
method_name = prefix ? "#{method_prefix}#{method}" : method
method_names << method_name.to_sym
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
definition = if /[^\]]=$/.match?(method)
@ -209,34 +215,33 @@ class Module
# whereas conceptually, from the user point of view, the delegator should
# be doing one call.
if allow_nil
method_def = [
"def #{method_prefix}#{method}(#{definition})",
"_ = #{to}",
"if !_.nil? || nil.respond_to?(:#{method})",
" _.#{method}(#{definition})",
"end",
"end"
].join ";"
else
exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
method = method.to_s
method_def = [
"def #{method_prefix}#{method}(#{definition})",
" _ = #{to}",
" _.#{method}(#{definition})",
"rescue NoMethodError => e",
" if _.nil? && e.name == :#{method}",
" #{exception}",
" else",
" raise",
" end",
method_def <<
"def #{method_name}(#{definition})" <<
" _ = #{to}" <<
" if !_.nil? || nil.respond_to?(:#{method})" <<
" _.#{method}(#{definition})" <<
" end" <<
"end"
else
method = method.to_s
method_name = method_name.to_s
method_def <<
"def #{method_name}(#{definition})" <<
" _ = #{to}" <<
" _.#{method}(#{definition})" <<
"rescue NoMethodError => e" <<
" if _.nil? && e.name == :#{method}" <<
%( raise DelegationError, "#{self}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") <<
" else" <<
" raise" <<
" end" <<
"end"
].join ";"
end
module_eval(method_def, file, line)
end
module_eval(method_def.join(";"), file, line)
private(*method_names) if private
method_names
end
@ -280,13 +285,14 @@ class Module
# variables, methods, constants, etc.
#
# The delegated method must be public on the target, otherwise it will
# raise +NoMethodError+.
# raise +DelegationError+. If you wish to instead return +nil+,
# use the <tt>:allow_nil</tt> option.
#
# The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
# delegation due to possible interference when calling
# <tt>Marshal.dump(object)</tt>, should the delegation target method
# of <tt>object</tt> add or remove instance variables.
def delegate_missing_to(target)
def delegate_missing_to(target, allow_nil: nil)
target = target.to_s
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
@ -307,7 +313,11 @@ class Module
super
rescue NoMethodError
if #{target}.nil?
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
if #{allow_nil == true}
nil
else
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
end
else
raise
end

View File

@ -11,20 +11,12 @@ class Module
if defined?(@parent_name)
@parent_name
else
parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
parent_name = name =~ /::[^:]+\z/ ? -$` : nil
@parent_name = parent_name unless frozen?
parent_name
end
end
def parent_name
ActiveSupport::Deprecation.warn(<<-MSG.squish)
`Module#parent_name` has been renamed to `module_parent_name`.
`parent_name` is deprecated and will be removed in Rails 6.1.
MSG
module_parent_name
end
# Returns the module which contains this one according to its name.
#
# module M
@ -44,14 +36,6 @@ class Module
module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
end
def parent
ActiveSupport::Deprecation.warn(<<-MSG.squish)
`Module#parent` has been renamed to `module_parent`.
`parent` is deprecated and will be removed in Rails 6.1.
MSG
module_parent
end
# Returns all the parents of this module according to its name, ordered from
# nested outwards. The receiver is not contained within the result.
#
@ -76,12 +60,4 @@ class Module
parents << Object unless parents.include? Object
parents
end
def parents
ActiveSupport::Deprecation.warn(<<-MSG.squish)
`Module#parents` has been renamed to `module_parents`.
`parents` is deprecated and will be removed in Rails 6.1.
MSG
module_parents
end
end

View File

@ -14,9 +14,22 @@ class NameError
# 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 ")
if /undefined local variable or method/ !~ message
$1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
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
@ -35,4 +48,18 @@ class NameError
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

View File

@ -2,7 +2,6 @@
require "active_support/core_ext/big_decimal/conversions"
require "active_support/number_helper"
require "active_support/core_ext/module/deprecation"
module ActiveSupport
module NumericWithFormat
@ -27,10 +26,11 @@ module ActiveSupport
# # => "+1.123.555.1234 x 1343"
#
# Currency:
# 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
# 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
# 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
# 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
# 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
# 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
# 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
# 1234567890.506.to_s(:currency, round_mode: :down) # => "$1,234,567,890.50"
# 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
# -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
# # => "($1,234,567,890.50)"
# 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
@ -43,6 +43,7 @@ module ActiveSupport
# 100.to_s(:percentage, precision: 0) # => "100%"
# 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
# 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
# 302.24398923423.to_s(:percentage, round_mode: :down) # => "302.243%"
# 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
# 100.to_s(:percentage, format: '%n %') # => "100.000 %"
#
@ -59,6 +60,7 @@ module ActiveSupport
# Rounded:
# 111.2345.to_s(:rounded) # => "111.235"
# 111.2345.to_s(:rounded, precision: 2) # => "111.23"
# 111.2345.to_s(:rounded, precision: 2, round_mode: :up) # => "111.24"
# 13.to_s(:rounded, precision: 5) # => "13.00000"
# 389.32314.to_s(:rounded, precision: 0) # => "389"
# 111.2345.to_s(:rounded, significant: true) # => "111"
@ -72,19 +74,20 @@ module ActiveSupport
# # => "1.111,23"
#
# Human-friendly size in Bytes:
# 123.to_s(:human_size) # => "123 Bytes"
# 1234.to_s(:human_size) # => "1.21 KB"
# 12345.to_s(:human_size) # => "12.1 KB"
# 1234567.to_s(:human_size) # => "1.18 MB"
# 1234567890.to_s(:human_size) # => "1.15 GB"
# 1234567890123.to_s(:human_size) # => "1.12 TB"
# 1234567890123456.to_s(:human_size) # => "1.1 PB"
# 1234567890123456789.to_s(:human_size) # => "1.07 EB"
# 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
# 483989.to_s(:human_size, precision: 2) # => "470 KB"
# 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
# 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
# 524288000.to_s(:human_size, precision: 5) # => "500 MB"
# 123.to_s(:human_size) # => "123 Bytes"
# 1234.to_s(:human_size) # => "1.21 KB"
# 12345.to_s(:human_size) # => "12.1 KB"
# 1234567.to_s(:human_size) # => "1.18 MB"
# 1234567890.to_s(:human_size) # => "1.15 GB"
# 1234567890123.to_s(:human_size) # => "1.12 TB"
# 1234567890123456.to_s(:human_size) # => "1.1 PB"
# 1234567890123456789.to_s(:human_size) # => "1.07 EB"
# 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
# 1234567.to_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
# 483989.to_s(:human_size, precision: 2) # => "470 KB"
# 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
# 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
# 524288000.to_s(:human_size, precision: 5) # => "500 MB"
#
# Human-friendly format:
# 123.to_s(:human) # => "123"
@ -96,6 +99,7 @@ module ActiveSupport
# 1234567890123456.to_s(:human) # => "1.23 Quadrillion"
# 1234567890123456789.to_s(:human) # => "1230 Quadrillion"
# 489939.to_s(:human, precision: 2) # => "490 Thousand"
# 489939.to_s(:human, precision: 2, round_mode: :down) # => "480 Thousand"
# 489939.to_s(:human, precision: 4) # => "489.9 Thousand"
# 1234567.to_s(:human, precision: 4,
# significant: false) # => "1.2346 Million"

Some files were not shown because too many files have changed in this diff Show More