activesupport 5.2.1.1 → 6.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +416 -351
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -2
- data/lib/active_support.rb +2 -1
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +28 -1
- data/lib/active_support/cache.rb +45 -23
- data/lib/active_support/cache/file_store.rb +22 -22
- data/lib/active_support/cache/mem_cache_store.rb +5 -0
- data/lib/active_support/cache/memory_store.rb +9 -2
- data/lib/active_support/cache/null_store.rb +5 -0
- data/lib/active_support/cache/redis_cache_store.rb +37 -10
- data/lib/active_support/callbacks.rb +16 -5
- data/lib/active_support/concern.rb +31 -4
- data/lib/active_support/configurable.rb +7 -11
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
- data/lib/active_support/core_ext/class/attribute.rb +11 -16
- data/lib/active_support/core_ext/class/subclasses.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +97 -73
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash.rb +1 -2
- data/lib/active_support/core_ext/hash/compact.rb +2 -26
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +0 -29
- data/lib/active_support/core_ext/hash/slice.rb +3 -25
- data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
- data/lib/active_support/core_ext/module/delegation.rb +33 -7
- data/lib/active_support/core_ext/module/introspection.rb +37 -13
- data/lib/active_support/core_ext/module/reachable.rb +1 -6
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
- data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/duplicable.rb +7 -114
- data/lib/active_support/core_ext/object/json.rb +1 -0
- data/lib/active_support/core_ext/object/try.rb +15 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +76 -0
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/include_range.rb +6 -22
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
- data/lib/active_support/core_ext/regexp.rb +0 -4
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +8 -0
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +7 -2
- data/lib/active_support/core_ext/string/multibyte.rb +4 -3
- data/lib/active_support/core_ext/string/output_safety.rb +63 -5
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +31 -2
- data/lib/active_support/core_ext/uri.rb +2 -1
- data/lib/active_support/current_attributes.rb +8 -0
- data/lib/active_support/dependencies.rb +74 -17
- data/lib/active_support/dependencies/zeitwerk_integration.rb +118 -0
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/deprecation/behaviors.rb +1 -1
- data/lib/active_support/deprecation/method_wrappers.rb +13 -12
- data/lib/active_support/deprecation/proxy_wrappers.rb +24 -5
- data/lib/active_support/descendants_tracker.rb +56 -9
- data/lib/active_support/duration.rb +6 -5
- data/lib/active_support/duration/iso8601_parser.rb +2 -3
- data/lib/active_support/duration/iso8601_serializer.rb +3 -4
- data/lib/active_support/encrypted_configuration.rb +1 -5
- data/lib/active_support/encrypted_file.rb +2 -1
- data/lib/active_support/evented_file_update_checker.rb +39 -9
- data/lib/active_support/execution_wrapper.rb +1 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +36 -18
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +14 -2
- data/lib/active_support/inflector/inflections.rb +1 -4
- data/lib/active_support/inflector/methods.rb +17 -27
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/json/decoding.rb +23 -23
- data/lib/active_support/json/encoding.rb +6 -2
- data/lib/active_support/key_generator.rb +0 -32
- data/lib/active_support/lazy_load_hooks.rb +5 -1
- data/lib/active_support/locale/en.rb +31 -0
- data/lib/active_support/log_subscriber.rb +31 -8
- data/lib/active_support/logger.rb +0 -15
- data/lib/active_support/logger_silence.rb +28 -12
- data/lib/active_support/logger_thread_safe_level.rb +28 -5
- data/lib/active_support/message_encryptor.rb +3 -5
- data/lib/active_support/message_verifier.rb +3 -3
- data/lib/active_support/multibyte/chars.rb +29 -48
- data/lib/active_support/multibyte/unicode.rb +44 -281
- data/lib/active_support/notifications.rb +41 -4
- data/lib/active_support/notifications/fanout.rb +100 -15
- data/lib/active_support/notifications/instrumenter.rb +80 -8
- data/lib/active_support/number_helper.rb +7 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +1 -1
- data/lib/active_support/parameter_filter.rb +129 -0
- data/lib/active_support/rails.rb +0 -6
- data/lib/active_support/reloader.rb +4 -5
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/subscriber.rb +65 -22
- data/lib/active_support/tagged_logging.rb +13 -4
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +15 -1
- data/lib/active_support/testing/deprecation.rb +0 -1
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +28 -1
- data/lib/active_support/testing/parallelization.rb +128 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +7 -7
- data/lib/active_support/time_with_zone.rb +15 -5
- data/lib/active_support/values/time_zone.rb +12 -7
- data/lib/active_support/xml_mini.rb +2 -9
- data/lib/active_support/xml_mini/jdom.rb +2 -2
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- metadata +33 -10
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -17,7 +17,6 @@ end
|
|
17
17
|
|
18
18
|
require "digest/sha2"
|
19
19
|
require "active_support/core_ext/marshal"
|
20
|
-
require "active_support/core_ext/hash/transform_values"
|
21
20
|
|
22
21
|
module ActiveSupport
|
23
22
|
module Cache
|
@@ -67,6 +66,11 @@ module ActiveSupport
|
|
67
66
|
SCAN_BATCH_SIZE = 1000
|
68
67
|
private_constant :SCAN_BATCH_SIZE
|
69
68
|
|
69
|
+
# Advertise cache versioning support.
|
70
|
+
def self.supports_cache_versioning?
|
71
|
+
true
|
72
|
+
end
|
73
|
+
|
70
74
|
# Support raw values in the local cache strategy.
|
71
75
|
module LocalCacheWithRaw # :nodoc:
|
72
76
|
private
|
@@ -148,15 +152,17 @@ module ActiveSupport
|
|
148
152
|
|
149
153
|
# Creates a new Redis cache store.
|
150
154
|
#
|
151
|
-
# Handles
|
152
|
-
#
|
155
|
+
# Handles four options: :redis block, :redis instance, single :url
|
156
|
+
# string, and multiple :url strings.
|
153
157
|
#
|
154
|
-
#
|
155
|
-
# :
|
156
|
-
# :
|
158
|
+
# Option Class Result
|
159
|
+
# :redis Proc -> options[:redis].call
|
160
|
+
# :redis Object -> options[:redis]
|
161
|
+
# :url String -> Redis.new(url: …)
|
162
|
+
# :url Array -> Redis::Distributed.new([{ url: … }, { url: … }, …])
|
157
163
|
#
|
158
164
|
# No namespace is set by default. Provide one if the Redis cache
|
159
|
-
# server is shared with other apps: <tt>namespace: 'myapp-cache'
|
165
|
+
# server is shared with other apps: <tt>namespace: 'myapp-cache'</tt>.
|
160
166
|
#
|
161
167
|
# Compression is enabled by default with a 1kB threshold, so cached
|
162
168
|
# values larger than 1kB are automatically compressed. Disable by
|
@@ -259,7 +265,14 @@ module ActiveSupport
|
|
259
265
|
def increment(name, amount = 1, options = nil)
|
260
266
|
instrument :increment, name, amount: amount do
|
261
267
|
failsafe :increment do
|
262
|
-
|
268
|
+
options = merged_options(options)
|
269
|
+
key = normalize_key(name, options)
|
270
|
+
|
271
|
+
redis.with do |c|
|
272
|
+
c.incrby(key, amount).tap do
|
273
|
+
write_key_expiry(c, key, options)
|
274
|
+
end
|
275
|
+
end
|
263
276
|
end
|
264
277
|
end
|
265
278
|
end
|
@@ -275,7 +288,14 @@ module ActiveSupport
|
|
275
288
|
def decrement(name, amount = 1, options = nil)
|
276
289
|
instrument :decrement, name, amount: amount do
|
277
290
|
failsafe :decrement do
|
278
|
-
|
291
|
+
options = merged_options(options)
|
292
|
+
key = normalize_key(name, options)
|
293
|
+
|
294
|
+
redis.with do |c|
|
295
|
+
c.decrby(key, amount).tap do
|
296
|
+
write_key_expiry(c, key, options)
|
297
|
+
end
|
298
|
+
end
|
279
299
|
end
|
280
300
|
end
|
281
301
|
end
|
@@ -343,6 +363,7 @@ module ActiveSupport
|
|
343
363
|
def read_multi_mget(*names)
|
344
364
|
options = names.extract_options!
|
345
365
|
options = merged_options(options)
|
366
|
+
return {} if names == []
|
346
367
|
|
347
368
|
keys = names.map { |name| normalize_key(name, options) }
|
348
369
|
|
@@ -386,6 +407,12 @@ module ActiveSupport
|
|
386
407
|
end
|
387
408
|
end
|
388
409
|
|
410
|
+
def write_key_expiry(client, key, options)
|
411
|
+
if options[:expires_in] && client.ttl(key).negative?
|
412
|
+
client.expire key, options[:expires_in].to_i
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
389
416
|
# Delete an entry from the cache.
|
390
417
|
def delete_entry(key, options)
|
391
418
|
failsafe :delete_entry, returning: false do
|
@@ -444,7 +471,7 @@ module ActiveSupport
|
|
444
471
|
|
445
472
|
def failsafe(method, returning: nil)
|
446
473
|
yield
|
447
|
-
rescue ::Redis::
|
474
|
+
rescue ::Redis::BaseError => e
|
448
475
|
handle_exception exception: e, method: method, returning: returning
|
449
476
|
returning
|
450
477
|
end
|
@@ -23,6 +23,9 @@ module ActiveSupport
|
|
23
23
|
# +ClassMethods.set_callback+), and run the installed callbacks at the
|
24
24
|
# appropriate times (via +run_callbacks+).
|
25
25
|
#
|
26
|
+
# By default callbacks are halted by throwing +:abort+.
|
27
|
+
# See +ClassMethods.define_callbacks+ for details.
|
28
|
+
#
|
26
29
|
# Three kinds of callbacks are supported: before callbacks, run before a
|
27
30
|
# certain event; after callbacks, run after the event; and around callbacks,
|
28
31
|
# blocks that surround the event, triggering it when they yield. Callback code
|
@@ -497,9 +500,7 @@ module ActiveSupport
|
|
497
500
|
arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
|
498
501
|
end
|
499
502
|
|
500
|
-
|
501
|
-
@nested
|
502
|
-
end
|
503
|
+
attr_reader :nested
|
503
504
|
|
504
505
|
def final?
|
505
506
|
!@call_template
|
@@ -578,7 +579,7 @@ module ActiveSupport
|
|
578
579
|
end
|
579
580
|
|
580
581
|
protected
|
581
|
-
|
582
|
+
attr_reader :chain
|
582
583
|
|
583
584
|
private
|
584
585
|
|
@@ -659,9 +660,17 @@ module ActiveSupport
|
|
659
660
|
# * <tt>:if</tt> - A symbol or an array of symbols, each naming an instance
|
660
661
|
# method or a proc; the callback will be called only when they all return
|
661
662
|
# a true value.
|
663
|
+
#
|
664
|
+
# If a proc is given, its body is evaluated in the context of the
|
665
|
+
# current object. It can also optionally accept the current object as
|
666
|
+
# an argument.
|
662
667
|
# * <tt>:unless</tt> - A symbol or an array of symbols, each naming an
|
663
668
|
# instance method or a proc; the callback will be called only when they
|
664
669
|
# all return a false value.
|
670
|
+
#
|
671
|
+
# If a proc is given, its body is evaluated in the context of the
|
672
|
+
# current object. It can also optionally accept the current object as
|
673
|
+
# an argument.
|
665
674
|
# * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
|
666
675
|
# existing chain rather than appended.
|
667
676
|
def set_callback(name, *filter_list, &block)
|
@@ -809,7 +818,9 @@ module ActiveSupport
|
|
809
818
|
names.each do |name|
|
810
819
|
name = name.to_sym
|
811
820
|
|
812
|
-
|
821
|
+
([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target|
|
822
|
+
target.set_callbacks name, CallbackChain.new(name, options)
|
823
|
+
end
|
813
824
|
|
814
825
|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
815
826
|
def _run_#{name}_callbacks(&block)
|
@@ -110,7 +110,7 @@ module ActiveSupport
|
|
110
110
|
base.instance_variable_set(:@_dependencies, [])
|
111
111
|
end
|
112
112
|
|
113
|
-
def append_features(base)
|
113
|
+
def append_features(base) #:nodoc:
|
114
114
|
if base.instance_variable_defined?(:@_dependencies)
|
115
115
|
base.instance_variable_get(:@_dependencies) << self
|
116
116
|
false
|
@@ -123,16 +123,43 @@ module ActiveSupport
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
# Evaluate given block in context of base class,
|
127
|
+
# so that you can write class macros here.
|
128
|
+
# When you define more than one +included+ block, it raises an exception.
|
126
129
|
def included(base = nil, &block)
|
127
130
|
if base.nil?
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
+
if instance_variable_defined?(:@_included_block)
|
132
|
+
if @_included_block.source_location != block.source_location
|
133
|
+
raise MultipleIncludedBlocks
|
134
|
+
end
|
135
|
+
else
|
136
|
+
@_included_block = block
|
137
|
+
end
|
131
138
|
else
|
132
139
|
super
|
133
140
|
end
|
134
141
|
end
|
135
142
|
|
143
|
+
# Define class methods from given block.
|
144
|
+
# You can define private class methods as well.
|
145
|
+
#
|
146
|
+
# module Example
|
147
|
+
# extend ActiveSupport::Concern
|
148
|
+
#
|
149
|
+
# class_methods do
|
150
|
+
# def foo; puts 'foo'; end
|
151
|
+
#
|
152
|
+
# private
|
153
|
+
# def bar; puts 'bar'; end
|
154
|
+
# end
|
155
|
+
# end
|
156
|
+
#
|
157
|
+
# class Buzz
|
158
|
+
# include Example
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# Buzz.foo # => "foo"
|
162
|
+
# Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
|
136
163
|
def class_methods(&class_methods_module_definition)
|
137
164
|
mod = const_defined?(:ClassMethods, false) ?
|
138
165
|
const_get(:ClassMethods) :
|
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
require "active_support/concern"
|
4
4
|
require "active_support/ordered_options"
|
5
|
-
require "active_support/core_ext/array/extract_options"
|
6
|
-
require "active_support/core_ext/regexp"
|
7
5
|
|
8
6
|
module ActiveSupport
|
9
7
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
@@ -69,8 +67,8 @@ module ActiveSupport
|
|
69
67
|
# end
|
70
68
|
# # => NameError: invalid config attribute name
|
71
69
|
#
|
72
|
-
# To
|
73
|
-
# To
|
70
|
+
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
|
71
|
+
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
|
74
72
|
#
|
75
73
|
# class User
|
76
74
|
# include ActiveSupport::Configurable
|
@@ -83,7 +81,7 @@ module ActiveSupport
|
|
83
81
|
# User.new.allowed_access = true # => NoMethodError
|
84
82
|
# User.new.allowed_access # => NoMethodError
|
85
83
|
#
|
86
|
-
# Or pass <tt>instance_accessor: false</tt>, to
|
84
|
+
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
|
87
85
|
#
|
88
86
|
# class User
|
89
87
|
# include ActiveSupport::Configurable
|
@@ -106,9 +104,7 @@ module ActiveSupport
|
|
106
104
|
# end
|
107
105
|
#
|
108
106
|
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
109
|
-
def config_accessor(*names)
|
110
|
-
options = names.extract_options!
|
111
|
-
|
107
|
+
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
|
112
108
|
names.each do |name|
|
113
109
|
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
114
110
|
|
@@ -118,9 +114,9 @@ module ActiveSupport
|
|
118
114
|
singleton_class.class_eval reader, __FILE__, reader_line
|
119
115
|
singleton_class.class_eval writer, __FILE__, writer_line
|
120
116
|
|
121
|
-
|
122
|
-
class_eval reader, __FILE__, reader_line
|
123
|
-
class_eval writer, __FILE__, writer_line
|
117
|
+
if instance_accessor
|
118
|
+
class_eval reader, __FILE__, reader_line if instance_reader
|
119
|
+
class_eval writer, __FILE__, writer_line if instance_writer
|
124
120
|
end
|
125
121
|
send("#{name}=", yield) if block_given?
|
126
122
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/array/wrap"
|
4
4
|
require "active_support/core_ext/array/access"
|
5
5
|
require "active_support/core_ext/array/conversions"
|
6
|
+
require "active_support/core_ext/array/extract"
|
6
7
|
require "active_support/core_ext/array/extract_options"
|
7
8
|
require "active_support/core_ext/array/grouping"
|
8
|
-
require "active_support/core_ext/array/prepend_and_append"
|
9
9
|
require "active_support/core_ext/array/inquiry"
|
@@ -29,16 +29,28 @@ class Array
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# Returns a
|
32
|
+
# Returns a new array that includes the passed elements.
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
|
34
|
+
# [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
|
35
|
+
# [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
|
36
|
+
def including(*elements)
|
37
|
+
self + elements.flatten(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a copy of the Array excluding the specified elements.
|
41
|
+
#
|
42
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
|
43
|
+
# [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
|
37
44
|
#
|
38
|
-
# Note: This is an optimization of <tt>Enumerable#
|
45
|
+
# Note: This is an optimization of <tt>Enumerable#excluding</tt> that uses <tt>Array#-</tt>
|
39
46
|
# instead of <tt>Array#reject</tt> for performance reasons.
|
47
|
+
def excluding(*elements)
|
48
|
+
self - elements.flatten(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Alias for #excluding.
|
40
52
|
def without(*elements)
|
41
|
-
|
53
|
+
excluding(*elements)
|
42
54
|
end
|
43
55
|
|
44
56
|
# Equal to <tt>self[1]</tt>.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Array
|
4
|
+
# Removes and returns the elements for which the block returns a true value.
|
5
|
+
# If no block is given, an Enumerator is returned instead.
|
6
|
+
#
|
7
|
+
# numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
8
|
+
# odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
|
9
|
+
# numbers # => [0, 2, 4, 6, 8]
|
10
|
+
def extract!
|
11
|
+
return to_enum(:extract!) { size } unless block_given?
|
12
|
+
|
13
|
+
extracted_elements = []
|
14
|
+
|
15
|
+
reject! do |element|
|
16
|
+
extracted_elements << element if yield(element)
|
17
|
+
end
|
18
|
+
|
19
|
+
extracted_elements
|
20
|
+
end
|
21
|
+
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# The human way of thinking about adding stuff to the end of a list is with append.
|
5
|
-
alias_method :append, :push unless [].respond_to?(:append)
|
3
|
+
require "active_support/deprecation"
|
6
4
|
|
7
|
-
|
8
|
-
alias_method :prepend, :unshift unless [].respond_to?(:prepend)
|
9
|
-
end
|
5
|
+
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
|
|
84
84
|
# To set a default value for the attribute, pass <tt>default:</tt>, like so:
|
85
85
|
#
|
86
86
|
# class_attribute :settings, default: {}
|
87
|
-
def class_attribute(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
87
|
+
def class_attribute(
|
88
|
+
*attrs,
|
89
|
+
instance_accessor: true,
|
90
|
+
instance_reader: instance_accessor,
|
91
|
+
instance_writer: instance_accessor,
|
92
|
+
instance_predicate: true,
|
93
|
+
default: nil
|
94
|
+
)
|
94
95
|
attrs.each do |name|
|
95
96
|
singleton_class.silence_redefinition_of_method(name)
|
96
|
-
define_singleton_method(name) {
|
97
|
+
define_singleton_method(name) { default }
|
97
98
|
|
98
99
|
singleton_class.silence_redefinition_of_method("#{name}?")
|
99
100
|
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
100
101
|
|
101
|
-
ivar = "@#{name}"
|
102
|
+
ivar = "@#{name}".to_sym
|
102
103
|
|
103
104
|
singleton_class.silence_redefinition_of_method("#{name}=")
|
104
105
|
define_singleton_method("#{name}=") do |val|
|
105
|
-
|
106
|
-
redefine_method(name) { val }
|
107
|
-
end
|
106
|
+
redefine_singleton_method(name) { val }
|
108
107
|
|
109
108
|
if singleton_class?
|
110
109
|
class_eval do
|
@@ -137,10 +136,6 @@ class Class
|
|
137
136
|
instance_variable_set ivar, val
|
138
137
|
end
|
139
138
|
end
|
140
|
-
|
141
|
-
unless default_value.nil?
|
142
|
-
self.send("#{name}=", default_value)
|
143
|
-
end
|
144
139
|
end
|
145
140
|
end
|
146
141
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class Class
|
4
4
|
begin
|
5
5
|
# Test if this Ruby supports each_object against singleton_class
|
6
|
-
ObjectSpace.each_object(Numeric.singleton_class) {}
|
6
|
+
ObjectSpace.each_object(Numeric.singleton_class) { }
|
7
7
|
|
8
8
|
# Returns an array with all classes that are < than its receiver.
|
9
9
|
#
|
@@ -110,12 +110,13 @@ class Date
|
|
110
110
|
# Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
|
111
111
|
# any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
|
112
112
|
def advance(options)
|
113
|
-
options = options.dup
|
114
113
|
d = self
|
115
|
-
|
116
|
-
d = d >> options
|
117
|
-
d = d
|
118
|
-
d = d +
|
114
|
+
|
115
|
+
d = d >> options[:years] * 12 if options[:years]
|
116
|
+
d = d >> options[:months] if options[:months]
|
117
|
+
d = d + options[:weeks] * 7 if options[:weeks]
|
118
|
+
d = d + options[:days] if options[:days]
|
119
|
+
|
119
120
|
d
|
120
121
|
end
|
121
122
|
|
@@ -5,13 +5,13 @@ require "active_support/core_ext/object/try"
|
|
5
5
|
module DateAndTime
|
6
6
|
module Calculations
|
7
7
|
DAYS_INTO_WEEK = {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
sunday: 0,
|
9
|
+
monday: 1,
|
10
|
+
tuesday: 2,
|
11
|
+
wednesday: 3,
|
12
|
+
thursday: 4,
|
13
|
+
friday: 5,
|
14
|
+
saturday: 6
|
15
15
|
}
|
16
16
|
WEEKEND_DAYS = [ 6, 0 ]
|
17
17
|
|
@@ -20,21 +20,11 @@ module DateAndTime
|
|
20
20
|
advance(days: -1)
|
21
21
|
end
|
22
22
|
|
23
|
-
# Returns a new date/time the specified number of days ago.
|
24
|
-
def prev_day(days = 1)
|
25
|
-
advance(days: -days)
|
26
|
-
end
|
27
|
-
|
28
23
|
# Returns a new date/time representing tomorrow.
|
29
24
|
def tomorrow
|
30
25
|
advance(days: 1)
|
31
26
|
end
|
32
27
|
|
33
|
-
# Returns a new date/time the specified number of days in the future.
|
34
|
-
def next_day(days = 1)
|
35
|
-
advance(days: days)
|
36
|
-
end
|
37
|
-
|
38
28
|
# Returns true if the date/time is today.
|
39
29
|
def today?
|
40
30
|
to_date == ::Date.current
|
@@ -60,6 +50,16 @@ module DateAndTime
|
|
60
50
|
!WEEKEND_DAYS.include?(wday)
|
61
51
|
end
|
62
52
|
|
53
|
+
# Returns true if the date/time falls before <tt>date_or_time</tt>.
|
54
|
+
def before?(date_or_time)
|
55
|
+
self < date_or_time
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns true if the date/time falls after <tt>date_or_time</tt>.
|
59
|
+
def after?(date_or_time)
|
60
|
+
self > date_or_time
|
61
|
+
end
|
62
|
+
|
63
63
|
# Returns a new date/time the specified number of days ago.
|
64
64
|
def days_ago(days)
|
65
65
|
advance(days: -days)
|
@@ -124,7 +124,7 @@ module DateAndTime
|
|
124
124
|
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
125
125
|
# now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
|
126
126
|
def beginning_of_quarter
|
127
|
-
first_quarter_month =
|
127
|
+
first_quarter_month = month - (2 + month) % 3
|
128
128
|
beginning_of_month.change(month: first_quarter_month)
|
129
129
|
end
|
130
130
|
alias :at_beginning_of_quarter :beginning_of_quarter
|
@@ -139,7 +139,7 @@ module DateAndTime
|
|
139
139
|
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
140
140
|
# now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
|
141
141
|
def end_of_quarter
|
142
|
-
last_quarter_month =
|
142
|
+
last_quarter_month = month + (12 - month) % 3
|
143
143
|
beginning_of_month.change(month: last_quarter_month).end_of_month
|
144
144
|
end
|
145
145
|
alias :at_end_of_quarter :end_of_quarter
|
@@ -188,21 +188,11 @@ module DateAndTime
|
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
|
-
# Returns a new date/time the specified number of months in the future.
|
192
|
-
def next_month(months = 1)
|
193
|
-
advance(months: months)
|
194
|
-
end
|
195
|
-
|
196
191
|
# Short-hand for months_since(3)
|
197
192
|
def next_quarter
|
198
193
|
months_since(3)
|
199
194
|
end
|
200
195
|
|
201
|
-
# Returns a new date/time the specified number of years in the future.
|
202
|
-
def next_year(years = 1)
|
203
|
-
advance(years: years)
|
204
|
-
end
|
205
|
-
|
206
196
|
# Returns a new date/time representing the given day in the previous week.
|
207
197
|
# Week is assumed to start on +start_day+, default is
|
208
198
|
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
@@ -223,11 +213,6 @@ module DateAndTime
|
|
223
213
|
end
|
224
214
|
alias_method :last_weekday, :prev_weekday
|
225
215
|
|
226
|
-
# Returns a new date/time the specified number of months ago.
|
227
|
-
def prev_month(months = 1)
|
228
|
-
advance(months: -months)
|
229
|
-
end
|
230
|
-
|
231
216
|
# Short-hand for months_ago(1).
|
232
217
|
def last_month
|
233
218
|
months_ago(1)
|
@@ -239,11 +224,6 @@ module DateAndTime
|
|
239
224
|
end
|
240
225
|
alias_method :last_quarter, :prev_quarter
|
241
226
|
|
242
|
-
# Returns a new date/time the specified number of years ago.
|
243
|
-
def prev_year(years = 1)
|
244
|
-
advance(years: -years)
|
245
|
-
end
|
246
|
-
|
247
227
|
# Short-hand for years_ago(1).
|
248
228
|
def last_year
|
249
229
|
years_ago(1)
|
@@ -253,9 +233,8 @@ module DateAndTime
|
|
253
233
|
# Week is assumed to start on +start_day+, default is
|
254
234
|
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
255
235
|
def days_to_week_start(start_day = Date.beginning_of_week)
|
256
|
-
start_day_number = DAYS_INTO_WEEK
|
257
|
-
|
258
|
-
(current_day_number - start_day_number) % 7
|
236
|
+
start_day_number = DAYS_INTO_WEEK.fetch(start_day)
|
237
|
+
(wday - start_day_number) % 7
|
259
238
|
end
|
260
239
|
|
261
240
|
# Returns a new date/time representing the start of this week on the given day.
|
@@ -336,8 +315,7 @@ module DateAndTime
|
|
336
315
|
# today.next_occurring(:monday) # => Mon, 18 Dec 2017
|
337
316
|
# today.next_occurring(:thursday) # => Thu, 21 Dec 2017
|
338
317
|
def next_occurring(day_of_week)
|
339
|
-
|
340
|
-
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number
|
318
|
+
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
|
341
319
|
from_now += 7 unless from_now > 0
|
342
320
|
advance(days: from_now)
|
343
321
|
end
|
@@ -348,8 +326,7 @@ module DateAndTime
|
|
348
326
|
# today.prev_occurring(:monday) # => Mon, 11 Dec 2017
|
349
327
|
# today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
|
350
328
|
def prev_occurring(day_of_week)
|
351
|
-
|
352
|
-
ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week)
|
329
|
+
ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
|
353
330
|
ago += 7 unless ago > 0
|
354
331
|
advance(days: -ago)
|
355
332
|
end
|
@@ -364,7 +341,7 @@ module DateAndTime
|
|
364
341
|
end
|
365
342
|
|
366
343
|
def days_span(day)
|
367
|
-
(DAYS_INTO_WEEK
|
344
|
+
(DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
|
368
345
|
end
|
369
346
|
|
370
347
|
def copy_time_to(other)
|