brew vendor-gems: commit updates.

This commit is contained in:
Mike McQuaid 2019-11-05 19:30:35 +00:00
parent 99a39913e6
commit 1241c40c8b
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
225 changed files with 3521 additions and 1556 deletions

View File

@ -5,14 +5,15 @@ ruby_version = RbConfig::CONFIG["ruby_version"]
path = File.expand_path('..', __FILE__)
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.7.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.12.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.13.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-5.2.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.2.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.0/lib"
$:.unshift "#{path}/"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-13/2.6.0-static/json-2.2.0"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/json-2.2.0"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/json-2.2.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-html-0.10.2/lib"
@ -22,22 +23,22 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/term-ansicolor-1.7.1/
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-0.20.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/coveralls-0.8.23/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-13/2.6.0-static/unf_ext-0.0.7.6"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/unf_ext-0.0.7.6"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf_ext-0.0.7.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf-0.1.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/domain_name-0.5.20190701/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-13/2.6.0-static/hpricot-0.8.6"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/hpricot-0.8.6"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/hpricot-0.8.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/http-cookie-1.0.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-13/2.6.0-static/jaro_winkler-1.5.3"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/jaro_winkler-1.5.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/jaro_winkler-1.5.4"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/jaro_winkler-1.5.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-data-3.2019.1009/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-3.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-digest_auth-1.4.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-persistent-3.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mini_portile2-2.4.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-13/2.6.0-static/nokogiri-1.10.4"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/nokogiri-1.10.5"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ntlm-http-0.1.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/webrobots-0.1.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/lib"
@ -47,7 +48,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-2.29.2
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.6.5.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-13/2.6.0-static/rdiscount-2.2.0.1"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/rdiscount-2.2.0.1"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rdiscount-2.2.0.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ronn-0.7.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-support-3.9.0/lib"
@ -60,7 +61,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.1/lib
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.6.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.75.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.76.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.5.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.36.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"

View File

@ -1,9 +0,0 @@
# frozen_string_literal: true
class Array
# The human way of thinking about adding stuff to the end of a list is with append.
alias_method :append, :push unless [].respond_to?(:append)
# The human way of thinking about adding stuff to the beginning of a list is with prepend.
alias_method :prepend, :unshift unless [].respond_to?(:prepend)
end

View File

@ -1,164 +0,0 @@
# frozen_string_literal: true
module Enumerable
# Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
# when we omit an identity.
#
# We tried shimming it to attempt the fast native method, rescue TypeError,
# and fall back to the compatible implementation, but that's much slower than
# just calling the compat method in the first place.
if Enumerable.instance_methods(false).include?(:sum) && !((?a..?b).sum rescue false)
# :stopdoc:
# We can't use Refinements here because Refinements with Module which will be prepended
# doesn't work well https://bugs.ruby-lang.org/issues/13446
alias :_original_sum_with_required_identity :sum
private :_original_sum_with_required_identity
# :startdoc:
# Calculates a sum from the elements.
#
# payments.sum { |p| p.price * p.tax_rate }
# payments.sum(&:price)
#
# The latter is a shortcut for:
#
# payments.inject(0) { |sum, p| sum + p.price }
#
# It can also calculate the sum without the use of a block.
#
# [5, 15, 10].sum # => 30
# ['foo', 'bar'].sum # => "foobar"
# [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
#
# The default sum of an empty list is zero. You can override this default:
#
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
def sum(identity = nil, &block)
if identity
_original_sum_with_required_identity(identity, &block)
elsif block_given?
map(&block).sum(identity)
else
inject(:+) || 0
end
end
else
def sum(identity = nil, &block)
if block_given?
map(&block).sum(identity)
else
sum = identity ? inject(identity, :+) : inject(:+)
sum || identity || 0
end
end
end
# Convert an enumerable to a hash.
#
# people.index_by(&:login)
# # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
# people.index_by { |person| "#{person.first_name} #{person.last_name}" }
# # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
def index_by
if block_given?
result = {}
each { |elem| result[yield(elem)] = elem }
result
else
to_enum(:index_by) { size if respond_to?(:size) }
end
end
# Returns +true+ if the enumerable has more than 1 element. Functionally
# equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
# much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
# if more than one person is over 26.
def many?
cnt = 0
if block_given?
any? do |element|
cnt += 1 if yield element
cnt > 1
end
else
any? { (cnt += 1) > 1 }
end
end
# The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
# collection does not include the object.
def exclude?(object)
!include?(object)
end
# Returns a copy of the enumerable without the specified elements.
#
# ["David", "Rafael", "Aaron", "Todd"].without "Aaron", "Todd"
# # => ["David", "Rafael"]
#
# {foo: 1, bar: 2, baz: 3}.without :bar
# # => {foo: 1, baz: 3}
def without(*elements)
reject { |element| elements.include?(element) }
end
# Convert an enumerable to an array based on the given key.
#
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
# # => ["David", "Rafael", "Aaron"]
#
# [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
# # => [[1, "David"], [2, "Rafael"]]
def pluck(*keys)
if keys.many?
map { |element| keys.map { |key| element[key] } }
else
map { |element| element[keys.first] }
end
end
end
class Range #:nodoc:
# Optimize range sum to use arithmetic progression if a block is not given and
# we have a range of numeric values.
def sum(identity = nil)
if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
super
else
actual_last = exclude_end? ? (last - 1) : last
if actual_last >= first
sum = identity || 0
sum + (actual_last - first + 1) * (actual_last + first) / 2
else
identity || 0
end
end
end
end
# Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
#
# We tried shimming it to attempt the fast native method, rescue TypeError,
# and fall back to the compatible implementation, but that's much slower than
# just calling the compat method in the first place.
if Array.instance_methods(false).include?(:sum) && !(%w[a].sum rescue false)
# Using Refinements here in order not to expose our internal method
using Module.new {
refine Array do
alias :orig_sum :sum
end
}
class Array
def sum(init = nil, &block) #:nodoc:
if init.is_a?(Numeric) || first.is_a?(Numeric)
init ||= 0
orig_sum(init, &block)
else
super
end
end
end
end

View File

