brew vendor-gems: commit updates.
This commit is contained in:
parent
99a39913e6
commit
1241c40c8b
23
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
23
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
@ -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"
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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: '£', separator: ',', delimiter: '')
|
||||
# # => "£1234567890,50"
|
||||
# 1234567890.50.to_s(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
||||
# # => "1234567890,50 £"
|
||||
#
|
||||
# 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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -1,3 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "active_support/core_ext/range/compare_range"
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
Binary file not shown.
@ -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
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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) :
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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>.
|
||||
@ -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
|
||||
@ -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."
|
||||
@ -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
|
||||
@ -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.
|
||||
#
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
@ -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
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "active_support/core_ext/digest/uuid"
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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."
|
||||
@ -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
|
||||
@ -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.
|
||||
@ -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' }
|
||||
@ -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
|
||||
@ -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."
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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.")
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user