Merge pull request #6696 from Homebrew/dependabot/bundler/Library/Homebrew/activesupport-6.0.1
build: bump activesupport from 5.2.3 to 6.0.1 in /Library/Homebrew
This commit is contained in:
commit
918224ce1a
@ -1,11 +1,12 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activesupport (5.2.3)
|
activesupport (6.0.1)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
|
zeitwerk (~> 2.2)
|
||||||
ast (2.4.0)
|
ast (2.4.0)
|
||||||
concurrent-ruby (1.1.5)
|
concurrent-ruby (1.1.5)
|
||||||
connection_pool (2.2.2)
|
connection_pool (2.2.2)
|
||||||
@ -109,6 +110,7 @@ GEM
|
|||||||
unf_ext (0.0.7.6)
|
unf_ext (0.0.7.6)
|
||||||
unicode-display_width (1.6.0)
|
unicode-display_width (1.6.0)
|
||||||
webrobots (0.1.2)
|
webrobots (0.1.2)
|
||||||
|
zeitwerk (2.2.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "rubygems"
|
|
||||||
|
|
||||||
module Cask
|
module Cask
|
||||||
class DSL
|
class DSL
|
||||||
class DependsOn < DelegateClass(Hash)
|
class DependsOn < DelegateClass(Hash)
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "rubygems"
|
|
||||||
|
|
||||||
require "formula_installer"
|
require "formula_installer"
|
||||||
require "unpack_strategy"
|
require "unpack_strategy"
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module Assertions
|
module Assertions
|
||||||
require "rubygems"
|
|
||||||
require "test/unit/assertions"
|
require "test/unit/assertions"
|
||||||
include ::Test::Unit::Assertions
|
include ::Test::Unit::Assertions
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ require "pp"
|
|||||||
|
|
||||||
require_relative "load_path"
|
require_relative "load_path"
|
||||||
|
|
||||||
|
require "rubygems"
|
||||||
require "active_support/core_ext/object/blank"
|
require "active_support/core_ext/object/blank"
|
||||||
require "active_support/core_ext/numeric/time"
|
require "active_support/core_ext/numeric/time"
|
||||||
require "active_support/core_ext/array/access"
|
require "active_support/core_ext/array/access"
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "open3"
|
require "open3"
|
||||||
require "rubygems"
|
|
||||||
|
|
||||||
require_relative "shared_examples/invalid_option"
|
require_relative "shared_examples/invalid_option"
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,6 @@ RSpec.shared_context "integration test" do
|
|||||||
"-I", $LOAD_PATH.join(File::PATH_SEPARATOR)
|
"-I", $LOAD_PATH.join(File::PATH_SEPARATOR)
|
||||||
]
|
]
|
||||||
if ENV["HOMEBREW_TESTS_COVERAGE"]
|
if ENV["HOMEBREW_TESTS_COVERAGE"]
|
||||||
require "rubygems"
|
|
||||||
simplecov_spec = Gem.loaded_specs["simplecov"]
|
simplecov_spec = Gem.loaded_specs["simplecov"]
|
||||||
specs = [simplecov_spec]
|
specs = [simplecov_spec]
|
||||||
simplecov_spec.runtime_dependencies.each do |dep|
|
simplecov_spec.runtime_dependencies.each do |dep|
|
||||||
|
|||||||
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__)
|
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/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/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/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/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}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.0/lib"
|
||||||
$:.unshift "#{path}/"
|
$:.unshift "#{path}/"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.2/lib"
|
$:.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/json-2.2.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/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"
|
$:.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/thor-0.20.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/coveralls-0.8.23/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}/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_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/unf-0.1.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/domain_name-0.5.20190701/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/hpricot-0.8.6/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/http-cookie-1.0.3/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}/extensions/universal-darwin-19/2.6.0/jaro_winkler-1.5.4"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/jaro_winkler-1.5.3/lib"
|
$:.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-data-3.2019.1009/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-3.3/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-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/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}/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}/extensions/universal-darwin-19/2.6.0/nokogiri-1.10.5"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.4/lib"
|
$:.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/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/webrobots-0.1.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mechanize-2.7.6/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/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/plist-3.5.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.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/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/ronn-0.7.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-support-3.9.0/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/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/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/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-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/rubocop-rspec-1.36.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.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
|
class BacktraceCleaner
|
||||||
def initialize
|
def initialize
|
||||||
@filters, @silencers = [], []
|
@filters, @silencers = [], []
|
||||||
|
add_gem_filter
|
||||||
|
add_gem_silencer
|
||||||
|
add_stdlib_silencer
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the backtrace after all filters and silencers have been run
|
# Returns the backtrace after all filters and silencers have been run
|
||||||
@ -82,6 +85,26 @@ module ActiveSupport
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
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)
|
def filter_backtrace(backtrace)
|
||||||
@filters.each do |f|
|
@filters.each do |f|
|
||||||
backtrace = backtrace.map { |line| f.call(line) }
|
backtrace = backtrace.map { |line| f.call(line) }
|
||||||
@ -99,7 +122,11 @@ module ActiveSupport
|
|||||||
end
|
end
|
||||||
|
|
||||||
def noise(backtrace)
|
def noise(backtrace)
|
||||||
backtrace - silence(backtrace)
|
backtrace.select do |line|
|
||||||
|
@silencers.any? do |s|
|
||||||
|
s.call(line)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -23,6 +23,9 @@ module ActiveSupport
|
|||||||
# +ClassMethods.set_callback+), and run the installed callbacks at the
|
# +ClassMethods.set_callback+), and run the installed callbacks at the
|
||||||
# appropriate times (via +run_callbacks+).
|
# 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
|
# Three kinds of callbacks are supported: before callbacks, run before a
|
||||||
# certain event; after callbacks, run after the event; and around callbacks,
|
# certain event; after callbacks, run after the event; and around callbacks,
|
||||||
# blocks that surround the event, triggering it when they yield. Callback code
|
# 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) }
|
arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def nested
|
attr_reader :nested
|
||||||
@nested
|
|
||||||
end
|
|
||||||
|
|
||||||
def final?
|
def final?
|
||||||
!@call_template
|
!@call_template
|
||||||
@ -578,7 +579,7 @@ module ActiveSupport
|
|||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def chain; @chain; end
|
attr_reader :chain
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
@ -659,9 +660,17 @@ module ActiveSupport
|
|||||||
# * <tt>:if</tt> - A symbol or an array of symbols, each naming an instance
|
# * <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
|
# method or a proc; the callback will be called only when they all return
|
||||||
# a true value.
|
# 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
|
# * <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
|
# instance method or a proc; the callback will be called only when they
|
||||||
# all return a false value.
|
# 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
|
# * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
|
||||||
# existing chain rather than appended.
|
# existing chain rather than appended.
|
||||||
def set_callback(name, *filter_list, &block)
|
def set_callback(name, *filter_list, &block)
|
||||||
@ -809,7 +818,9 @@ module ActiveSupport
|
|||||||
names.each do |name|
|
names.each do |name|
|
||||||
name = name.to_sym
|
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
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
||||||
def _run_#{name}_callbacks(&block)
|
def _run_#{name}_callbacks(&block)
|
||||||
@ -110,7 +110,7 @@ module ActiveSupport
|
|||||||
base.instance_variable_set(:@_dependencies, [])
|
base.instance_variable_set(:@_dependencies, [])
|
||||||
end
|
end
|
||||||
|
|
||||||
def append_features(base)
|
def append_features(base) #:nodoc:
|
||||||
if base.instance_variable_defined?(:@_dependencies)
|
if base.instance_variable_defined?(:@_dependencies)
|
||||||
base.instance_variable_get(:@_dependencies) << self
|
base.instance_variable_get(:@_dependencies) << self
|
||||||
false
|
false
|
||||||
@ -123,6 +123,9 @@ module ActiveSupport
|
|||||||
end
|
end
|
||||||
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)
|
def included(base = nil, &block)
|
||||||
if base.nil?
|
if base.nil?
|
||||||
if instance_variable_defined?(:@_included_block)
|
if instance_variable_defined?(:@_included_block)
|
||||||
@ -137,6 +140,26 @@ module ActiveSupport
|
|||||||
end
|
end
|
||||||
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)
|
def class_methods(&class_methods_module_definition)
|
||||||
mod = const_defined?(:ClassMethods, false) ?
|
mod = const_defined?(:ClassMethods, false) ?
|
||||||
const_get(:ClassMethods) :
|
const_get(:ClassMethods) :
|
||||||
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
require "active_support/concern"
|
require "active_support/concern"
|
||||||
require "active_support/ordered_options"
|
require "active_support/ordered_options"
|
||||||
require "active_support/core_ext/array/extract_options"
|
|
||||||
require "active_support/core_ext/regexp"
|
|
||||||
|
|
||||||
module ActiveSupport
|
module ActiveSupport
|
||||||
# Configurable provides a <tt>config</tt> method to store and retrieve
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
||||||
@ -69,8 +67,8 @@ module ActiveSupport
|
|||||||
# end
|
# end
|
||||||
# # => NameError: invalid config attribute name
|
# # => NameError: invalid config attribute name
|
||||||
#
|
#
|
||||||
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
# To omit 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 reader method, pass <tt>instance_reader: false</tt>.
|
||||||
#
|
#
|
||||||
# class User
|
# class User
|
||||||
# include ActiveSupport::Configurable
|
# include ActiveSupport::Configurable
|
||||||
@ -83,7 +81,7 @@ module ActiveSupport
|
|||||||
# User.new.allowed_access = true # => NoMethodError
|
# User.new.allowed_access = true # => NoMethodError
|
||||||
# User.new.allowed_access # => 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
|
# class User
|
||||||
# include ActiveSupport::Configurable
|
# include ActiveSupport::Configurable
|
||||||
@ -106,9 +104,7 @@ module ActiveSupport
|
|||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
||||||
def config_accessor(*names)
|
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
|
||||||
options = names.extract_options!
|
|
||||||
|
|
||||||
names.each do |name|
|
names.each do |name|
|
||||||
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(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 reader, __FILE__, reader_line
|
||||||
singleton_class.class_eval writer, __FILE__, writer_line
|
singleton_class.class_eval writer, __FILE__, writer_line
|
||||||
|
|
||||||
unless options[:instance_accessor] == false
|
if instance_accessor
|
||||||
class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
|
class_eval reader, __FILE__, reader_line if instance_reader
|
||||||
class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
|
class_eval writer, __FILE__, writer_line if instance_writer
|
||||||
end
|
end
|
||||||
send("#{name}=", yield) if block_given?
|
send("#{name}=", yield) if block_given?
|
||||||
end
|
end
|
||||||
@ -3,7 +3,7 @@
|
|||||||
require "active_support/core_ext/array/wrap"
|
require "active_support/core_ext/array/wrap"
|
||||||
require "active_support/core_ext/array/access"
|
require "active_support/core_ext/array/access"
|
||||||
require "active_support/core_ext/array/conversions"
|
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/extract_options"
|
||||||
require "active_support/core_ext/array/grouping"
|
require "active_support/core_ext/array/grouping"
|
||||||
require "active_support/core_ext/array/prepend_and_append"
|
|
||||||
require "active_support/core_ext/array/inquiry"
|
require "active_support/core_ext/array/inquiry"
|
||||||
@ -29,16 +29,28 @@ class Array
|
|||||||
end
|
end
|
||||||
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"]
|
# [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
|
||||||
# people.without "Aaron", "Todd"
|
# [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
|
||||||
# # => ["David", "Rafael"]
|
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.
|
# instead of <tt>Array#reject</tt> for performance reasons.
|
||||||
|
def excluding(*elements)
|
||||||
|
self - elements.flatten(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Alias for #excluding.
|
||||||
def without(*elements)
|
def without(*elements)
|
||||||
self - elements
|
excluding(*elements)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Equal to <tt>self[1]</tt>.
|
# 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:
|
# To set a default value for the attribute, pass <tt>default:</tt>, like so:
|
||||||
#
|
#
|
||||||
# class_attribute :settings, default: {}
|
# class_attribute :settings, default: {}
|
||||||
def class_attribute(*attrs)
|
def class_attribute(
|
||||||
options = attrs.extract_options!
|
*attrs,
|
||||||
instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
|
instance_accessor: true,
|
||||||
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
|
instance_reader: instance_accessor,
|
||||||
instance_predicate = options.fetch(:instance_predicate, true)
|
instance_writer: instance_accessor,
|
||||||
default_value = options.fetch(:default, nil)
|
instance_predicate: true,
|
||||||
|
default: nil
|
||||||
|
)
|
||||||
attrs.each do |name|
|
attrs.each do |name|
|
||||||
singleton_class.silence_redefinition_of_method(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}?")
|
singleton_class.silence_redefinition_of_method("#{name}?")
|
||||||
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
||||||
|
|
||||||
ivar = "@#{name}"
|
ivar = "@#{name}".to_sym
|
||||||
|
|
||||||
singleton_class.silence_redefinition_of_method("#{name}=")
|
singleton_class.silence_redefinition_of_method("#{name}=")
|
||||||
define_singleton_method("#{name}=") do |val|
|
define_singleton_method("#{name}=") do |val|
|
||||||
singleton_class.class_eval do
|
redefine_singleton_method(name) { val }
|
||||||
redefine_method(name) { val }
|
|
||||||
end
|
|
||||||
|
|
||||||
if singleton_class?
|
if singleton_class?
|
||||||
class_eval do
|
class_eval do
|
||||||
@ -137,10 +136,6 @@ class Class
|
|||||||
instance_variable_set ivar, val
|
instance_variable_set ivar, val
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless default_value.nil?
|
|
||||||
self.send("#{name}=", default_value)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3,7 +3,7 @@
|
|||||||
class Class
|
class Class
|
||||||
begin
|
begin
|
||||||
# Test if this Ruby supports each_object against singleton_class
|
# 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.
|
# 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
|
# 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>.
|
# any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
|
||||||
def advance(options)
|
def advance(options)
|
||||||
options = options.dup
|
|
||||||
d = self
|
d = self
|
||||||
d = d >> options.delete(:years) * 12 if options[:years]
|
|
||||||
d = d >> options.delete(:months) if options[:months]
|
d = d >> options[:years] * 12 if options[:years]
|
||||||
d = d + options.delete(:weeks) * 7 if options[:weeks]
|
d = d >> options[:months] if options[:months]
|
||||||
d = d + options.delete(:days) if options[:days]
|
d = d + options[:weeks] * 7 if options[:weeks]
|
||||||
|
d = d + options[:days] if options[:days]
|
||||||
|
|
||||||
d
|
d
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -5,13 +5,13 @@ require "active_support/core_ext/object/try"
|
|||||||
module DateAndTime
|
module DateAndTime
|
||||||
module Calculations
|
module Calculations
|
||||||
DAYS_INTO_WEEK = {
|
DAYS_INTO_WEEK = {
|
||||||
monday: 0,
|
sunday: 0,
|
||||||
tuesday: 1,
|
monday: 1,
|
||||||
wednesday: 2,
|
tuesday: 2,
|
||||||
thursday: 3,
|
wednesday: 3,
|
||||||
friday: 4,
|
thursday: 4,
|
||||||
saturday: 5,
|
friday: 5,
|
||||||
sunday: 6
|
saturday: 6
|
||||||
}
|
}
|
||||||
WEEKEND_DAYS = [ 6, 0 ]
|
WEEKEND_DAYS = [ 6, 0 ]
|
||||||
|
|
||||||
@ -20,21 +20,11 @@ module DateAndTime
|
|||||||
advance(days: -1)
|
advance(days: -1)
|
||||||
end
|
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.
|
# Returns a new date/time representing tomorrow.
|
||||||
def tomorrow
|
def tomorrow
|
||||||
advance(days: 1)
|
advance(days: 1)
|
||||||
end
|
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.
|
# Returns true if the date/time is today.
|
||||||
def today?
|
def today?
|
||||||
to_date == ::Date.current
|
to_date == ::Date.current
|
||||||
@ -60,6 +50,16 @@ module DateAndTime
|
|||||||
!WEEKEND_DAYS.include?(wday)
|
!WEEKEND_DAYS.include?(wday)
|
||||||
end
|
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.
|
# Returns a new date/time the specified number of days ago.
|
||||||
def days_ago(days)
|
def days_ago(days)
|
||||||
advance(days: -days)
|
advance(days: -days)
|
||||||
@ -124,7 +124,7 @@ module DateAndTime
|
|||||||
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
||||||
# now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
|
# now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
|
||||||
def beginning_of_quarter
|
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)
|
beginning_of_month.change(month: first_quarter_month)
|
||||||
end
|
end
|
||||||
alias :at_beginning_of_quarter :beginning_of_quarter
|
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 = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
||||||
# now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
|
# now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
|
||||||
def end_of_quarter
|
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
|
beginning_of_month.change(month: last_quarter_month).end_of_month
|
||||||
end
|
end
|
||||||
alias :at_end_of_quarter :end_of_quarter
|
alias :at_end_of_quarter :end_of_quarter
|
||||||
@ -188,21 +188,11 @@ module DateAndTime
|
|||||||
end
|
end
|
||||||
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)
|
# Short-hand for months_since(3)
|
||||||
def next_quarter
|
def next_quarter
|
||||||
months_since(3)
|
months_since(3)
|
||||||
end
|
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.
|
# Returns a new date/time representing the given day in the previous week.
|
||||||
# Week is assumed to start on +start_day+, default is
|
# Week is assumed to start on +start_day+, default is
|
||||||
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
||||||
@ -223,11 +213,6 @@ module DateAndTime
|
|||||||
end
|
end
|
||||||
alias_method :last_weekday, :prev_weekday
|
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).
|
# Short-hand for months_ago(1).
|
||||||
def last_month
|
def last_month
|
||||||
months_ago(1)
|
months_ago(1)
|
||||||
@ -239,11 +224,6 @@ module DateAndTime
|
|||||||
end
|
end
|
||||||
alias_method :last_quarter, :prev_quarter
|
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).
|
# Short-hand for years_ago(1).
|
||||||
def last_year
|
def last_year
|
||||||
years_ago(1)
|
years_ago(1)
|
||||||
@ -253,9 +233,8 @@ module DateAndTime
|
|||||||
# Week is assumed to start on +start_day+, default is
|
# Week is assumed to start on +start_day+, default is
|
||||||
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
||||||
def days_to_week_start(start_day = Date.beginning_of_week)
|
def days_to_week_start(start_day = Date.beginning_of_week)
|
||||||
start_day_number = DAYS_INTO_WEEK[start_day]
|
start_day_number = DAYS_INTO_WEEK.fetch(start_day)
|
||||||
current_day_number = wday != 0 ? wday - 1 : 6
|
(wday - start_day_number) % 7
|
||||||
(current_day_number - start_day_number) % 7
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a new date/time representing the start of this week on the given day.
|
# 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(:monday) # => Mon, 18 Dec 2017
|
||||||
# today.next_occurring(:thursday) # => Thu, 21 Dec 2017
|
# today.next_occurring(:thursday) # => Thu, 21 Dec 2017
|
||||||
def next_occurring(day_of_week)
|
def next_occurring(day_of_week)
|
||||||
current_day_number = wday != 0 ? wday - 1 : 6
|
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
|
||||||
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number
|
|
||||||
from_now += 7 unless from_now > 0
|
from_now += 7 unless from_now > 0
|
||||||
advance(days: from_now)
|
advance(days: from_now)
|
||||||
end
|
end
|
||||||
@ -348,8 +326,7 @@ module DateAndTime
|
|||||||
# today.prev_occurring(:monday) # => Mon, 11 Dec 2017
|
# today.prev_occurring(:monday) # => Mon, 11 Dec 2017
|
||||||
# today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
|
# today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
|
||||||
def prev_occurring(day_of_week)
|
def prev_occurring(day_of_week)
|
||||||
current_day_number = wday != 0 ? wday - 1 : 6
|
ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
|
||||||
ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week)
|
|
||||||
ago += 7 unless ago > 0
|
ago += 7 unless ago > 0
|
||||||
advance(days: -ago)
|
advance(days: -ago)
|
||||||
end
|
end
|
||||||
@ -364,7 +341,7 @@ module DateAndTime
|
|||||||
end
|
end
|
||||||
|
|
||||||
def days_span(day)
|
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
|
end
|
||||||
|
|
||||||
def copy_time_to(other)
|
def copy_time_to(other)
|
||||||
@ -110,7 +110,7 @@ class DateTime
|
|||||||
# instance time. Do not use this method in combination with x.months, use
|
# instance time. Do not use this method in combination with x.months, use
|
||||||
# months_since instead!
|
# months_since instead!
|
||||||
def since(seconds)
|
def since(seconds)
|
||||||
self + Rational(seconds.round, 86400)
|
self + Rational(seconds, 86400)
|
||||||
end
|
end
|
||||||
alias :in :since
|
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
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "active_support/core_ext/hash/compact"
|
|
||||||
require "active_support/core_ext/hash/conversions"
|
require "active_support/core_ext/hash/conversions"
|
||||||
require "active_support/core_ext/hash/deep_merge"
|
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/except"
|
||||||
require "active_support/core_ext/hash/indifferent_access"
|
require "active_support/core_ext/hash/indifferent_access"
|
||||||
require "active_support/core_ext/hash/keys"
|
require "active_support/core_ext/hash/keys"
|
||||||
require "active_support/core_ext/hash/reverse_merge"
|
require "active_support/core_ext/hash/reverse_merge"
|
||||||
require "active_support/core_ext/hash/slice"
|
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:
|
# This is useful for limiting a set of parameters to everything but a few known toggles:
|
||||||
# @person.update(params[:person].except(:admin))
|
# @person.update(params[:person].except(:admin))
|
||||||
def except(*keys)
|
def except(*keys)
|
||||||
dup.except!(*keys)
|
slice(*self.keys - keys)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes the given keys from hash and returns it.
|
# Removes the given keys from hash and returns it.
|
||||||
@ -1,35 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Hash
|
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.
|
# Returns a new hash with all keys converted to strings.
|
||||||
#
|
#
|
||||||
# hash = { name: 'Rob', age: '28' }
|
# 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
|
# 6.multiple_of?(5) # => false
|
||||||
# 10.multiple_of?(2) # => true
|
# 10.multiple_of?(2) # => true
|
||||||
def multiple_of?(number)
|
def multiple_of?(number)
|
||||||
number != 0 ? self % number == 0 : zero?
|
number == 0 ? self == 0 : self % number == 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1,6 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "active_support/core_ext/kernel/agnostics"
|
|
||||||
require "active_support/core_ext/kernel/concern"
|
require "active_support/core_ext/kernel/concern"
|
||||||
require "active_support/core_ext/kernel/reporting"
|
require "active_support/core_ext/kernel/reporting"
|
||||||
require "active_support/core_ext/kernel/singleton_class"
|
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"
|
# Returns true if the given path name (except perhaps for the ".rb"
|
||||||
# extension) is the missing file which caused the exception to be raised.
|
# extension) is the missing file which caused the exception to be raised.
|
||||||
def is_missing?(location)
|
def is_missing?(location)
|
||||||
location.sub(/\.rb$/, "".freeze) == path.sub(/\.rb$/, "".freeze)
|
location.sub(/\.rb$/, "") == path.to_s.sub(/\.rb$/, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3,7 +3,6 @@
|
|||||||
require "active_support/core_ext/module/aliasing"
|
require "active_support/core_ext/module/aliasing"
|
||||||
require "active_support/core_ext/module/introspection"
|
require "active_support/core_ext/module/introspection"
|
||||||
require "active_support/core_ext/module/anonymous"
|
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"
|
||||||
require "active_support/core_ext/module/attribute_accessors_per_thread"
|
require "active_support/core_ext/module/attribute_accessors_per_thread"
|
||||||
require "active_support/core_ext/module/attr_internal"
|
require "active_support/core_ext/module/attr_internal"
|
||||||
@ -1,8 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# 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
|
# Extends the module object with class/module and instance accessors for
|
||||||
# class/module attributes, just like the native attr* accessors for instance
|
# class/module attributes, just like the native attr* accessors for instance
|
||||||
# attributes.
|
# attributes.
|
||||||
@ -27,7 +24,7 @@ class Module
|
|||||||
# end
|
# end
|
||||||
# # => NameError: invalid attribute name: 1_Badname
|
# # => 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>.
|
# <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
|
||||||
#
|
#
|
||||||
# module HairColors
|
# module HairColors
|
||||||
@ -94,7 +91,7 @@ class Module
|
|||||||
# Person.new.hair_colors = [:blonde, :red]
|
# Person.new.hair_colors = [:blonde, :red]
|
||||||
# HairColors.class_variable_get("@@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>.
|
# <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
|
||||||
#
|
#
|
||||||
# module HairColors
|
# module HairColors
|
||||||
@ -163,14 +160,14 @@ class Module
|
|||||||
# parent class. Similarly if parent class changes the value then that would
|
# parent class. Similarly if parent class changes the value then that would
|
||||||
# change the value of subclasses too.
|
# change the value of subclasses too.
|
||||||
#
|
#
|
||||||
# class Male < Person
|
# class Citizen < Person
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Male.new.hair_colors << :blue
|
# Citizen.new.hair_colors << :blue
|
||||||
# Person.new.hair_colors # => [:brown, :black, :blonde, :red, :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 omit 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 reader method, pass <tt>instance_reader: false</tt>.
|
||||||
#
|
#
|
||||||
# module HairColors
|
# module HairColors
|
||||||
# mattr_accessor :hair_colors, instance_writer: false, instance_reader: false
|
# 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 = [:brown] # => NoMethodError
|
||||||
# Person.new.hair_colors # => 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
|
# module HairColors
|
||||||
# mattr_accessor :hair_colors, instance_accessor: false
|
# mattr_accessor :hair_colors, instance_accessor: false
|
||||||
@ -1,8 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# 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
|
# Extends the module object with class/module and instance accessors for
|
||||||
# class/module attributes, just like the native attr* accessors for instance
|
# class/module attributes, just like the native attr* accessors for instance
|
||||||
# attributes, but does so on a per-thread basis.
|
# attributes, but does so on a per-thread basis.
|
||||||
@ -28,7 +25,7 @@ class Module
|
|||||||
# end
|
# end
|
||||||
# # => NameError: invalid attribute name: 1_Badname
|
# # => 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>.
|
# <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
|
||||||
#
|
#
|
||||||
# class Current
|
# class Current
|
||||||
@ -36,9 +33,7 @@ class Module
|
|||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Current.new.user # => NoMethodError
|
# Current.new.user # => NoMethodError
|
||||||
def thread_mattr_reader(*syms) # :nodoc:
|
def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true) # :nodoc:
|
||||||
options = syms.extract_options!
|
|
||||||
|
|
||||||
syms.each do |sym|
|
syms.each do |sym|
|
||||||
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
|
||||||
|
|
||||||
@ -50,7 +45,7 @@ class Module
|
|||||||
end
|
end
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
unless options[:instance_reader] == false || options[:instance_accessor] == false
|
if instance_reader && instance_accessor
|
||||||
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
||||||
def #{sym}
|
def #{sym}
|
||||||
self.class.#{sym}
|
self.class.#{sym}
|
||||||
@ -71,7 +66,7 @@ class Module
|
|||||||
# Current.user = "DHH"
|
# Current.user = "DHH"
|
||||||
# Thread.current[:attr_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>.
|
# <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
|
||||||
#
|
#
|
||||||
# class Current
|
# class Current
|
||||||
@ -79,8 +74,7 @@ class Module
|
|||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Current.new.user = "DHH" # => NoMethodError
|
# Current.new.user = "DHH" # => NoMethodError
|
||||||
def thread_mattr_writer(*syms) # :nodoc:
|
def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true) # :nodoc:
|
||||||
options = syms.extract_options!
|
|
||||||
syms.each do |sym|
|
syms.each do |sym|
|
||||||
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
|
||||||
|
|
||||||
@ -92,7 +86,7 @@ class Module
|
|||||||
end
|
end
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
unless options[:instance_writer] == false || options[:instance_accessor] == false
|
if instance_writer && instance_accessor
|
||||||
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
||||||
def #{sym}=(obj)
|
def #{sym}=(obj)
|
||||||
self.class.#{sym} = obj
|
self.class.#{sym} = obj
|
||||||
@ -124,8 +118,8 @@ class Module
|
|||||||
# Customer.user # => "Rafael"
|
# Customer.user # => "Rafael"
|
||||||
# Account.user # => "DHH"
|
# Account.user # => "DHH"
|
||||||
#
|
#
|
||||||
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
# To omit 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 reader method, pass <tt>instance_reader: false</tt>.
|
||||||
#
|
#
|
||||||
# class Current
|
# class Current
|
||||||
# thread_mattr_accessor :user, instance_writer: false, instance_reader: false
|
# thread_mattr_accessor :user, instance_writer: false, instance_reader: false
|
||||||
@ -134,17 +128,17 @@ class Module
|
|||||||
# Current.new.user = "DHH" # => NoMethodError
|
# Current.new.user = "DHH" # => NoMethodError
|
||||||
# Current.new.user # => 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
|
# class Current
|
||||||
# mattr_accessor :user, instance_accessor: false
|
# thread_mattr_accessor :user, instance_accessor: false
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Current.new.user = "DHH" # => NoMethodError
|
# Current.new.user = "DHH" # => NoMethodError
|
||||||
# Current.new.user # => NoMethodError
|
# Current.new.user # => NoMethodError
|
||||||
def thread_mattr_accessor(*syms)
|
def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true)
|
||||||
thread_mattr_reader(*syms)
|
thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor)
|
||||||
thread_mattr_writer(*syms)
|
thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
|
||||||
end
|
end
|
||||||
alias :thread_cattr_accessor :thread_mattr_accessor
|
alias :thread_cattr_accessor :thread_mattr_accessor
|
||||||
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