@ -1,29 +0,0 @@
# frozen_string_literal: true
class Hash
unless Hash.instance_methods(false).include?(:compact)
# Returns a hash with non +nil+ values.
#
# hash = { a: true, b: false, c: nil }
# hash.compact # => { a: true, b: false }
# hash # => { a: true, b: false, c: nil }
# { c: nil }.compact # => {}
# { c: true }.compact # => { c: true }
def compact
select { |_, value| !value.nil? }
end
end
unless Hash.instance_methods(false).include?(:compact!)
# Replaces current hash with non +nil+ values.
# Returns +nil+ if no changes were made, otherwise returns the hash.
#
# hash = { a: true, b: false, c: nil }
# hash.compact! # => { a: true, b: false }
# hash # => { a: true, b: false }
# { c: true }.compact! # => nil
def compact!
reject! { |_, value| value.nil? }
end
end
end

View File

@ -1,48 +0,0 @@
# frozen_string_literal: true
class Hash
# Slices a hash to include only the given keys. Returns a hash containing
# the given keys.
#
# { a: 1, b: 2, c: 3, d: 4 }.slice(:a, :b)
# # => {:a=>1, :b=>2}
#
# This is useful for limiting an options hash to valid keys before
# passing to a method:
#
# def search(criteria = {})
# criteria.assert_valid_keys(:mass, :velocity, :time)
# end
#
# search(options.slice(:mass, :velocity, :time))
#
# If you have an array of keys you want to limit to, you should splat them:
#
# valid_keys = [:mass, :velocity, :time]
# search(options.slice(*valid_keys))
def slice(*keys)
keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
end unless method_defined?(:slice)
# Replaces the hash with only the given keys.
# Returns a hash containing the removed key/value pairs.
#
# { a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b)
# # => {:c=>3, :d=>4}
def slice!(*keys)
omit = slice(*self.keys - keys)
hash = slice(*keys)
hash.default = default
hash.default_proc = default_proc if default_proc
replace(hash)
omit
end
# 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}
def extract!(*keys)
keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
end
end

View File

@ -1,32 +0,0 @@
# frozen_string_literal: true
class Hash
# Returns a new hash with the results of running +block+ once for every value.
# The keys are unchanged.
#
# { a: 1, b: 2, c: 3 }.transform_values { |x| x * 2 } # => { a: 2, b: 4, c: 6 }
#
# If you do not provide a +block+, it will return an Enumerator
# for chaining with other methods:
#
# { a: 1, b: 2 }.transform_values.with_index { |v, i| [v, i].join.to_i } # => { a: 10, b: 21 }
def transform_values
return enum_for(:transform_values) { size } unless block_given?
return {} if empty?
result = self.class.new
each do |key, value|
result[key] = yield(value)
end
result
end unless method_defined? :transform_values
# Destructively converts all values using the +block+ operations.
# Same as +transform_values+ but modifies +self+.
def transform_values!
return enum_for(:transform_values!) { size } unless block_given?
each do |key, value|
self[key] = yield(value)
end
end unless method_defined? :transform_values!
# TODO: Remove this file when supporting only Ruby 2.4+.
end

View File

