activesupport 4.2.11.1 → 6.0.3.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 +399 -411
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +34 -6
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +58 -53
- data/lib/active_support/cache/mem_cache_store.rb +95 -91
- data/lib/active_support/cache/memory_store.rb +39 -36
- data/lib/active_support/cache/null_store.rb +11 -7
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +75 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +331 -217
- data/lib/active_support/callbacks.rb +650 -592
- data/lib/active_support/concern.rb +35 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +13 -14
- data/lib/active_support/core_ext/array/access.rb +41 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -20
- 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 +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +45 -31
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -6
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +25 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +114 -22
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/compact.rb +4 -23
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -9
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +19 -42
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +5 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
- data/lib/active_support/core_ext/hash.rb +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +8 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +133 -30
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +44 -19
- data/lib/active_support/core_ext/module/reachable.rb +5 -7
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -11
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
- data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +5 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -3
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +13 -93
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +51 -20
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +81 -23
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +76 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_range.rb +7 -21
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +2 -0
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +16 -6
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +7 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +48 -6
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +66 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +16 -7
- data/lib/active_support/core_ext/string/output_safety.rb +93 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +115 -52
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +6 -7
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +203 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +208 -166
- data/lib/active_support/deprecation/behaviors.rb +44 -11
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +61 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/descendants_tracker.rb +57 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +53 -0
- data/lib/active_support/duration.rb +315 -40
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +100 -0
- data/lib/active_support/evented_file_update_checker.rb +234 -0
- data/lib/active_support/execution_wrapper.rb +129 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/gem_version.rb +6 -4
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +129 -30
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +50 -14
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -13
- data/lib/active_support/inflector/methods.rb +159 -145
- data/lib/active_support/inflector/transliterate.rb +84 -34
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +17 -60
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +11 -43
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +44 -19
- data/lib/active_support/logger.rb +9 -23
- data/lib/active_support/logger_silence.rb +32 -14
- data/lib/active_support/logger_thread_safe_level.rb +32 -8
- data/lib/active_support/message_encryptor.rb +166 -53
- data/lib/active_support/message_verifier.rb +149 -16
- data/lib/active_support/messages/metadata.rb +72 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte/chars.rb +56 -63
- data/lib/active_support/multibyte/unicode.rb +56 -290
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +109 -22
- data/lib/active_support/notifications/instrumenter.rb +107 -16
- data/lib/active_support/notifications.rb +51 -10
- data/lib/active_support/number_helper/number_converter.rb +16 -15
- data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +105 -68
- data/lib/active_support/option_merger.rb +24 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +27 -5
- data/lib/active_support/parameter_filter.rb +128 -0
- data/lib/active_support/per_thread_registry.rb +9 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +74 -30
- data/lib/active_support/tagged_logging.rb +25 -13
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +151 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +13 -10
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +35 -26
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization.rb +134 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +43 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +84 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +179 -39
- data/lib/active_support/values/time_zone.rb +203 -63
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -115
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +11 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +13 -11
- metadata +84 -26
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
|
5
|
+
module SecureRandom
|
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
|
+
|
9
|
+
# SecureRandom.base58 generates a random base58 string.
|
10
|
+
#
|
11
|
+
# The argument _n_ specifies the length of the random string to be generated.
|
12
|
+
#
|
13
|
+
# If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
|
14
|
+
#
|
15
|
+
# The result may contain alphanumeric characters except 0, O, I and l.
|
16
|
+
#
|
17
|
+
# p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
|
18
|
+
# p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
19
|
+
def self.base58(n = 16)
|
20
|
+
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
21
|
+
idx = byte % 64
|
22
|
+
idx = SecureRandom.random_number(58) if idx >= 58
|
23
|
+
BASE58_ALPHABET[idx]
|
24
|
+
end.join
|
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
|
45
|
+
end
|
@@ -1,9 +1,11 @@
|
|
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
|
4
6
|
# position 1, and so on. If a range is supplied, a substring containing
|
5
7
|
# characters at offsets given by the range is returned. In both cases, if an
|
6
|
-
# offset is negative, it is counted from the end of the string. Returns nil
|
8
|
+
# offset is negative, it is counted from the end of the string. Returns +nil+
|
7
9
|
# if the initial offset falls outside the string. Returns an empty string if
|
8
10
|
# the beginning of the range is greater than the end of the string.
|
9
11
|
#
|
@@ -17,7 +19,7 @@ class String
|
|
17
19
|
#
|
18
20
|
# If a Regexp is given, the matching portion of the string is returned.
|
19
21
|
# If a String is given, that given string is returned if it occurs in
|
20
|
-
# the string. In both cases, nil is returned if there is no match.
|
22
|
+
# the string. In both cases, +nil+ is returned if there is no match.
|
21
23
|
#
|
22
24
|
# str = "hello"
|
23
25
|
# str.at(/lo/) # => "lo"
|
@@ -73,10 +75,14 @@ class String
|
|
73
75
|
# str.first(0) # => ""
|
74
76
|
# str.first(6) # => "hello"
|
75
77
|
def first(limit = 1)
|
78
|
+
ActiveSupport::Deprecation.warn(
|
79
|
+
"Calling String#first with a negative integer limit " \
|
80
|
+
"will raise an ArgumentError in Rails 6.1."
|
81
|
+
) if limit < 0
|
76
82
|
if limit == 0
|
77
|
-
|
83
|
+
""
|
78
84
|
elsif limit >= size
|
79
|
-
|
85
|
+
dup
|
80
86
|
else
|
81
87
|
to(limit - 1)
|
82
88
|
end
|
@@ -93,10 +99,14 @@ class String
|
|
93
99
|
# str.last(0) # => ""
|
94
100
|
# str.last(6) # => "hello"
|
95
101
|
def last(limit = 1)
|
102
|
+
ActiveSupport::Deprecation.warn(
|
103
|
+
"Calling String#last with a negative integer limit " \
|
104
|
+
"will raise an ArgumentError in Rails 6.1."
|
105
|
+
) if limit < 0
|
96
106
|
if limit == 0
|
97
|
-
|
107
|
+
""
|
98
108
|
elsif limit >= size
|
99
|
-
|
109
|
+
dup
|
100
110
|
else
|
101
111
|
from(-limit)
|
102
112
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class String
|
2
|
-
#
|
4
|
+
# Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
|
3
5
|
def acts_like_string?
|
4
6
|
true
|
5
7
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "active_support/core_ext/time/calculations"
|
3
5
|
|
4
6
|
class String
|
5
7
|
# Converts a string to a Time value.
|
@@ -14,11 +16,12 @@ class String
|
|
14
16
|
# "06:12".to_time # => 2012-12-13 06:12:00 +0100
|
15
17
|
# "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
|
16
18
|
# "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
|
17
|
-
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13
|
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
|
19
21
|
def to_time(form = :local)
|
20
22
|
parts = Date._parse(self, false)
|
21
|
-
|
23
|
+
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
24
|
+
return if (parts.keys & used_keys).empty?
|
22
25
|
|
23
26
|
now = Time.now
|
24
27
|
time = Time.new(
|
@@ -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
|
@@ -17,9 +19,8 @@ class String
|
|
17
19
|
# str.squish! # => "foo bar boo"
|
18
20
|
# str # => "foo bar boo"
|
19
21
|
def squish!
|
20
|
-
gsub!(
|
21
|
-
|
22
|
-
gsub!(/[[:space:]]+/, ' ')
|
22
|
+
gsub!(/[[:space:]]+/, " ")
|
23
|
+
strip!
|
23
24
|
self
|
24
25
|
end
|
25
26
|
|
@@ -65,7 +66,7 @@ class String
|
|
65
66
|
def truncate(truncate_at, options = {})
|
66
67
|
return dup unless length > truncate_at
|
67
68
|
|
68
|
-
omission = options[:omission] ||
|
69
|
+
omission = options[:omission] || "..."
|
69
70
|
length_with_room_for_omission = truncate_at - omission.length
|
70
71
|
stop = \
|
71
72
|
if options[:separator]
|
@@ -74,7 +75,48 @@ class String
|
|
74
75
|
length_with_room_for_omission
|
75
76
|
end
|
76
77
|
|
77
|
-
"#{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
|
78
120
|
end
|
79
121
|
|
80
122
|
# Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
|
@@ -95,7 +137,7 @@ class String
|
|
95
137
|
sep = options[:separator] || /\s+/
|
96
138
|
sep = Regexp.escape(sep.to_s) unless Regexp === sep
|
97
139
|
if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
|
98
|
-
$1 + (options[:omission] ||
|
140
|
+
$1 + (options[:omission] || "...")
|
99
141
|
else
|
100
142
|
dup
|
101
143
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class String
|
2
4
|
# Same as +indent+, except it indents the receiver in-place.
|
3
5
|
#
|
4
6
|
# Returns the indented string, or +nil+ if there was nothing to indent.
|
5
|
-
def indent!(amount, indent_string=nil, indent_empty_lines=false)
|
6
|
-
indent_string = indent_string || self[/^[ \t]/] ||
|
7
|
+
def indent!(amount, indent_string = nil, indent_empty_lines = false)
|
8
|
+
indent_string = indent_string || self[/^[ \t]/] || " "
|
7
9
|
re = indent_empty_lines ? /^/ : /^(?!$)/
|
8
10
|
gsub!(re, indent_string * amount)
|
9
11
|
end
|
@@ -37,7 +39,7 @@ class String
|
|
37
39
|
# "foo\n\nbar".indent(2) # => " foo\n\n bar"
|
38
40
|
# "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
|
39
41
|
#
|
40
|
-
def indent(amount, indent_string=nil, indent_empty_lines=false)
|
41
|
-
dup.tap {|_| _.indent!(amount, indent_string, indent_empty_lines)}
|
42
|
+
def indent(amount, indent_string = nil, indent_empty_lines = false)
|
43
|
+
dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
|
42
44
|
end
|
43
45
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/inflector/methods"
|
4
|
+
require "active_support/inflector/transliterate"
|
3
5
|
|
4
6
|
# String inflections define new methods on the String class to transform names for different purposes.
|
5
7
|
# For instance, you can figure out the name of a table from the name of a class.
|
@@ -31,7 +33,7 @@ class String
|
|
31
33
|
def pluralize(count = nil, locale = :en)
|
32
34
|
locale = count if count.is_a?(Symbol)
|
33
35
|
if count == 1
|
34
|
-
|
36
|
+
dup
|
35
37
|
else
|
36
38
|
ActiveSupport::Inflector.pluralize(self, locale)
|
37
39
|
end
|
@@ -67,7 +69,7 @@ class String
|
|
67
69
|
end
|
68
70
|
|
69
71
|
# +safe_constantize+ tries to find a declared constant with the name specified
|
70
|
-
# in the string. It returns nil when the name is not in CamelCase
|
72
|
+
# in the string. It returns +nil+ when the name is not in CamelCase
|
71
73
|
# or is not initialized. See ActiveSupport::Inflector.safe_constantize
|
72
74
|
#
|
73
75
|
# 'Module'.safe_constantize # => Module
|
@@ -92,6 +94,8 @@ class String
|
|
92
94
|
ActiveSupport::Inflector.camelize(self, true)
|
93
95
|
when :lower
|
94
96
|
ActiveSupport::Inflector.camelize(self, false)
|
97
|
+
else
|
98
|
+
raise ArgumentError, "Invalid option, use either :upper or :lower."
|
95
99
|
end
|
96
100
|
end
|
97
101
|
alias_method :camelcase, :camelize
|
@@ -100,12 +104,17 @@ class String
|
|
100
104
|
# a nicer looking title. +titleize+ is meant for creating pretty output. It is not
|
101
105
|
# used in the Rails internals.
|
102
106
|
#
|
107
|
+
# The trailing '_id','Id'.. can be kept and capitalized by setting the
|
108
|
+
# optional parameter +keep_id_suffix+ to true.
|
109
|
+
# By default, this parameter is false.
|
110
|
+
#
|
103
111
|
# +titleize+ is also aliased as +titlecase+.
|
104
112
|
#
|
105
|
-
# 'man from the boondocks'.titleize
|
106
|
-
# 'x-men: the last stand'.titleize
|
107
|
-
|
108
|
-
|
113
|
+
# 'man from the boondocks'.titleize # => "Man From The Boondocks"
|
114
|
+
# 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
|
115
|
+
# 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
|
116
|
+
def titleize(keep_id_suffix: false)
|
117
|
+
ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
|
109
118
|
end
|
110
119
|
alias_method :titlecase, :titleize
|
111
120
|
|
@@ -128,10 +137,10 @@ class String
|
|
128
137
|
|
129
138
|
# Removes the module part from the constant expression in the string.
|
130
139
|
#
|
131
|
-
# '
|
132
|
-
# 'Inflections'.demodulize
|
133
|
-
# '::Inflections'.demodulize
|
134
|
-
# ''.demodulize
|
140
|
+
# 'ActiveSupport::Inflector::Inflections'.demodulize # => "Inflections"
|
141
|
+
# 'Inflections'.demodulize # => "Inflections"
|
142
|
+
# '::Inflections'.demodulize # => "Inflections"
|
143
|
+
# ''.demodulize # => ''
|
135
144
|
#
|
136
145
|
# See also +deconstantize+.
|
137
146
|
def demodulize
|
@@ -153,6 +162,11 @@ class String
|
|
153
162
|
|
154
163
|
# Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
|
155
164
|
#
|
165
|
+
# If the optional parameter +locale+ is specified,
|
166
|
+
# the word will be parameterized as a word of that language.
|
167
|
+
# By default, this parameter is set to <tt>nil</tt> and it will use
|
168
|
+
# the configured <tt>I18n.locale</tt>.
|
169
|
+
#
|
156
170
|
# class Person
|
157
171
|
# def to_param
|
158
172
|
# "#{id}-#{name.parameterize}"
|
@@ -164,31 +178,45 @@ class String
|
|
164
178
|
#
|
165
179
|
# <%= link_to(@person.name, person_path) %>
|
166
180
|
# # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
|
167
|
-
|
168
|
-
|
181
|
+
#
|
182
|
+
# To preserve the case of the characters in a string, use the +preserve_case+ argument.
|
183
|
+
#
|
184
|
+
# class Person
|
185
|
+
# def to_param
|
186
|
+
# "#{id}-#{name.parameterize(preserve_case: true)}"
|
187
|
+
# end
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# @person = Person.find(1)
|
191
|
+
# # => #<Person id: 1, name: "Donald E. Knuth">
|
192
|
+
#
|
193
|
+
# <%= link_to(@person.name, person_path) %>
|
194
|
+
# # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
|
195
|
+
def parameterize(separator: "-", preserve_case: false, locale: nil)
|
196
|
+
ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
|
169
197
|
end
|
170
198
|
|
171
199
|
# Creates the name of a table like Rails does for models to table names. This method
|
172
200
|
# uses the +pluralize+ method on the last word in the string.
|
173
201
|
#
|
174
202
|
# 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
|
175
|
-
# '
|
203
|
+
# 'ham_and_egg'.tableize # => "ham_and_eggs"
|
176
204
|
# 'fancyCategory'.tableize # => "fancy_categories"
|
177
205
|
def tableize
|
178
206
|
ActiveSupport::Inflector.tableize(self)
|
179
207
|
end
|
180
208
|
|
181
|
-
#
|
209
|
+
# Creates a class name from a plural table name like Rails does for table names to models.
|
182
210
|
# Note that this returns a string and not a class. (To convert to an actual class
|
183
211
|
# follow +classify+ with +constantize+.)
|
184
212
|
#
|
185
|
-
# '
|
213
|
+
# 'ham_and_eggs'.classify # => "HamAndEgg"
|
186
214
|
# 'posts'.classify # => "Post"
|
187
215
|
def classify
|
188
216
|
ActiveSupport::Inflector.classify(self)
|
189
217
|
end
|
190
218
|
|
191
|
-
# Capitalizes the first word, turns underscores into spaces, and strips a
|
219
|
+
# Capitalizes the first word, turns underscores into spaces, and (by default)strips a
|
192
220
|
# trailing '_id' if present.
|
193
221
|
# Like +titleize+, this is meant for creating pretty output.
|
194
222
|
#
|
@@ -196,12 +224,26 @@ class String
|
|
196
224
|
# optional parameter +capitalize+ to false.
|
197
225
|
# By default, this parameter is true.
|
198
226
|
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
|
204
|
-
|
227
|
+
# The trailing '_id' can be kept and capitalized by setting the
|
228
|
+
# optional parameter +keep_id_suffix+ to true.
|
229
|
+
# By default, this parameter is false.
|
230
|
+
#
|
231
|
+
# 'employee_salary'.humanize # => "Employee salary"
|
232
|
+
# 'author_id'.humanize # => "Author"
|
233
|
+
# 'author_id'.humanize(capitalize: false) # => "author"
|
234
|
+
# '_id'.humanize # => "Id"
|
235
|
+
# 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
|
236
|
+
def humanize(capitalize: true, keep_id_suffix: false)
|
237
|
+
ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Converts just the first character to uppercase.
|
241
|
+
#
|
242
|
+
# 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
|
243
|
+
# 'w'.upcase_first # => "W"
|
244
|
+
# ''.upcase_first # => ""
|
245
|
+
def upcase_first
|
246
|
+
ActiveSupport::Inflector.upcase_first(self)
|
205
247
|
end
|
206
248
|
|
207
249
|
# Creates a foreign key name from a class name.
|
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/multibyte"
|
3
4
|
|
4
5
|
class String
|
5
6
|
# == Multibyte proxy
|
@@ -10,12 +11,13 @@ class String
|
|
10
11
|
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
11
12
|
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
12
13
|
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# >> "lj".mb_chars.upcase.to_s
|
15
|
+
# => "LJ"
|
16
|
+
#
|
17
|
+
# NOTE: Ruby 2.4 and later support native Unicode case mappings:
|
16
18
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
+
# >> "lj".upcase
|
20
|
+
# => "LJ"
|
19
21
|
#
|
20
22
|
# == Method chaining
|
21
23
|
#
|
@@ -36,6 +38,13 @@ class String
|
|
36
38
|
ActiveSupport::Multibyte.proxy_class.new(self)
|
37
39
|
end
|
38
40
|
|
41
|
+
# Returns +true+ if string has utf_8 encoding.
|
42
|
+
#
|
43
|
+
# utf_8_str = "some string".encode "UTF-8"
|
44
|
+
# iso_str = "some string".encode "ISO-8859-1"
|
45
|
+
#
|
46
|
+
# utf_8_str.is_utf8? # => true
|
47
|
+
# iso_str.is_utf8? # => false
|
39
48
|
def is_utf8?
|
40
49
|
case encoding
|
41
50
|
when Encoding::UTF_8
|