activesupport 5.1.1 → 6.1.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 +5 -5
- data/CHANGELOG.md +360 -442
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +6 -2
- data/lib/active_support/backtrace_cleaner.rb +31 -3
- data/lib/active_support/benchmarkable.rb +3 -1
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +37 -36
- data/lib/active_support/cache/mem_cache_store.rb +65 -53
- data/lib/active_support/cache/memory_store.rb +61 -33
- data/lib/active_support/cache/null_store.rb +10 -3
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +68 -22
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +305 -127
- data/lib/active_support/callbacks.rb +106 -98
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -1
- data/lib/active_support/configurable.rb +12 -14
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +7 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +3 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +18 -40
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +8 -5
- data/lib/active_support/core_ext/date/conversions.rb +12 -10
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +174 -71
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -5
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +3 -30
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/marshal.rb +4 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +103 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +3 -1
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +2 -1
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +13 -3
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +6 -101
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +22 -2
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +7 -2
- data/lib/active_support/core_ext/object/try.rb +19 -7
- data/lib/active_support/core_ext/object/with_options.rb +4 -2
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +3 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +3 -0
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +76 -20
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +73 -18
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +4 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +11 -6
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +135 -60
- data/lib/active_support/deprecation/behaviors.rb +43 -11
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +30 -15
- data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +9 -2
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +6 -6
- data/lib/active_support/duration/iso8601_serializer.rb +20 -14
- data/lib/active_support/duration.rb +179 -41
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +84 -117
- data/lib/active_support/execution_wrapper.rb +3 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +3 -1
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +134 -37
- data/lib/active_support/i18n.rb +4 -1
- data/lib/active_support/i18n_railtie.rb +20 -11
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +19 -8
- data/lib/active_support/inflector/methods.rb +87 -77
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +13 -3
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -33
- data/lib/active_support/lazy_load_hooks.rb +33 -10
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/log_subscriber.rb +46 -13
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +54 -7
- data/lib/active_support/message_encryptor.rb +101 -33
- data/lib/active_support/message_verifier.rb +85 -14
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +12 -68
- data/lib/active_support/multibyte/unicode.rb +17 -327
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +118 -16
- data/lib/active_support/notifications/instrumenter.rb +73 -9
- data/lib/active_support/notifications.rb +74 -8
- data/lib/active_support/number_helper/number_converter.rb +7 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +8 -7
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +16 -53
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +41 -12
- data/lib/active_support/option_merger.rb +24 -3
- data/lib/active_support/ordered_hash.rb +3 -1
- data/lib/active_support/ordered_options.rb +17 -5
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +3 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +60 -9
- data/lib/active_support/reloader.rb +11 -10
- data/lib/active_support/rescuable.rb +7 -6
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +6 -3
- data/lib/active_support/subscriber.rb +74 -24
- data/lib/active_support/tagged_logging.rb +44 -8
- data/lib/active_support/test_case.rb +94 -2
- data/lib/active_support/testing/assertions.rb +58 -20
- data/lib/active_support/testing/autorun.rb +2 -4
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -1
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +8 -4
- data/lib/active_support/testing/method_call_assertions.rb +30 -1
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +3 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +78 -13
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +113 -41
- data/lib/active_support/values/time_zone.rb +55 -25
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini/jdom.rb +5 -4
- data/lib/active_support/xml_mini/libxml.rb +4 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
- data/lib/active_support/xml_mini/nokogiri.rb +4 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
- data/lib/active_support/xml_mini/rexml.rb +12 -3
- data/lib/active_support/xml_mini.rb +5 -11
- data/lib/active_support.rb +18 -13
- metadata +81 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,22 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "delegate"
|
2
4
|
|
3
5
|
module ActiveSupport
|
4
6
|
module Tryable #:nodoc:
|
5
|
-
def try(*
|
6
|
-
|
7
|
+
def try(method_name = nil, *args, &b)
|
8
|
+
if method_name.nil? && block_given?
|
9
|
+
if b.arity == 0
|
10
|
+
instance_eval(&b)
|
11
|
+
else
|
12
|
+
yield self
|
13
|
+
end
|
14
|
+
elsif respond_to?(method_name)
|
15
|
+
public_send(method_name, *args, &b)
|
16
|
+
end
|
7
17
|
end
|
18
|
+
ruby2_keywords(:try) if respond_to?(:ruby2_keywords, true)
|
8
19
|
|
9
|
-
def try!(*
|
10
|
-
if
|
20
|
+
def try!(method_name = nil, *args, &b)
|
21
|
+
if method_name.nil? && block_given?
|
11
22
|
if b.arity == 0
|
12
23
|
instance_eval(&b)
|
13
24
|
else
|
14
25
|
yield self
|
15
26
|
end
|
16
27
|
else
|
17
|
-
public_send(*
|
28
|
+
public_send(method_name, *args, &b)
|
18
29
|
end
|
19
30
|
end
|
31
|
+
ruby2_keywords(:try!) if respond_to?(:ruby2_keywords, true)
|
20
32
|
end
|
21
33
|
end
|
22
34
|
|
@@ -133,14 +145,14 @@ class NilClass
|
|
133
145
|
#
|
134
146
|
# With +try+
|
135
147
|
# @person.try(:children).try(:first).try(:name)
|
136
|
-
def try(*
|
148
|
+
def try(_method_name = nil, *)
|
137
149
|
nil
|
138
150
|
end
|
139
151
|
|
140
152
|
# Calling +try!+ on +nil+ always returns +nil+.
|
141
153
|
#
|
142
154
|
# nil.try!(:name) # => nil
|
143
|
-
def try!(*
|
155
|
+
def try!(_method_name = nil, *)
|
144
156
|
nil
|
145
157
|
end
|
146
158
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/option_merger"
|
2
4
|
|
3
5
|
class Object
|
@@ -60,13 +62,13 @@ class Object
|
|
60
62
|
#
|
61
63
|
# validates :content, length: { minimum: 50 }, if: -> { content.present? }
|
62
64
|
#
|
63
|
-
# Hence the inherited default for
|
65
|
+
# Hence the inherited default for +if+ key is ignored.
|
64
66
|
#
|
65
67
|
# NOTE: You cannot call class methods implicitly inside of with_options.
|
66
68
|
# You can access these methods using the class name instead:
|
67
69
|
#
|
68
70
|
# class Phone < ActiveRecord::Base
|
69
|
-
# enum phone_number_type:
|
71
|
+
# enum phone_number_type: { home: 0, office: 1, mobile: 2 }
|
70
72
|
#
|
71
73
|
# with_options presence: true do
|
72
74
|
# validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module CompareWithRange
|
5
|
+
# Extends the default Range#=== to support range comparisons.
|
6
|
+
# (1..5) === (1..5) # => true
|
7
|
+
# (1..5) === (2..3) # => true
|
8
|
+
# (1..5) === (1...6) # => true
|
9
|
+
# (1..5) === (2..6) # => false
|
10
|
+
#
|
11
|
+
# The native Range#=== behavior is untouched.
|
12
|
+
# ('a'..'f') === ('c') # => true
|
13
|
+
# (5..9) === (11) # => false
|
14
|
+
#
|
15
|
+
# The given range must be fully bounded, with both start and end.
|
16
|
+
def ===(value)
|
17
|
+
if value.is_a?(::Range)
|
18
|
+
is_backwards_op = value.exclude_end? ? :>= : :>
|
19
|
+
return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
|
20
|
+
# 1...10 includes 1..9 but it does not include 1..10.
|
21
|
+
# 1..10 includes 1...11 but it does not include 1...12.
|
22
|
+
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
23
|
+
value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
|
24
|
+
super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Extends the default Range#include? to support range comparisons.
|
31
|
+
# (1..5).include?(1..5) # => true
|
32
|
+
# (1..5).include?(2..3) # => true
|
33
|
+
# (1..5).include?(1...6) # => true
|
34
|
+
# (1..5).include?(2..6) # => false
|
35
|
+
#
|
36
|
+
# The native Range#include? behavior is untouched.
|
37
|
+
# ('a'..'f').include?('c') # => true
|
38
|
+
# (5..9).include?(11) # => false
|
39
|
+
#
|
40
|
+
# The given range must be fully bounded, with both start and end.
|
41
|
+
def include?(value)
|
42
|
+
if value.is_a?(::Range)
|
43
|
+
is_backwards_op = value.exclude_end? ? :>= : :>
|
44
|
+
return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
|
45
|
+
# 1...10 includes 1..9 but it does not include 1..10.
|
46
|
+
# 1..10 includes 1...11 but it does not include 1...12.
|
47
|
+
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
48
|
+
value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
|
49
|
+
super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Extends the default Range#cover? to support range comparisons.
|
56
|
+
# (1..5).cover?(1..5) # => true
|
57
|
+
# (1..5).cover?(2..3) # => true
|
58
|
+
# (1..5).cover?(1...6) # => true
|
59
|
+
# (1..5).cover?(2..6) # => false
|
60
|
+
#
|
61
|
+
# The native Range#cover? behavior is untouched.
|
62
|
+
# ('a'..'f').cover?('c') # => true
|
63
|
+
# (5..9).cover?(11) # => false
|
64
|
+
#
|
65
|
+
# The given range must be fully bounded, with both start and end.
|
66
|
+
def cover?(value)
|
67
|
+
if value.is_a?(::Range)
|
68
|
+
is_backwards_op = value.exclude_end? ? :>= : :>
|
69
|
+
return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
|
70
|
+
# 1...10 covers 1..9 but it does not cover 1..10.
|
71
|
+
# 1..10 covers 1...11 but it does not cover 1...12.
|
72
|
+
operator = exclude_end? && !value.exclude_end? ? :< : :<=
|
73
|
+
value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
|
74
|
+
super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
Range.prepend(ActiveSupport::CompareWithRange)
|
@@ -1,31 +1,41 @@
|
|
1
|
-
|
2
|
-
RANGE_FORMATS = {
|
3
|
-
db: Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
|
4
|
-
}
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
3
|
+
module ActiveSupport
|
4
|
+
module RangeWithFormat
|
5
|
+
RANGE_FORMATS = {
|
6
|
+
db: -> (start, stop) do
|
7
|
+
case start
|
8
|
+
when String then "BETWEEN '#{start}' AND '#{stop}'"
|
9
|
+
else
|
10
|
+
"BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
}
|
14
|
+
|
15
|
+
# Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
|
16
|
+
#
|
17
|
+
# range = (1..100) # => 1..100
|
18
|
+
#
|
19
|
+
# range.to_s # => "1..100"
|
20
|
+
# range.to_s(:db) # => "BETWEEN '1' AND '100'"
|
21
|
+
#
|
22
|
+
# == Adding your own range formats to to_s
|
23
|
+
# You can add your own formats to the Range::RANGE_FORMATS hash.
|
24
|
+
# Use the format name as the hash key and a Proc instance.
|
25
|
+
#
|
26
|
+
# # config/initializers/range_formats.rb
|
27
|
+
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
|
28
|
+
def to_s(format = :default)
|
29
|
+
if formatter = RANGE_FORMATS[format]
|
30
|
+
formatter.call(first, last)
|
31
|
+
else
|
32
|
+
super()
|
33
|
+
end
|
24
34
|
end
|
25
|
-
end
|
26
35
|
|
27
|
-
|
28
|
-
|
36
|
+
alias_method :to_default_s, :to_s
|
37
|
+
alias_method :to_formatted_s, :to_s
|
38
|
+
end
|
29
39
|
end
|
30
40
|
|
31
41
|
Range.prepend(ActiveSupport::RangeWithFormat)
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module EachTimeWithZone #:nodoc:
|
3
7
|
def each(&block)
|
@@ -11,9 +15,8 @@ module ActiveSupport
|
|
11
15
|
end
|
12
16
|
|
13
17
|
private
|
14
|
-
|
15
18
|
def ensure_iteration_allowed
|
16
|
-
raise TypeError, "can't iterate from #{first.class}" if first.is_a?(
|
19
|
+
raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone)
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
require "active_support/deprecation"
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module IncludeTimeWithZone #:nodoc:
|
8
|
+
# Extends the default Range#include? to support ActiveSupport::TimeWithZone.
|
9
|
+
#
|
10
|
+
# (1.hour.ago..1.hour.from_now).include?(Time.current) # => true
|
11
|
+
#
|
12
|
+
def include?(value)
|
13
|
+
if self.begin.is_a?(TimeWithZone) || self.end.is_a?(TimeWithZone)
|
14
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
15
|
+
Using `Range#include?` to check the inclusion of a value in
|
16
|
+
a date time range is deprecated.
|
17
|
+
It is recommended to use `Range#cover?` instead of `Range#include?` to
|
18
|
+
check the inclusion of a value in a date time range.
|
19
|
+
MSG
|
20
|
+
cover?(value)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Range.prepend(ActiveSupport::IncludeTimeWithZone)
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/range/conversions"
|
2
|
-
require "active_support/core_ext/range/
|
4
|
+
require "active_support/core_ext/range/compare_range"
|
5
|
+
require "active_support/core_ext/range/include_time_with_zone"
|
3
6
|
require "active_support/core_ext/range/overlaps"
|
4
7
|
require "active_support/core_ext/range/each"
|
@@ -1,9 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Regexp
|
4
|
+
# Returns +true+ if the regexp has the multiline flag set.
|
5
|
+
#
|
6
|
+
# (/./).multiline? # => false
|
7
|
+
# (/./m).multiline? # => true
|
8
|
+
#
|
9
|
+
# Regexp.new(".").multiline? # => false
|
10
|
+
# Regexp.new(".", Regexp::MULTILINE).multiline? # => true
|
2
11
|
def multiline?
|
3
12
|
options & MULTILINE == MULTILINE
|
4
13
|
end
|
5
|
-
|
6
|
-
def match?(string, pos = 0)
|
7
|
-
!!match(string, pos)
|
8
|
-
end unless //.respond_to?(:match?)
|
9
14
|
end
|
@@ -1,18 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "securerandom"
|
2
4
|
|
3
5
|
module SecureRandom
|
4
6
|
BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
|
7
|
+
BASE36_ALPHABET = ("0".."9").to_a + ("a".."z").to_a
|
8
|
+
|
5
9
|
# SecureRandom.base58 generates a random base58 string.
|
6
10
|
#
|
7
|
-
# The argument _n_ specifies the length
|
11
|
+
# The argument _n_ specifies the length of the random string to be generated.
|
8
12
|
#
|
9
13
|
# If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
|
10
14
|
#
|
11
|
-
# The result may contain alphanumeric characters except 0, O, I and l
|
15
|
+
# The result may contain alphanumeric characters except 0, O, I and l.
|
12
16
|
#
|
13
17
|
# p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
|
14
18
|
# p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
15
|
-
#
|
16
19
|
def self.base58(n = 16)
|
17
20
|
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
18
21
|
idx = byte % 64
|
@@ -20,4 +23,23 @@ module SecureRandom
|
|
20
23
|
BASE58_ALPHABET[idx]
|
21
24
|
end.join
|
22
25
|
end
|
26
|
+
|
27
|
+
# SecureRandom.base36 generates a random base36 string in lowercase.
|
28
|
+
#
|
29
|
+
# The argument _n_ specifies the length of the random string to be generated.
|
30
|
+
#
|
31
|
+
# If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
|
32
|
+
# This method can be used over +base58+ if a deterministic case key is necessary.
|
33
|
+
#
|
34
|
+
# The result will contain alphanumeric characters in lowercase.
|
35
|
+
#
|
36
|
+
# p SecureRandom.base36 # => "4kugl2pdqmscqtje"
|
37
|
+
# p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
|
38
|
+
def self.base36(n = 16)
|
39
|
+
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
40
|
+
idx = byte % 64
|
41
|
+
idx = SecureRandom.random_number(36) if idx >= 36
|
42
|
+
BASE36_ALPHABET[idx]
|
43
|
+
end.join
|
44
|
+
end
|
23
45
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class String
|
2
4
|
# If you pass a single integer, returns a substring of one character at that
|
3
5
|
# position. The first character of the string is at position 0, the next at
|
@@ -42,7 +44,7 @@ class String
|
|
42
44
|
# str.from(0).to(-1) # => "hello"
|
43
45
|
# str.from(1).to(-2) # => "ell"
|
44
46
|
def from(position)
|
45
|
-
self[position
|
47
|
+
self[position, length]
|
46
48
|
end
|
47
49
|
|
48
50
|
# Returns a substring from the beginning of the string to the given position.
|
@@ -59,7 +61,8 @@ class String
|
|
59
61
|
# str.from(0).to(-1) # => "hello"
|
60
62
|
# str.from(1).to(-2) # => "ell"
|
61
63
|
def to(position)
|
62
|
-
|
64
|
+
position += size if position < 0
|
65
|
+
self[0, position + 1] || +""
|
63
66
|
end
|
64
67
|
|
65
68
|
# Returns the first character. If a limit is supplied, returns a substring
|
@@ -73,13 +76,7 @@ class String
|
|
73
76
|
# str.first(0) # => ""
|
74
77
|
# str.first(6) # => "hello"
|
75
78
|
def first(limit = 1)
|
76
|
-
|
77
|
-
""
|
78
|
-
elsif limit >= size
|
79
|
-
dup
|
80
|
-
else
|
81
|
-
to(limit - 1)
|
82
|
-
end
|
79
|
+
self[0, limit] || raise(ArgumentError, "negative limit")
|
83
80
|
end
|
84
81
|
|
85
82
|
# Returns the last character of the string. If a limit is supplied, returns a substring
|
@@ -93,12 +90,6 @@ class String
|
|
93
90
|
# str.last(0) # => ""
|
94
91
|
# str.last(6) # => "hello"
|
95
92
|
def last(limit = 1)
|
96
|
-
|
97
|
-
""
|
98
|
-
elsif limit >= size
|
99
|
-
dup
|
100
|
-
else
|
101
|
-
from(-limit)
|
102
|
-
end
|
93
|
+
self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
|
103
94
|
end
|
104
95
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "date"
|
2
4
|
require "active_support/core_ext/time/calculations"
|
3
5
|
|
@@ -16,6 +18,7 @@ class String
|
|
16
18
|
# "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
|
17
19
|
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
|
18
20
|
# "12/13/2012".to_time # => ArgumentError: argument out of range
|
21
|
+
# "1604326192".to_time # => ArgumentError: argument out of range
|
19
22
|
def to_time(form = :local)
|
20
23
|
parts = Date._parse(self, false)
|
21
24
|
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class String
|
2
4
|
# Returns the string, first removing all whitespace on both ends of
|
3
5
|
# the string, and then changing remaining consecutive whitespace
|
@@ -73,7 +75,48 @@ class String
|
|
73
75
|
length_with_room_for_omission
|
74
76
|
end
|
75
77
|
|
76
|
-
"#{self[0, stop]}#{omission}"
|
78
|
+
+"#{self[0, stop]}#{omission}"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
|
82
|
+
# breaking string encoding by splitting multibyte characters or breaking
|
83
|
+
# grapheme clusters ("perceptual characters") by truncating at combining
|
84
|
+
# characters.
|
85
|
+
#
|
86
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
|
87
|
+
# => 20
|
88
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
|
89
|
+
# => 80
|
90
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
|
91
|
+
# => "🔪🔪🔪🔪…"
|
92
|
+
#
|
93
|
+
# The truncated text ends with the <tt>:omission</tt> string, defaulting
|
94
|
+
# to "…", for a total length not exceeding <tt>bytesize</tt>.
|
95
|
+
def truncate_bytes(truncate_at, omission: "…")
|
96
|
+
omission ||= ""
|
97
|
+
|
98
|
+
case
|
99
|
+
when bytesize <= truncate_at
|
100
|
+
dup
|
101
|
+
when omission.bytesize > truncate_at
|
102
|
+
raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
|
103
|
+
when omission.bytesize == truncate_at
|
104
|
+
omission.dup
|
105
|
+
else
|
106
|
+
self.class.new.tap do |cut|
|
107
|
+
cut_at = truncate_at - omission.bytesize
|
108
|
+
|
109
|
+
scan(/\X/) do |grapheme|
|
110
|
+
if cut.bytesize + grapheme.bytesize <= cut_at
|
111
|
+
cut << grapheme
|
112
|
+
else
|
113
|
+
break
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
cut << omission
|
118
|
+
end
|
119
|
+
end
|
77
120
|
end
|
78
121
|
|
79
122
|
# Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
|