@ -1,13 +0,0 @@
# frozen_string_literal: true
class Object
# Makes backticks behave (somewhat more) similarly on all platforms.
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
# spawned shell prints a message to stderr and sets $?. We emulate
# Unix on the former but not the latter.
def `(command) #:nodoc:
super
rescue Errno::ENOENT => e
STDERR.puts "#$0: #{e}"
end
end

View File

@ -1,62 +0,0 @@
# frozen_string_literal: true
require "active_support/inflector"
class Module
# Returns the name of the module containing this one.
#
# M::N.parent_name # => "M"
def parent_name
if defined?(@parent_name)
@parent_name
else
parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
@parent_name = parent_name unless frozen?
parent_name
end
end
# Returns the module which contains this one according to its name.
#
# module M
# module N
# end
# end
# X = M::N
#
# M::N.parent # => M
# X.parent # => M
#
# The parent of top-level and anonymous modules is Object.
#
# M.parent # => Object
# Module.new.parent # => Object
def parent
parent_name ? ActiveSupport::Inflector.constantize(parent_name) : Object
end
# Returns all the parents of this module according to its name, ordered from
# nested outwards. The receiver is not contained within the result.
#
# module M
# module N
# end
# end
# X = M::N
#
# M.parents # => [Object]
# M::N.parents # => [M, Object]
# X.parents # => [M, Object]
def parents
parents = []
if parent_name
parts = parent_name.split("::")
until parts.empty?
parents << ActiveSupport::Inflector.constantize(parts * "::")
parts.pop
end
end
parents << Object unless parents.include? Object
parents
end
end

View File

@ -1,140 +0,0 @@
# frozen_string_literal: true
require "active_support/core_ext/big_decimal/conversions"
require "active_support/number_helper"
require "active_support/core_ext/module/deprecation"
module ActiveSupport::NumericWithFormat
# Provides options for converting numbers into formatted strings.
# Options are provided for phone numbers, currency, percentage,
# precision, positional notation, file size and pretty printing.
#
# ==== Options
#
# For details on which formats use which options, see ActiveSupport::NumberHelper
#
# ==== Examples
#
# Phone Numbers:
# 5551234.to_s(:phone) # => "555-1234"
# 1235551234.to_s(:phone) # => "123-555-1234"
# 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
# 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
# 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
# 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
# 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
# # => "+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, negative_format: '(%u%n)')
# # => "($1,234,567,890.50)"
# 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
# # => "&pound;1234567890,50"
# 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
# # => "1234567890,50 &pound;"
#
# Percentage:
# 100.to_s(:percentage) # => "100.000%"
# 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%"
# 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
# 100.to_s(:percentage, format: '%n %') # => "100.000 %"
#
# Delimited:
# 12345678.to_s(:delimited) # => "12,345,678"
# 12345678.05.to_s(:delimited) # => "12,345,678.05"
# 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
# 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
# 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
# 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
# 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
# # => "98 765 432,98"
#
# Rounded:
# 111.2345.to_s(:rounded) # => "111.235"
# 111.2345.to_s(:rounded, precision: 2) # => "111.23"
# 13.to_s(:rounded, precision: 5) # => "13.00000"
# 389.32314.to_s(:rounded, precision: 0) # => "389"
# 111.2345.to_s(:rounded, significant: true) # => "111"
# 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
# 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
# 111.234.to_s(:rounded, locale: :fr) # => "111,234"
# 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
# # => "13"
# 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
# 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
# # => "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"
#
# Human-friendly format:
# 123.to_s(:human) # => "123"
# 1234.to_s(:human) # => "1.23 Thousand"
# 12345.to_s(:human) # => "12.3 Thousand"
# 1234567.to_s(:human) # => "1.23 Million"
# 1234567890.to_s(:human) # => "1.23 Billion"
# 1234567890123.to_s(:human) # => "1.23 Trillion"
# 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: 4) # => "489.9 Thousand"
# 1234567.to_s(:human, precision: 4,
# significant: false) # => "1.2346 Million"
# 1234567.to_s(:human, precision: 1,
# separator: ',',
# significant: false) # => "1,2 Million"
def to_s(format = nil, options = nil)
case format
when nil
super()
when Integer, String
super(format)
when :phone
ActiveSupport::NumberHelper.number_to_phone(self, options || {})
when :currency
ActiveSupport::NumberHelper.number_to_currency(self, options || {})
when :percentage
ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
when :delimited
ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
when :rounded
ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
when :human
ActiveSupport::NumberHelper.number_to_human(self, options || {})
when :human_size
ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
when Symbol
super()
else
super(format)
end
end
end
# Ruby 2.4+ unifies Fixnum & Bignum into Integer.
if 0.class == Integer
Integer.prepend ActiveSupport::NumericWithFormat
else
Fixnum.prepend ActiveSupport::NumericWithFormat
Bignum.prepend ActiveSupport::NumericWithFormat
end
Float.prepend ActiveSupport::NumericWithFormat
BigDecimal.prepend ActiveSupport::NumericWithFormat

View File

@ -1,28 +0,0 @@
# frozen_string_literal: true
unless 1.respond_to?(:positive?) # TODO: Remove this file when we drop support to ruby < 2.3
class Numeric
# Returns true if the number is positive.
#
# 1.positive? # => true
# 0.positive? # => false
# -1.positive? # => false
def positive?
self > 0
end
# Returns true if the number is negative.
#
# -1.negative? # => true
# 0.negative? # => false
# 1.negative? # => false
def negative?
self < 0
end
end
class Complex
undef :positive?
undef :negative?
end
end

View File

@ -1,156 +0,0 @@
# frozen_string_literal: true
#--
# Most objects are cloneable, but not all. For example you can't dup methods:
#
# method(:puts).dup # => TypeError: allocator undefined for Method
#
# Classes may signal their instances are not duplicable removing +dup+/+clone+
# or raising exceptions from them. So, to dup an arbitrary object you normally
# use an optimistic approach and are ready to catch an exception, say:
#
# arbitrary_object.dup rescue object
#
# Rails dups objects in a few critical spots where they are not that arbitrary.
# That rescue is very expensive (like 40 times slower than a predicate), and it
# is often triggered.
#
# That's why we hardcode the following cases and check duplicable? instead of
# using that rescue idiom.
#++
class Object
# Can you safely dup this object?
#
# False for method objects;
# true otherwise.
def duplicable?
true
end
end
class NilClass
begin
nil.dup
rescue TypeError
# +nil+ is not duplicable:
#
# nil.duplicable? # => false
# nil.dup # => TypeError: can't dup NilClass
def duplicable?
false
end
end
end
class FalseClass
begin
false.dup
rescue TypeError
# +false+ is not duplicable:
#
# false.duplicable? # => false
# false.dup # => TypeError: can't dup FalseClass
def duplicable?
false
end
end
end
class TrueClass
begin
true.dup
rescue TypeError
# +true+ is not duplicable:
#
# true.duplicable? # => false
# true.dup # => TypeError: can't dup TrueClass
def duplicable?
false
end
end
end
class Symbol
begin
:symbol.dup # Ruby 2.4.x.
"symbol_from_string".to_sym.dup # Some symbols can't `dup` in Ruby 2.4.0.
rescue TypeError
# Symbols are not duplicable:
#
# :my_symbol.duplicable? # => false
# :my_symbol.dup # => TypeError: can't dup Symbol
def duplicable?
false
end
end
end
class Numeric
begin
1.dup
rescue TypeError
# Numbers are not duplicable:
#
# 3.duplicable? # => false
# 3.dup # => TypeError: can't dup Integer
def duplicable?
false
end
end
end
require "bigdecimal"
class BigDecimal
# BigDecimals are duplicable:
#
# BigDecimal("1.2").duplicable? # => true
# BigDecimal("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
def duplicable?
true
end
end
class Method
# Methods are not duplicable:
#
# method(:puts).duplicable? # => false
# method(:puts).dup # => TypeError: allocator undefined for Method
def duplicable?
false
end
end
class Complex
begin
Complex(1).dup
rescue TypeError
# Complexes are not duplicable:
#
# Complex(1).duplicable? # => false
# Complex(1).dup # => TypeError: can't copy Complex
def duplicable?
false
end
end
end
class Rational
begin
Rational(1).dup
rescue TypeError
# Rationals are not duplicable:
#
# Rational(1).duplicable? # => false
# Rational(1).dup # => TypeError: can't copy Rational
def duplicable?
false
end
end
end

View File

@ -1,39 +0,0 @@
# frozen_string_literal: true
module ActiveSupport::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
Range.prepend(ActiveSupport::RangeWithFormat)

View File

@ -1,3 +0,0 @@
# frozen_string_literal: true
require "active_support/core_ext/range/compare_range"

View File

@ -1,25 +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"]
# 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
end

View File

@ -1,62 +0,0 @@
# frozen_string_literal: true
module ActiveSupport
# This module provides an internal implementation to track descendants
# which is faster than iterating through ObjectSpace.
module DescendantsTracker
@@direct_descendants = {}
class << self
def direct_descendants(klass)
@@direct_descendants[klass] || []
end
def descendants(klass)
arr = []
accumulate_descendants(klass, arr)
arr
end
def clear
if defined? ActiveSupport::Dependencies
@@direct_descendants.each do |klass, descendants|
if ActiveSupport::Dependencies.autoloaded?(klass)
@@direct_descendants.delete(klass)
else
descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
end
end
else
@@direct_descendants.clear
end
end
# This is the only method that is not thread safe, but is only ever called
# during the eager loading phase.
def store_inherited(klass, descendant)
(@@direct_descendants[klass] ||= []) << descendant
end
private
def accumulate_descendants(klass, acc)
if direct_descendants = @@direct_descendants[klass]
acc.concat(direct_descendants)
direct_descendants.each { |direct_descendant| accumulate_descendants(direct_descendant, acc) }
end
end
end
def inherited(base)
DescendantsTracker.store_inherited(self, base)
super
end
def direct_descendants
DescendantsTracker.direct_descendants(self)
end
def descendants
DescendantsTracker.descendants(self)
end
end
end

View File

@ -1,29 +0,0 @@
# frozen_string_literal: true
require "active_support/concern"
require "active_support/core_ext/module/attribute_accessors"
require "concurrent"
module LoggerSilence
extend ActiveSupport::Concern
included do
cattr_accessor :silencer, default: true
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

View File

@ -1,33 +0,0 @@
# frozen_string_literal: true
require "active_support/concern"
module ActiveSupport
module LoggerThreadSafeLevel # :nodoc:
extend ActiveSupport::Concern
def after_initialize
@local_levels = Concurrent::Map.new(initial_capacity: 2)
end
def local_log_id
Thread.current.__id__
end
def local_level
@local_levels[local_log_id]
end
def local_level=(level)
if level
@local_levels[local_log_id] = level
else
@local_levels.delete(local_log_id)
end
end
def level
local_level || super
end
end
end

View File

@ -1,93 +0,0 @@
# frozen_string_literal: true
require "securerandom"
module ActiveSupport
module Notifications
# Instrumenters are stored in a thread local.
class Instrumenter
attr_reader :id
def initialize(notifier)
@id = unique_id
@notifier = notifier
end
# Instrument the given block by measuring the time taken to execute it
# and publish it. Notice that events get sent even if an error occurs
# in the passed-in block.
def instrument(name, payload = {})
# some of the listeners might have state
listeners_state = start name, payload
begin
yield payload
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
raise e
ensure
finish_with_state listeners_state, name, payload
end
end
# Send a start notification with +name+ and +payload+.
def start(name, payload)
@notifier.start name, @id, payload
end
# Send a finish notification with +name+ and +payload+.
def finish(name, payload)
@notifier.finish name, @id, payload
end
def finish_with_state(listeners_state, name, payload)
@notifier.finish name, @id, payload, listeners_state
end
private
def unique_id
SecureRandom.hex(10)
end
end
class Event
attr_reader :name, :time, :transaction_id, :payload, :children
attr_accessor :end
def initialize(name, start, ending, transaction_id, payload)
@name = name
@payload = payload.dup
@time = start
@transaction_id = transaction_id
@end = ending
@children = []
@duration = nil
end
# Returns the difference in milliseconds between when the execution of the
# event started and when it ended.
#
# ActiveSupport::Notifications.subscribe('wait') do |*args|
# @event = ActiveSupport::Notifications::Event.new(*args)
# end
#
# ActiveSupport::Notifications.instrument('wait') do
# sleep 1
# end
#
# @event.duration # => 1000.138
def duration
@duration ||= 1000.0 * (self.end - time)
end
def <<(event)
@children << event
end
def parent_of?(event)
@children.include? event
end
end
end
end

View File

@ -1,72 +0,0 @@
# frozen_string_literal: true
gem "minitest" # make sure we get the gem, not stdlib
require "minitest"
require "active_support/testing/tagged_logging"
require "active_support/testing/setup_and_teardown"
require "active_support/testing/assertions"
require "active_support/testing/deprecation"
require "active_support/testing/declarative"
require "active_support/testing/isolation"
require "active_support/testing/constant_lookup"
require "active_support/testing/time_helpers"
require "active_support/testing/file_fixtures"
module ActiveSupport
class TestCase < ::Minitest::Test
Assertion = Minitest::Assertion
class << self
# Sets the order in which test cases are run.
#
# ActiveSupport::TestCase.test_order = :random # => :random
#
# Valid values are:
# * +:random+ (to run tests in random order)
# * +:parallel+ (to run tests in parallel)
# * +:sorted+ (to run tests alphabetically by method name)
# * +:alpha+ (equivalent to +:sorted+)
def test_order=(new_order)
ActiveSupport.test_order = new_order
end
# Returns the order in which test cases are run.
#
# ActiveSupport::TestCase.test_order # => :random
#
# Possible values are +:random+, +:parallel+, +:alpha+, +:sorted+.
# Defaults to +:random+.
def test_order
ActiveSupport.test_order ||= :random
end
end
alias_method :method_name, :name
include ActiveSupport::Testing::TaggedLogging
prepend ActiveSupport::Testing::SetupAndTeardown
include ActiveSupport::Testing::Assertions
include ActiveSupport::Testing::Deprecation
include ActiveSupport::Testing::TimeHelpers
include ActiveSupport::Testing::FileFixtures
extend ActiveSupport::Testing::Declarative
# test/unit backwards compatibility methods
alias :assert_raise :assert_raises
alias :assert_not_empty :refute_empty
alias :assert_not_equal :refute_equal
alias :assert_not_in_delta :refute_in_delta
alias :assert_not_in_epsilon :refute_in_epsilon
alias :assert_not_includes :refute_includes
alias :assert_not_instance_of :refute_instance_of
alias :assert_not_kind_of :refute_kind_of
alias :assert_no_match :refute_match
alias :assert_not_nil :refute_nil
alias :assert_not_operator :refute_operator
alias :assert_not_predicate :refute_predicate
alias :assert_not_respond_to :refute_respond_to
alias :assert_not_same :refute_same
ActiveSupport.run_load_hooks(:active_support_test_case, self)
end
end

View File

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

View File

@ -31,6 +31,9 @@ module ActiveSupport
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
@ -82,6 +85,26 @@ module ActiveSupport
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{(#{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) }
@ -99,7 +122,11 @@ module ActiveSupport
end
def noise(backtrace)
backtrace - silence(backtrace)
backtrace.select do |line|
@silencers.any? do |s|
s.call(line)
end
end
end
end
end

View File

@ -23,6 +23,9 @@ module ActiveSupport
# +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
@ -497,9 +500,7 @@ module ActiveSupport
arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
end
def nested
@nested
end
attr_reader :nested
def final?
!@call_template
@ -578,7 +579,7 @@ module ActiveSupport
end
protected
def chain; @chain; end
attr_reader :chain
private
@ -659,9 +660,17 @@ module ActiveSupport
# * <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)
@ -809,7 +818,9 @@ module ActiveSupport
names.each do |name|
name = name.to_sym
set_callbacks name, CallbackChain.new(name, options)
([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)

View File

@ -110,7 +110,7 @@ module ActiveSupport
base.instance_variable_set(:@_dependencies, [])
end
def append_features(base)
def append_features(base) #:nodoc:
if base.instance_variable_defined?(:@_dependencies)
base.instance_variable_get(:@_dependencies) << self
false
@ -123,6 +123,9 @@ 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 +included+ block, it raises an exception.
def included(base = nil, &block)
if base.nil?
if instance_variable_defined?(:@_included_block)
@ -137,6 +140,26 @@ module ActiveSupport
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) :

View File

@ -2,8 +2,6 @@
require "active_support/concern"
require "active_support/ordered_options"
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/regexp"
module ActiveSupport
# Configurable provides a <tt>config</tt> method to store and retrieve
@ -69,8 +67,8 @@ module ActiveSupport
# end
# # => NameError: invalid config attribute name
#
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
# 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
@ -83,7 +81,7 @@ module ActiveSupport
# User.new.allowed_access = true # => NoMethodError
# User.new.allowed_access # => NoMethodError
#
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
#
# class User
# include ActiveSupport::Configurable
@ -106,9 +104,7 @@ module ActiveSupport
# end
#
# User.hair_colors # => [:brown, :black, :blonde, :red]
def config_accessor(*names)
options = names.extract_options!
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)
@ -118,9 +114,9 @@ module ActiveSupport
singleton_class.class_eval reader, __FILE__, reader_line
singleton_class.class_eval writer, __FILE__, writer_line
unless options[:instance_accessor] == false
class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
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

View File

@ -3,7 +3,7 @@
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/prepend_and_append"
require "active_support/core_ext/array/inquiry"

View File

@ -29,16 +29,28 @@ class Array
end
end
# Returns a copy of the Array without the specified elements.
# Returns a new array that includes the passed elements.
#
# people = ["David", "Rafael", "Aaron", "Todd"]
# people.without "Aaron", "Todd"
# # => ["David", "Rafael"]
# [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
# [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
def including(*elements)
self + elements.flatten(1)
end
# Returns a copy of the Array excluding the specified elements.
#
# Note: This is an optimization of <tt>Enumerable#without</tt> that uses <tt>Array#-</tt>
# ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
# [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
#
# Note: This is an optimization of <tt>Enumerable#excluding</tt> that uses <tt>Array#-</tt>
# instead of <tt>Array#reject</tt> for performance reasons.
def excluding(*elements)
self - elements.flatten(1)
end
# Alias for #excluding.
def without(*elements)
self - elements
excluding(*elements)
end
# Equal to <tt>self[1]</tt>.

View File

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

View File

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

@ -84,27 +84,26 @@ class Class
# To set a default value for the attribute, pass <tt>default:</tt>, like so:
#
# class_attribute :settings, default: {}
def class_attribute(*attrs)
options = attrs.extract_options!
instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
instance_predicate = options.fetch(:instance_predicate, true)
default_value = options.fetch(:default, nil)
def class_attribute(
*attrs,
instance_accessor: true,
instance_reader: instance_accessor,
instance_writer: instance_accessor,
instance_predicate: true,
default: nil
)
attrs.each do |name|
singleton_class.silence_redefinition_of_method(name)
define_singleton_method(name) { nil }
define_singleton_method(name) { default }
singleton_class.silence_redefinition_of_method("#{name}?")
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
ivar = "@#{name}"
ivar = "@#{name}".to_sym
singleton_class.silence_redefinition_of_method("#{name}=")
define_singleton_method("#{name}=") do |val|
singleton_class.class_eval do
redefine_method(name) { val }
end
redefine_singleton_method(name) { val }
if singleton_class?
class_eval do
@ -137,10 +136,6 @@ class Class
instance_variable_set ivar, val
end
end
unless default_value.nil?
self.send("#{name}=", default_value)
end
end
end
end

View File

@ -3,7 +3,7 @@
class Class
begin
# Test if this Ruby supports each_object against singleton_class
ObjectSpace.each_object(Numeric.singleton_class) {}
ObjectSpace.each_object(Numeric.singleton_class) { }
# Returns an array with all classes that are < than its receiver.
#

View File

@ -110,12 +110,13 @@ class Date
# 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)
options = options.dup
d = self
d = d >> options.delete(:years) * 12 if options[:years]
d = d >> options.delete(:months) if options[:months]
d = d + options.delete(:weeks) * 7 if options[:weeks]
d = d + options.delete(:days) if options[:days]
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

View File

@ -5,13 +5,13 @@ require "active_support/core_ext/object/try"
module DateAndTime
module Calculations
DAYS_INTO_WEEK = {
monday: 0,
tuesday: 1,
wednesday: 2,
thursday: 3,
friday: 4,
saturday: 5,
sunday: 6
sunday: 0,
monday: 1,
tuesday: 2,
wednesday: 3,
thursday: 4,
friday: 5,
saturday: 6
}
WEEKEND_DAYS = [ 6, 0 ]
@ -20,21 +20,11 @@ module DateAndTime
advance(days: -1)
end
# Returns a new date/time the specified number of days ago.
def prev_day(days = 1)
advance(days: -days)
end
# Returns a new date/time representing tomorrow.
def tomorrow
advance(days: 1)
end
# Returns a new date/time the specified number of days in the future.
def next_day(days = 1)
advance(days: days)
end
# Returns true if the date/time is today.
def today?
to_date == ::Date.current
@ -60,6 +50,16 @@ module DateAndTime
!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)
@ -124,7 +124,7 @@ module DateAndTime
# 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 = [10, 7, 4, 1].detect { |m| m <= month }
first_quarter_month = month - (2 + month) % 3
beginning_of_month.change(month: first_quarter_month)
end
alias :at_beginning_of_quarter :beginning_of_quarter
@ -139,7 +139,7 @@ module DateAndTime
# 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 = [3, 6, 9, 12].detect { |m| m >= month }
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
@ -188,21 +188,11 @@ module DateAndTime
end
end
# Returns a new date/time the specified number of months in the future.
def next_month(months = 1)
advance(months: months)
end
# Short-hand for months_since(3)
def next_quarter
months_since(3)
end
# Returns a new date/time the specified number of years in the future.
def next_year(years = 1)
advance(years: years)
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.
@ -223,11 +213,6 @@ module DateAndTime
end
alias_method :last_weekday, :prev_weekday
# Returns a new date/time the specified number of months ago.
def prev_month(months = 1)
advance(months: -months)
end
# Short-hand for months_ago(1).
def last_month
months_ago(1)
@ -239,11 +224,6 @@ module DateAndTime
end
alias_method :last_quarter, :prev_quarter
# Returns a new date/time the specified number of years ago.
def prev_year(years = 1)
advance(years: -years)
end
# Short-hand for years_ago(1).
def last_year
years_ago(1)
@ -253,9 +233,8 @@ module DateAndTime
# 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[start_day]
current_day_number = wday != 0 ? wday - 1 : 6
(current_day_number - start_day_number) % 7
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.
@ -336,8 +315,7 @@ module DateAndTime
# today.next_occurring(:monday) # => Mon, 18 Dec 2017
# today.next_occurring(:thursday) # => Thu, 21 Dec 2017
def next_occurring(day_of_week)
current_day_number = wday != 0 ? wday - 1 : 6
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
from_now += 7 unless from_now > 0
advance(days: from_now)
end
@ -348,8 +326,7 @@ module DateAndTime
# today.prev_occurring(:monday) # => Mon, 11 Dec 2017
# today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
def prev_occurring(day_of_week)
current_day_number = wday != 0 ? wday - 1 : 6
ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week)
ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
ago += 7 unless ago > 0
advance(days: -ago)
end
@ -364,7 +341,7 @@ module DateAndTime
end
def days_span(day)
(DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
(DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
end
def copy_time_to(other)

View File

@ -110,7 +110,7 @@ class DateTime
# instance time. Do not use this method in combination with x.months, use
# months_since instead!
def since(seconds)
self + Rational(seconds.round, 86400)
self + Rational(seconds, 86400)
end
alias :in :since

View File

@ -0,0 +1,3 @@
# frozen_string_literal: true
require "active_support/core_ext/digest/uuid"

View File

@ -0,0 +1,188 @@
# frozen_string_literal: true
module Enumerable
INDEX_WITH_DEFAULT = Object.new
private_constant :INDEX_WITH_DEFAULT
# Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
# when we omit an identity.
# :stopdoc:
# We can't use Refinements here because Refinements with Module which will be prepended
# doesn't work well https://bugs.ruby-lang.org/issues/13446
alias :_original_sum_with_required_identity :sum
private :_original_sum_with_required_identity
# :startdoc:
# Calculates a sum from the elements.
#
# payments.sum { |p| p.price * p.tax_rate }
# payments.sum(&:price)
#
# The latter is a shortcut for:
#
# payments.inject(0) { |sum, p| sum + p.price }
#
# It can also calculate the sum without the use of a block.
#
# [5, 15, 10].sum # => 30
# ['foo', 'bar'].sum # => "foobar"
# [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
#
# The default sum of an empty list is zero. You can override this default:
#
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
def sum(identity = nil, &block)
if identity
_original_sum_with_required_identity(identity, &block)
elsif block_given?
map(&block).sum(identity)
else
inject(:+) || 0
end
end
# Convert an enumerable to a hash keying it by the block return value.
#
# people.index_by(&:login)
# # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
#
# people.index_by { |person| "#{person.first_name} #{person.last_name}" }
# # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
def index_by
if block_given?
result = {}
each { |elem| result[yield(elem)] = elem }
result
else
to_enum(:index_by) { size if respond_to?(:size) }
end
end
# Convert an enumerable to a hash keying it with the enumerable items and with the values returned in the block.
#
# 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?" }
def index_with(default = INDEX_WITH_DEFAULT)
if block_given?
result = {}
each { |elem| result[elem] = yield(elem) }
result
elsif default != INDEX_WITH_DEFAULT
result = {}
each { |elem| result[elem] = default }
result
else
to_enum(:index_with) { size if respond_to?(:size) }
end
end
# Returns +true+ if the enumerable has more than 1 element. Functionally
# equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
# much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
# if more than one person is over 26.
def many?
cnt = 0
if block_given?
any? do |element|
cnt += 1 if yield element
cnt > 1
end
else
any? { (cnt += 1) > 1 }
end
end
# Returns a new array that includes the passed elements.
#
# [ 1, 2, 3 ].including(4, 5)
# # => [ 1, 2, 3, 4, 5 ]
#
# ["David", "Rafael"].including %w[ Aaron Todd ]
# # => ["David", "Rafael", "Aaron", "Todd"]
def including(*elements)
to_a.including(*elements)
end
# The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
# collection does not include the object.
def exclude?(object)
!include?(object)
end
# Returns a copy of the enumerable excluding the specified elements.
#
# ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
# # => ["David", "Rafael"]
#
# ["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ]
# # => ["David", "Rafael"]
#
# {foo: 1, bar: 2, baz: 3}.excluding :bar
# # => {foo: 1, baz: 3}
def excluding(*elements)
elements.flatten!(1)
reject { |element| elements.include?(element) }
end
# Alias for #excluding.
def without(*elements)
excluding(*elements)
end
# Convert an enumerable to an array based on the given key.
#
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
# # => ["David", "Rafael", "Aaron"]
#
# [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
# # => [[1, "David"], [2, "Rafael"]]
def pluck(*keys)
if keys.many?
map { |element| keys.map { |key| element[key] } }
else
map { |element| element[keys.first] }
end
end
end
class Range #:nodoc:
# Optimize range sum to use arithmetic progression if a block is not given and
# we have a range of numeric values.
def sum(identity = nil)
if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer))
super
else
actual_last = exclude_end? ? (last - 1) : last
if actual_last >= first
sum = identity || 0
sum + (actual_last - first + 1) * (actual_last + first) / 2
else
identity || 0
end
end
end
end
# Using Refinements here in order not to expose our internal method
using Module.new {
refine Array do
alias :orig_sum :sum
end
}
class Array #:nodoc:
# Array#sum was added in Ruby 2.4 but it only works with Numeric elements.
def sum(init = nil, &block)
if init.is_a?(Numeric) || first.is_a?(Numeric)
init ||= 0
orig_sum(init, &block)
else
super
end
end
end

View File

@ -1,11 +1,10 @@
# frozen_string_literal: true
require "active_support/core_ext/hash/compact"
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"
require "active_support/core_ext/hash/transform_values"

View File

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

@ -0,0 +1,46 @@
# frozen_string_literal: true
class Hash
# Returns a new hash with all values converted by the block operation.
# This includes the values from the root hash and from all
# nested hashes and arrays.
#
# hash = { person: { name: 'Rob', age: '28' } }
#
# hash.deep_transform_values{ |value| value.to_s.upcase }
# # => {person: {name: "ROB", age: "28"}}
def deep_transform_values(&block)
_deep_transform_values_in_object(self, &block)
end
# Destructively converts all values by using the block operation.
# This includes the values from the root hash and from all
# nested hashes and arrays.
def deep_transform_values!(&block)
_deep_transform_values_in_object!(self, &block)
end
private
# support methods for deep transforming nested hashes and arrays
def _deep_transform_values_in_object(object, &block)
case object
when Hash
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
when Array
object.map { |e| _deep_transform_values_in_object(e, &block) }
else
yield(object)
end
end
def _deep_transform_values_in_object!(object, &block)
case object
when Hash
object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
when Array
object.map! { |e| _deep_transform_values_in_object!(e, &block) }
else
yield(object)
end
end
end

View File

@ -10,7 +10,7 @@ class Hash
# This is useful for limiting a set of parameters to everything but a few known toggles:
# @person.update(params[:person].except(:admin))
def except(*keys)
dup.except!(*keys)
slice(*self.keys - keys)
end
# Removes the given keys from hash and returns it.

View File

@ -1,35 +1,6 @@
# frozen_string_literal: true
class Hash
# Returns a new hash with all keys converted using the +block+ operation.
#
# hash = { name: 'Rob', age: '28' }
#
# hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
#
# If you do not provide a +block+, it will return an Enumerator
# for chaining with other methods:
#
# hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
def transform_keys
return enum_for(:transform_keys) { size } unless block_given?
result = {}
each_key do |key|
result[yield(key)] = self[key]
end
result
end unless method_defined? :transform_keys
# Destructively converts all keys using the +block+ operations.
# Same as +transform_keys+ but modifies +self+.
def transform_keys!
return enum_for(:transform_keys!) { size } unless block_given?
keys.each do |key|
self[yield(key)] = delete(key)
end
self
end unless method_defined? :transform_keys!
# Returns a new hash with all keys converted to strings.
#
# hash = { name: 'Rob', age: '28' }

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class Hash
# Replaces the hash with only the given keys.
# Returns a hash containing the removed key/value pairs.
#
# hash = { a: 1, b: 2, c: 3, d: 4 }
# hash.slice!(:a, :b) # => {:c=>3, :d=>4}
# hash # => {:a=>1, :b=>2}
def slice!(*keys)
omit = slice(*self.keys - keys)
hash = slice(*keys)
hash.default = default
hash.default_proc = default_proc if default_proc
replace(hash)
omit
end
# 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}
def extract!(*keys)
keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
end
end

View File

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

@ -7,6 +7,6 @@ class Integer
# 6.multiple_of?(5) # => false
# 10.multiple_of?(2) # => true
def multiple_of?(number)
number != 0 ? self % number == 0 : zero?
number == 0 ? self == 0 : self % number == 0
end
end

View File

@ -1,6 +1,5 @@
# frozen_string_literal: true
require "active_support/core_ext/kernel/agnostics"
require "active_support/core_ext/kernel/concern"
require "active_support/core_ext/kernel/reporting"
require "active_support/core_ext/kernel/singleton_class"

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$/, "".freeze) == path.sub(/\.rb$/, "".freeze)
location.sub(/\.rb$/, "") == path.to_s.sub(/\.rb$/, "")
end
end

View File

@ -3,7 +3,6 @@
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/reachable"
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"

View File

@ -1,8 +1,5 @@
# frozen_string_literal: true
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/regexp"
# Extends the module object with class/module and instance accessors for
# class/module attributes, just like the native attr* accessors for instance
# attributes.
@ -27,7 +24,7 @@ class Module
# end
# # => NameError: invalid attribute name: 1_Badname
#
# If you want to opt out the creation on the instance reader method, pass
# To omit the instance reader method, pass
# <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
#
# module HairColors
@ -94,7 +91,7 @@ class Module
# Person.new.hair_colors = [:blonde, :red]
# HairColors.class_variable_get("@@hair_colors") # => [:blonde, :red]
#
# If you want to opt out the instance writer method, pass
# To omit the instance writer method, pass
# <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
#
# module HairColors
@ -163,14 +160,14 @@ class Module
# parent class. Similarly if parent class changes the value then that would
# change the value of subclasses too.
#
# class Male < Person
# class Citizen < Person
# end
#
# Male.new.hair_colors << :blue
# Citizen.new.hair_colors << :blue
# Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue]
#
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
#
# module HairColors
# mattr_accessor :hair_colors, instance_writer: false, instance_reader: false
@ -183,7 +180,7 @@ class Module
# Person.new.hair_colors = [:brown] # => NoMethodError
# Person.new.hair_colors # => NoMethodError
#
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
#
# module HairColors
# mattr_accessor :hair_colors, instance_accessor: false

View File

@ -1,8 +1,5 @@
# frozen_string_literal: true
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/regexp"
# Extends the module object with class/module and instance accessors for
# class/module attributes, just like the native attr* accessors for instance
# attributes, but does so on a per-thread basis.
@ -28,7 +25,7 @@ class Module
# end
# # => NameError: invalid attribute name: 1_Badname
#
# If you want to opt out of the creation of the instance reader method, pass
# To omit the instance reader method, pass
# <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
#
# class Current
@ -36,9 +33,7 @@ class Module
# end
#
# Current.new.user # => NoMethodError
def thread_mattr_reader(*syms) # :nodoc:
options = syms.extract_options!
def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true) # :nodoc:
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
@ -50,7 +45,7 @@ class Module
end
EOS
unless options[:instance_reader] == false || options[:instance_accessor] == false
if instance_reader && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}
self.class.#{sym}
@ -71,7 +66,7 @@ class Module
# Current.user = "DHH"
# Thread.current[:attr_Current_user] # => "DHH"
#
# If you want to opt out of the creation of the instance writer method, pass
# To omit the instance writer method, pass
# <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
#
# class Current
@ -79,8 +74,7 @@ class Module
# end
#
# Current.new.user = "DHH" # => NoMethodError
def thread_mattr_writer(*syms) # :nodoc:
options = syms.extract_options!
def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true) # :nodoc:
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
@ -92,7 +86,7 @@ class Module
end
EOS
unless options[:instance_writer] == false || options[:instance_accessor] == false
if instance_writer && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
self.class.#{sym} = obj
@ -124,8 +118,8 @@ class Module
# Customer.user # => "Rafael"
# Account.user # => "DHH"
#
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
# 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 Current
# thread_mattr_accessor :user, instance_writer: false, instance_reader: false
@ -134,17 +128,17 @@ class Module
# Current.new.user = "DHH" # => NoMethodError
# Current.new.user # => NoMethodError
#
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
#
# class Current
# mattr_accessor :user, instance_accessor: false
# thread_mattr_accessor :user, instance_accessor: false
# end
#
# Current.new.user = "DHH" # => NoMethodError
# Current.new.user # => NoMethodError
def thread_mattr_accessor(*syms)
thread_mattr_reader(*syms)
thread_mattr_writer(*syms)
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)
thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
end
alias :thread_cattr_accessor :thread_mattr_accessor
end

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true
require "set"
require "active_support/core_ext/regexp"
class Module
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
@ -20,10 +19,11 @@ class Module
# public methods as your own.
#
# ==== Options
# * <tt>:to</tt> - Specifies the target object
# * <tt>:to</tt> - Specifies the target object name as a symbol or string
# * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
# * <tt>:allow_nil</tt> - if set to true, prevents a +Module::DelegationError+
# * <tt>:allow_nil</tt> - If set to true, prevents a +Module::DelegationError+
# from being raised
# * <tt>:private</tt> - If set to true, changes method visibility to private
#
# The macro receives one or more method names (specified as symbols or
# strings) and the name of the target object via the <tt>:to</tt> option
@ -114,6 +114,23 @@ class Module
# invoice.customer_name # => 'John Doe'
# invoice.customer_address # => 'Vimmersvej 13'
#
# The delegated methods are public by default.
# Pass <tt>private: true</tt> to change that.
#
# class User < ActiveRecord::Base
# has_one :profile
# delegate :first_name, to: :profile
# delegate :date_of_birth, to: :profile, private: true
#
# def age
# Date.today.year - date_of_birth.year
# end
# end
#
# User.new.first_name # => "Tomas"
# User.new.date_of_birth # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>
# User.new.age # => 2
#
# If the target is +nil+ and does not respond to the delegated method a
# +Module::DelegationError+ is raised. If you wish to instead return +nil+,
# use the <tt>:allow_nil</tt> option.
@ -151,7 +168,7 @@ class Module
# Foo.new("Bar").name # raises NoMethodError: undefined method `name'
#
# The target method must be public, otherwise it will raise +NoMethodError+.
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
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)."
end
@ -173,7 +190,7 @@ class Module
to = to.to_s
to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
methods.map do |method|
method_names = methods.map do |method|
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"
@ -213,6 +230,9 @@ class Module
module_eval(method_def, file, line)
end
private(*method_names) if private
method_names
end
# When building decorators, a common pattern may emerge:
@ -223,7 +243,7 @@ class Module
# end
#
# def person
# @event.detail.person || @event.creator
# detail.person || creator
# end
#
# private
@ -246,7 +266,7 @@ class Module
# end
#
# def person
# @event.detail.person || @event.creator
# detail.person || creator
# end
# end
#
@ -255,6 +275,11 @@ class Module
#
# The delegated method must be public on the target, otherwise it will
# raise +NoMethodError+.
#
# 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)
target = target.to_s
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
@ -264,6 +289,7 @@ class Module
# It may look like an oversight, but we deliberately do not pass
# +include_private+, because they do not get delegated.
return false if name == :marshal_dump || name == :_dump
#{target}.respond_to?(name) || super
end

View File

@ -0,0 +1,86 @@
# frozen_string_literal: true
require "active_support/inflector"
class Module
# Returns the name of the module containing this one.
#
# M::N.module_parent_name # => "M"
def module_parent_name
if defined?(@parent_name)
@parent_name
else
parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : 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
# module N
# end
# end
# X = M::N
#
# M::N.module_parent # => M
# X.module_parent # => M
#
# The parent of top-level and anonymous modules is Object.
#
# M.module_parent # => Object
# Module.new.module_parent # => Object
def module_parent
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.
#
# module M
# module N
# end
# end
# X = M::N
#
# M.module_parents # => [Object]
# M::N.module_parents # => [M, Object]
# X.module_parents # => [M, Object]
def module_parents
parents = []
if module_parent_name
parts = module_parent_name.split("::")
until parts.empty?
parents << ActiveSupport::Inflector.constantize(parts * "::")
parts.pop
end
end
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

@ -3,9 +3,4 @@
require "active_support/core_ext/module/anonymous"
require "active_support/core_ext/string/inflections"
class Module
def reachable? #:nodoc:
!anonymous? && name.safe_constantize.equal?(self)
end
deprecate :reachable?
end
ActiveSupport::Deprecation.warn("reachable is deprecated and will be removed from the framework.")

View File

@ -1,23 +1,14 @@
# frozen_string_literal: true
class Module
if RUBY_VERSION >= "2.3"
# Marks the named method as intended to be redefined, if it exists.
# Suppresses the Ruby method redefinition warning. Prefer
# #redefine_method where possible.
def silence_redefinition_of_method(method)
if method_defined?(method) || private_method_defined?(method)
# This suppresses the "method redefined" warning; the self-alias
# looks odd, but means we don't need to generate a unique name
alias_method method, method
end
end
else
def silence_redefinition_of_method(method)
if method_defined?(method) || private_method_defined?(method)
alias_method :__rails_redefine, method
remove_method :__rails_redefine
end
# Marks the named method as intended to be redefined, if it exists.
# Suppresses the Ruby method redefinition warning. Prefer
# #redefine_method where possible.
def silence_redefinition_of_method(method)
if method_defined?(method) || private_method_defined?(method)
# This suppresses the "method redefined" warning; the self-alias
# looks odd, but means we don't need to generate a unique name
alias_method method, method
end
end

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