omg-activesupport 8.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +86 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +40 -0
- data/lib/active_support/actionable_error.rb +50 -0
- data/lib/active_support/all.rb +5 -0
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +163 -0
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +53 -0
- data/lib/active_support/broadcast_logger.rb +251 -0
- data/lib/active_support/builder.rb +8 -0
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +244 -0
- data/lib/active_support/cache/mem_cache_store.rb +290 -0
- data/lib/active_support/cache/memory_store.rb +262 -0
- data/lib/active_support/cache/null_store.rb +62 -0
- data/lib/active_support/cache/redis_cache_store.rb +492 -0
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +201 -0
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +1104 -0
- data/lib/active_support/callbacks.rb +944 -0
- data/lib/active_support/class_attribute.rb +26 -0
- data/lib/active_support/code_generator.rb +79 -0
- data/lib/active_support/concern.rb +217 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +72 -0
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +225 -0
- data/lib/active_support/configurable.rb +159 -0
- data/lib/active_support/configuration_file.rb +60 -0
- data/lib/active_support/core_ext/array/access.rb +100 -0
- data/lib/active_support/core_ext/array/conversions.rb +213 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/core_ext/array/grouping.rb +109 -0
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/core_ext/array.rb +9 -0
- data/lib/active_support/core_ext/benchmark.rb +13 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/active_support/core_ext/big_decimal.rb +3 -0
- data/lib/active_support/core_ext/class/attribute.rb +122 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/class/subclasses.rb +24 -0
- data/lib/active_support/core_ext/class.rb +4 -0
- data/lib/active_support/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/core_ext/date/blank.rb +18 -0
- data/lib/active_support/core_ext/date/calculations.rb +161 -0
- data/lib/active_support/core_ext/date/conversions.rb +98 -0
- data/lib/active_support/core_ext/date/zones.rb +8 -0
- data/lib/active_support/core_ext/date.rb +7 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +58 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
- data/lib/active_support/core_ext/date_time/blank.rb +18 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +106 -0
- data/lib/active_support/core_ext/date_time.rb +7 -0
- data/lib/active_support/core_ext/digest/uuid.rb +76 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +267 -0
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/file/atomic.rb +72 -0
- data/lib/active_support/core_ext/file.rb +3 -0
- data/lib/active_support/core_ext/hash/conversions.rb +262 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +42 -0
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +24 -0
- data/lib/active_support/core_ext/hash/keys.rb +143 -0
- data/lib/active_support/core_ext/hash/reverse_merge.rb +25 -0
- data/lib/active_support/core_ext/hash/slice.rb +27 -0
- data/lib/active_support/core_ext/hash.rb +10 -0
- data/lib/active_support/core_ext/integer/inflections.rb +31 -0
- data/lib/active_support/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/core_ext/integer/time.rb +22 -0
- data/lib/active_support/core_ext/integer.rb +5 -0
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/core_ext/kernel.rb +5 -0
- data/lib/active_support/core_ext/load_error.rb +9 -0
- data/lib/active_support/core_ext/module/aliasing.rb +31 -0
- data/lib/active_support/core_ext/module/anonymous.rb +30 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +49 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +225 -0
- data/lib/active_support/core_ext/module/deprecation.rb +25 -0
- data/lib/active_support/core_ext/module/introspection.rb +62 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +17 -0
- data/lib/active_support/core_ext/module.rb +13 -0
- data/lib/active_support/core_ext/name_error.rb +59 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +75 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/time.rb +66 -0
- data/lib/active_support/core_ext/numeric.rb +5 -0
- data/lib/active_support/core_ext/object/acts_like.rb +45 -0
- data/lib/active_support/core_ext/object/blank.rb +199 -0
- data/lib/active_support/core_ext/object/conversions.rb +6 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
- data/lib/active_support/core_ext/object/duplicable.rb +69 -0
- data/lib/active_support/core_ext/object/inclusion.rb +37 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
- data/lib/active_support/core_ext/object/json.rb +260 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -0
- data/lib/active_support/core_ext/object/to_query.rb +87 -0
- data/lib/active_support/core_ext/object/try.rb +158 -0
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +101 -0
- data/lib/active_support/core_ext/object.rb +17 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +62 -0
- data/lib/active_support/core_ext/range/each.rb +24 -0
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +6 -0
- data/lib/active_support/core_ext/regexp.rb +14 -0
- data/lib/active_support/core_ext/securerandom.rb +41 -0
- data/lib/active_support/core_ext/string/access.rb +95 -0
- data/lib/active_support/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/core_ext/string/conversions.rb +60 -0
- data/lib/active_support/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/core_ext/string/filters.rb +151 -0
- data/lib/active_support/core_ext/string/indent.rb +45 -0
- data/lib/active_support/core_ext/string/inflections.rb +300 -0
- data/lib/active_support/core_ext/string/inquiry.rb +16 -0
- data/lib/active_support/core_ext/string/multibyte.rb +58 -0
- data/lib/active_support/core_ext/string/output_safety.rb +228 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/string/strip.rb +27 -0
- data/lib/active_support/core_ext/string/zones.rb +16 -0
- data/lib/active_support/core_ext/string.rb +15 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/core_ext/time/calculations.rb +386 -0
- data/lib/active_support/core_ext/time/compatibility.rb +32 -0
- data/lib/active_support/core_ext/time/conversions.rb +75 -0
- data/lib/active_support/core_ext/time/zones.rb +97 -0
- data/lib/active_support/core_ext/time.rb +7 -0
- data/lib/active_support/core_ext.rb +5 -0
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +233 -0
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +72 -0
- data/lib/active_support/dependencies/interlock.rb +49 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +98 -0
- data/lib/active_support/deprecation/behaviors.rb +148 -0
- data/lib/active_support/deprecation/constant_accessor.rb +74 -0
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/method_wrappers.rb +68 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
- data/lib/active_support/deprecation/reporting.rb +179 -0
- data/lib/active_support/deprecation.rb +81 -0
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +112 -0
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +64 -0
- data/lib/active_support/duration.rb +520 -0
- data/lib/active_support/encrypted_configuration.rb +126 -0
- data/lib/active_support/encrypted_file.rb +133 -0
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +265 -0
- data/lib/active_support/evented_file_update_checker.rb +182 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +150 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +164 -0
- data/lib/active_support/fork_tracker.rb +43 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +40 -0
- data/lib/active_support/hash_with_indifferent_access.rb +445 -0
- data/lib/active_support/html_safe_translation.rb +56 -0
- data/lib/active_support/i18n.rb +17 -0
- data/lib/active_support/i18n_railtie.rb +138 -0
- data/lib/active_support/inflections.rb +72 -0
- data/lib/active_support/inflector/inflections.rb +273 -0
- data/lib/active_support/inflector/methods.rb +387 -0
- data/lib/active_support/inflector/transliterate.rb +149 -0
- data/lib/active_support/inflector.rb +9 -0
- data/lib/active_support/isolated_execution_state.rb +75 -0
- data/lib/active_support/json/decoding.rb +76 -0
- data/lib/active_support/json/encoding.rb +120 -0
- data/lib/active_support/json.rb +4 -0
- data/lib/active_support/key_generator.rb +66 -0
- data/lib/active_support/lazy_load_hooks.rb +107 -0
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +141 -0
- data/lib/active_support/log_subscriber/test_helper.rb +106 -0
- data/lib/active_support/log_subscriber.rb +192 -0
- data/lib/active_support/logger.rb +55 -0
- data/lib/active_support/logger_silence.rb +21 -0
- data/lib/active_support/logger_thread_safe_level.rb +47 -0
- data/lib/active_support/message_encryptor.rb +374 -0
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +305 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +368 -0
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +146 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +59 -0
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +178 -0
- data/lib/active_support/multibyte/unicode.rb +42 -0
- data/lib/active_support/multibyte.rb +23 -0
- data/lib/active_support/notifications/fanout.rb +446 -0
- data/lib/active_support/notifications/instrumenter.rb +240 -0
- data/lib/active_support/notifications.rb +281 -0
- data/lib/active_support/number_helper/number_converter.rb +190 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +479 -0
- data/lib/active_support/option_merger.rb +38 -0
- data/lib/active_support/ordered_hash.rb +50 -0
- data/lib/active_support/ordered_options.rb +147 -0
- data/lib/active_support/parameter_filter.rb +157 -0
- data/lib/active_support/proxy_object.rb +20 -0
- data/lib/active_support/rails.rb +26 -0
- data/lib/active_support/railtie.rb +161 -0
- data/lib/active_support/reloader.rb +138 -0
- data/lib/active_support/rescuable.rb +176 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +35 -0
- data/lib/active_support/subscriber.rb +146 -0
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +152 -0
- data/lib/active_support/test_case.rb +304 -0
- data/lib/active_support/testing/assertions.rb +332 -0
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/constant_lookup.rb +51 -0
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/declarative.rb +28 -0
- data/lib/active_support/testing/deprecation.rb +82 -0
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +121 -0
- data/lib/active_support/testing/method_call_assertions.rb +69 -0
- data/lib/active_support/testing/parallelization/server.rb +85 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +57 -0
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/strict_warnings.rb +43 -0
- data/lib/active_support/testing/tagged_logging.rb +27 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +269 -0
- data/lib/active_support/time.rb +20 -0
- data/lib/active_support/time_with_zone.rb +609 -0
- data/lib/active_support/values/time_zone.rb +614 -0
- data/lib/active_support/version.rb +10 -0
- data/lib/active_support/xml_mini/jdom.rb +175 -0
- data/lib/active_support/xml_mini/libxml.rb +80 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
- data/lib/active_support/xml_mini/nokogiri.rb +83 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
- data/lib/active_support/xml_mini/rexml.rb +137 -0
- data/lib/active_support/xml_mini.rb +211 -0
- data/lib/active_support.rb +144 -0
- metadata +526 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
class Pathname
|
6
|
+
# Returns the receiver if the named file exists otherwise returns +nil+.
|
7
|
+
# <tt>pathname.existence</tt> is equivalent to
|
8
|
+
#
|
9
|
+
# pathname.exist? ? pathname : nil
|
10
|
+
#
|
11
|
+
# For example, something like
|
12
|
+
#
|
13
|
+
# content = pathname.read if pathname.exist?
|
14
|
+
#
|
15
|
+
# becomes
|
16
|
+
#
|
17
|
+
# content = pathname.existence&.read
|
18
|
+
#
|
19
|
+
# @return [Pathname]
|
20
|
+
def existence
|
21
|
+
self if exist?
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
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
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Range.prepend(ActiveSupport::CompareWithRange)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# = \Range With Format
|
5
|
+
module RangeWithFormat
|
6
|
+
RANGE_FORMATS = {
|
7
|
+
db: -> (start, stop) do
|
8
|
+
if start && stop
|
9
|
+
case start
|
10
|
+
when String then "BETWEEN '#{start}' AND '#{stop}'"
|
11
|
+
else
|
12
|
+
"BETWEEN '#{start.to_fs(:db)}' AND '#{stop.to_fs(:db)}'"
|
13
|
+
end
|
14
|
+
elsif start
|
15
|
+
case start
|
16
|
+
when String then ">= '#{start}'"
|
17
|
+
else
|
18
|
+
">= '#{start.to_fs(:db)}'"
|
19
|
+
end
|
20
|
+
elsif stop
|
21
|
+
case stop
|
22
|
+
when String then "<= '#{stop}'"
|
23
|
+
else
|
24
|
+
"<= '#{stop.to_fs(:db)}'"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
}
|
29
|
+
|
30
|
+
# Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
|
31
|
+
#
|
32
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
33
|
+
#
|
34
|
+
# range = (1..100) # => 1..100
|
35
|
+
#
|
36
|
+
# range.to_s # => "1..100"
|
37
|
+
# range.to_fs(:db) # => "BETWEEN '1' AND '100'"
|
38
|
+
#
|
39
|
+
# range = (1..) # => 1..
|
40
|
+
# range.to_fs(:db) # => ">= '1'"
|
41
|
+
#
|
42
|
+
# range = (..100) # => ..100
|
43
|
+
# range.to_fs(:db) # => "<= '100'"
|
44
|
+
#
|
45
|
+
# == Adding your own range formats to to_fs
|
46
|
+
# You can add your own formats to the Range::RANGE_FORMATS hash.
|
47
|
+
# Use the format name as the hash key and a Proc instance.
|
48
|
+
#
|
49
|
+
# # config/initializers/range_formats.rb
|
50
|
+
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_fs(:db)} and #{stop.to_fs(:db)}" }
|
51
|
+
def to_fs(format = :default)
|
52
|
+
if formatter = RANGE_FORMATS[format]
|
53
|
+
formatter.call(self.begin, self.end)
|
54
|
+
else
|
55
|
+
to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
alias_method :to_formatted_s, :to_fs
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
Range.prepend(ActiveSupport::RangeWithFormat)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module EachTimeWithZone # :nodoc:
|
7
|
+
def each(&block)
|
8
|
+
ensure_iteration_allowed
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def step(n = 1, &block)
|
13
|
+
ensure_iteration_allowed
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def ensure_iteration_allowed
|
19
|
+
raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Range.prepend(ActiveSupport::EachTimeWithZone)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Range
|
4
|
+
# Compare two ranges and see if they overlap each other
|
5
|
+
# (1..5).overlap?(4..6) # => true
|
6
|
+
# (1..5).overlap?(7..9) # => false
|
7
|
+
unless Range.method_defined?(:overlap?) # Ruby 3.3+
|
8
|
+
def overlap?(other)
|
9
|
+
raise TypeError unless other.is_a? Range
|
10
|
+
|
11
|
+
self_begin = self.begin
|
12
|
+
other_end = other.end
|
13
|
+
other_excl = other.exclude_end?
|
14
|
+
|
15
|
+
return false if _empty_range?(self_begin, other_end, other_excl)
|
16
|
+
|
17
|
+
other_begin = other.begin
|
18
|
+
self_end = self.end
|
19
|
+
self_excl = self.exclude_end?
|
20
|
+
|
21
|
+
return false if _empty_range?(other_begin, self_end, self_excl)
|
22
|
+
return true if self_begin == other_begin
|
23
|
+
|
24
|
+
return false if _empty_range?(self_begin, self_end, self_excl)
|
25
|
+
return false if _empty_range?(other_begin, other_end, other_excl)
|
26
|
+
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def _empty_range?(b, e, excl)
|
32
|
+
return false if b.nil? || e.nil?
|
33
|
+
|
34
|
+
comp = b <=> e
|
35
|
+
comp.nil? || comp > 0 || (comp == 0 && excl)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
alias :overlaps? :overlap?
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
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
|
11
|
+
def multiline?
|
12
|
+
options & MULTILINE == MULTILINE
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,41 @@
|
|
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.alphanumeric(n, chars: BASE58_ALPHABET)
|
21
|
+
end
|
22
|
+
|
23
|
+
# SecureRandom.base36 generates a random base36 string in lowercase.
|
24
|
+
#
|
25
|
+
# The argument _n_ specifies the length of the random string to be generated.
|
26
|
+
#
|
27
|
+
# If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
|
28
|
+
# This method can be used over +base58+ if a deterministic case key is necessary.
|
29
|
+
#
|
30
|
+
# The result will contain alphanumeric characters in lowercase.
|
31
|
+
#
|
32
|
+
# p SecureRandom.base36 # => "4kugl2pdqmscqtje"
|
33
|
+
# p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
|
34
|
+
def self.base36(n = 16)
|
35
|
+
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
36
|
+
idx = byte % 64
|
37
|
+
idx = SecureRandom.random_number(36) if idx >= 36
|
38
|
+
BASE36_ALPHABET[idx]
|
39
|
+
end.join
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
# If you pass a single integer, returns a substring of one character at that
|
5
|
+
# position. The first character of the string is at position 0, the next at
|
6
|
+
# position 1, and so on. If a range is supplied, a substring containing
|
7
|
+
# characters at offsets given by the range is returned. In both cases, if an
|
8
|
+
# offset is negative, it is counted from the end of the string. Returns +nil+
|
9
|
+
# if the initial offset falls outside the string. Returns an empty string if
|
10
|
+
# the beginning of the range is greater than the end of the string.
|
11
|
+
#
|
12
|
+
# str = "hello"
|
13
|
+
# str.at(0) # => "h"
|
14
|
+
# str.at(1..3) # => "ell"
|
15
|
+
# str.at(-2) # => "l"
|
16
|
+
# str.at(-2..-1) # => "lo"
|
17
|
+
# str.at(5) # => nil
|
18
|
+
# str.at(5..-1) # => ""
|
19
|
+
#
|
20
|
+
# If a Regexp is given, the matching portion of the string is returned.
|
21
|
+
# If a String is given, that given string is returned if it occurs in
|
22
|
+
# the string. In both cases, +nil+ is returned if there is no match.
|
23
|
+
#
|
24
|
+
# str = "hello"
|
25
|
+
# str.at(/lo/) # => "lo"
|
26
|
+
# str.at(/ol/) # => nil
|
27
|
+
# str.at("lo") # => "lo"
|
28
|
+
# str.at("ol") # => nil
|
29
|
+
def at(position)
|
30
|
+
self[position]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a substring from the given position to the end of the string.
|
34
|
+
# If the position is negative, it is counted from the end of the string.
|
35
|
+
#
|
36
|
+
# str = "hello"
|
37
|
+
# str.from(0) # => "hello"
|
38
|
+
# str.from(3) # => "lo"
|
39
|
+
# str.from(-2) # => "lo"
|
40
|
+
#
|
41
|
+
# You can mix it with +to+ method and do fun things like:
|
42
|
+
#
|
43
|
+
# str = "hello"
|
44
|
+
# str.from(0).to(-1) # => "hello"
|
45
|
+
# str.from(1).to(-2) # => "ell"
|
46
|
+
def from(position)
|
47
|
+
self[position, length]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a substring from the beginning of the string to the given position.
|
51
|
+
# If the position is negative, it is counted from the end of the string.
|
52
|
+
#
|
53
|
+
# str = "hello"
|
54
|
+
# str.to(0) # => "h"
|
55
|
+
# str.to(3) # => "hell"
|
56
|
+
# str.to(-2) # => "hell"
|
57
|
+
#
|
58
|
+
# You can mix it with +from+ method and do fun things like:
|
59
|
+
#
|
60
|
+
# str = "hello"
|
61
|
+
# str.from(0).to(-1) # => "hello"
|
62
|
+
# str.from(1).to(-2) # => "ell"
|
63
|
+
def to(position)
|
64
|
+
position += size if position < 0
|
65
|
+
self[0, position + 1] || +""
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the first character. If a limit is supplied, returns a substring
|
69
|
+
# from the beginning of the string until it reaches the limit value. If the
|
70
|
+
# given limit is greater than or equal to the string length, returns a copy of self.
|
71
|
+
#
|
72
|
+
# str = "hello"
|
73
|
+
# str.first # => "h"
|
74
|
+
# str.first(1) # => "h"
|
75
|
+
# str.first(2) # => "he"
|
76
|
+
# str.first(0) # => ""
|
77
|
+
# str.first(6) # => "hello"
|
78
|
+
def first(limit = 1)
|
79
|
+
self[0, limit] || raise(ArgumentError, "negative limit")
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns the last character of the string. If a limit is supplied, returns a substring
|
83
|
+
# from the end of the string until it reaches the limit value (counting backwards). If
|
84
|
+
# the given limit is greater than or equal to the string length, returns a copy of self.
|
85
|
+
#
|
86
|
+
# str = "hello"
|
87
|
+
# str.last # => "o"
|
88
|
+
# str.last(1) # => "o"
|
89
|
+
# str.last(2) # => "lo"
|
90
|
+
# str.last(0) # => ""
|
91
|
+
# str.last(6) # => "hello"
|
92
|
+
def last(limit = 1)
|
93
|
+
self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "active_support/core_ext/time/calculations"
|
5
|
+
|
6
|
+
class String
|
7
|
+
# Converts a string to a Time value.
|
8
|
+
# The +form+ can be either +:utc+ or +:local+ (default +:local+).
|
9
|
+
#
|
10
|
+
# The time is parsed using Time.parse method.
|
11
|
+
# If +form+ is +:local+, then the time is in the system timezone.
|
12
|
+
# If the date part is missing then the current date is used and if
|
13
|
+
# the time part is missing then it is assumed to be 00:00:00.
|
14
|
+
#
|
15
|
+
# "13-12-2012".to_time # => 2012-12-13 00:00:00 +0100
|
16
|
+
# "06:12".to_time # => 2012-12-13 06:12:00 +0100
|
17
|
+
# "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
|
18
|
+
# "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
|
19
|
+
# "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
|
20
|
+
# "12/13/2012".to_time # => ArgumentError: argument out of range
|
21
|
+
# "1604326192".to_time # => ArgumentError: argument out of range
|
22
|
+
def to_time(form = :local)
|
23
|
+
parts = Date._parse(self, false)
|
24
|
+
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
25
|
+
return if !parts.keys.intersect?(used_keys)
|
26
|
+
|
27
|
+
now = Time.now
|
28
|
+
time = Time.new(
|
29
|
+
parts.fetch(:year, now.year),
|
30
|
+
parts.fetch(:mon, now.month),
|
31
|
+
parts.fetch(:mday, now.day),
|
32
|
+
parts.fetch(:hour, 0),
|
33
|
+
parts.fetch(:min, 0),
|
34
|
+
parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
|
35
|
+
parts.fetch(:offset, form == :utc ? 0 : nil)
|
36
|
+
)
|
37
|
+
|
38
|
+
form == :utc ? time.utc : time.to_time
|
39
|
+
end
|
40
|
+
|
41
|
+
# Converts a string to a Date value.
|
42
|
+
#
|
43
|
+
# "1-1-2012".to_date # => Sun, 01 Jan 2012
|
44
|
+
# "01/01/2012".to_date # => Sun, 01 Jan 2012
|
45
|
+
# "2012-12-13".to_date # => Thu, 13 Dec 2012
|
46
|
+
# "12/13/2012".to_date # => ArgumentError: invalid date
|
47
|
+
def to_date
|
48
|
+
::Date.parse(self, false) unless blank?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts a string to a DateTime value.
|
52
|
+
#
|
53
|
+
# "1-1-2012".to_datetime # => Sun, 01 Jan 2012 00:00:00 +0000
|
54
|
+
# "01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
|
55
|
+
# "2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000
|
56
|
+
# "12/13/2012".to_datetime # => ArgumentError: invalid date
|
57
|
+
def to_datetime
|
58
|
+
::DateTime.parse(self, false) unless blank?
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
# The inverse of <tt>String#include?</tt>. Returns true if the string
|
5
|
+
# does not include the other string.
|
6
|
+
#
|
7
|
+
# "hello".exclude? "lo" # => false
|
8
|
+
# "hello".exclude? "ol" # => true
|
9
|
+
# "hello".exclude? ?h # => false
|
10
|
+
def exclude?(string)
|
11
|
+
!include?(string)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
# Returns the string, first removing all whitespace on both ends of
|
5
|
+
# the string, and then changing remaining consecutive whitespace
|
6
|
+
# groups into one space each.
|
7
|
+
#
|
8
|
+
# Note that it handles both ASCII and Unicode whitespace.
|
9
|
+
#
|
10
|
+
# %{ Multi-line
|
11
|
+
# string }.squish # => "Multi-line string"
|
12
|
+
# " foo bar \n \t boo".squish # => "foo bar boo"
|
13
|
+
def squish
|
14
|
+
dup.squish!
|
15
|
+
end
|
16
|
+
|
17
|
+
# Performs a destructive squish. See String#squish.
|
18
|
+
# str = " foo bar \n \t boo"
|
19
|
+
# str.squish! # => "foo bar boo"
|
20
|
+
# str # => "foo bar boo"
|
21
|
+
def squish!
|
22
|
+
gsub!(/[[:space:]]+/, " ")
|
23
|
+
strip!
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a new string with all occurrences of the patterns removed.
|
28
|
+
# str = "foo bar test"
|
29
|
+
# str.remove(" test") # => "foo bar"
|
30
|
+
# str.remove(" test", /bar/) # => "foo "
|
31
|
+
# str # => "foo bar test"
|
32
|
+
def remove(*patterns)
|
33
|
+
dup.remove!(*patterns)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Alters the string by removing all occurrences of the patterns.
|
37
|
+
# str = "foo bar test"
|
38
|
+
# str.remove!(" test", /bar/) # => "foo "
|
39
|
+
# str # => "foo "
|
40
|
+
def remove!(*patterns)
|
41
|
+
patterns.each do |pattern|
|
42
|
+
gsub! pattern, ""
|
43
|
+
end
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# Truncates a given +text+ to length <tt>truncate_to</tt> if +text+ is longer than <tt>truncate_to</tt>:
|
49
|
+
#
|
50
|
+
# 'Once upon a time in a world far far away'.truncate(27)
|
51
|
+
# # => "Once upon a time in a wo..."
|
52
|
+
#
|
53
|
+
# Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
|
54
|
+
#
|
55
|
+
# 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
|
56
|
+
# # => "Once upon a time in a..."
|
57
|
+
#
|
58
|
+
# 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
|
59
|
+
# # => "Once upon a time in a..."
|
60
|
+
#
|
61
|
+
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...").
|
62
|
+
# The total length will not exceed <tt>truncate_to</tt> unless both +text+ and <tt>:omission</tt>
|
63
|
+
# are longer than <tt>truncate_to</tt>:
|
64
|
+
#
|
65
|
+
# 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
|
66
|
+
# # => "And they f... (continued)"
|
67
|
+
#
|
68
|
+
# 'And they found that many people were sleeping better.'.truncate(4, omission: '... (continued)')
|
69
|
+
# # => "... (continued)"
|
70
|
+
def truncate(truncate_to, options = {})
|
71
|
+
return dup unless length > truncate_to
|
72
|
+
|
73
|
+
omission = options[:omission] || "..."
|
74
|
+
length_with_room_for_omission = truncate_to - omission.length
|
75
|
+
stop = \
|
76
|
+
if options[:separator]
|
77
|
+
rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
|
78
|
+
else
|
79
|
+
length_with_room_for_omission
|
80
|
+
end
|
81
|
+
|
82
|
+
+"#{self[0, stop]}#{omission}"
|
83
|
+
end
|
84
|
+
|
85
|
+
# Truncates +text+ to at most <tt>truncate_to</tt> bytes in length without
|
86
|
+
# breaking string encoding by splitting multibyte characters or breaking
|
87
|
+
# grapheme clusters ("perceptual characters") by truncating at combining
|
88
|
+
# characters.
|
89
|
+
#
|
90
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
|
91
|
+
# => 20
|
92
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
|
93
|
+
# => 80
|
94
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
|
95
|
+
# => "🔪🔪🔪🔪…"
|
96
|
+
#
|
97
|
+
# The truncated text ends with the <tt>:omission</tt> string, defaulting
|
98
|
+
# to "…", for a total length not exceeding <tt>truncate_to</tt>.
|
99
|
+
#
|
100
|
+
# Raises +ArgumentError+ when the bytesize of <tt>:omission</tt> exceeds <tt>truncate_to</tt>.
|
101
|
+
def truncate_bytes(truncate_to, omission: "…")
|
102
|
+
omission ||= ""
|
103
|
+
|
104
|
+
case
|
105
|
+
when bytesize <= truncate_to
|
106
|
+
dup
|
107
|
+
when omission.bytesize > truncate_to
|
108
|
+
raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_to} bytes"
|
109
|
+
when omission.bytesize == truncate_to
|
110
|
+
omission.dup
|
111
|
+
else
|
112
|
+
self.class.new.force_encoding(encoding).tap do |cut|
|
113
|
+
cut_at = truncate_to - omission.bytesize
|
114
|
+
|
115
|
+
each_grapheme_cluster do |grapheme|
|
116
|
+
if cut.bytesize + grapheme.bytesize <= cut_at
|
117
|
+
cut << grapheme
|
118
|
+
else
|
119
|
+
break
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
cut << omission
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
|
129
|
+
#
|
130
|
+
# 'Once upon a time in a world far far away'.truncate_words(4)
|
131
|
+
# # => "Once upon a time..."
|
132
|
+
#
|
133
|
+
# Pass a string or regexp <tt>:separator</tt> to specify a different separator of words:
|
134
|
+
#
|
135
|
+
# 'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate_words(5, separator: '<br>')
|
136
|
+
# # => "Once<br>upon<br>a<br>time<br>in..."
|
137
|
+
#
|
138
|
+
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "..."):
|
139
|
+
#
|
140
|
+
# 'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)')
|
141
|
+
# # => "And they found that many... (continued)"
|
142
|
+
def truncate_words(words_count, options = {})
|
143
|
+
sep = options[:separator] || /\s+/
|
144
|
+
sep = Regexp.escape(sep.to_s) unless Regexp === sep
|
145
|
+
if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
|
146
|
+
$1 + (options[:omission] || "...")
|
147
|
+
else
|
148
|
+
dup
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
# Same as +indent+, except it indents the receiver in-place.
|
5
|
+
#
|
6
|
+
# Returns the indented string, or +nil+ if there was nothing to indent.
|
7
|
+
def indent!(amount, indent_string = nil, indent_empty_lines = false)
|
8
|
+
indent_string = indent_string || self[/^[ \t]/] || " "
|
9
|
+
re = indent_empty_lines ? /^/ : /^(?!$)/
|
10
|
+
gsub!(re, indent_string * amount)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Indents the lines in the receiver:
|
14
|
+
#
|
15
|
+
# <<EOS.indent(2)
|
16
|
+
# def some_method
|
17
|
+
# some_code
|
18
|
+
# end
|
19
|
+
# EOS
|
20
|
+
# # =>
|
21
|
+
# def some_method
|
22
|
+
# some_code
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# The second argument, +indent_string+, specifies which indent string to
|
26
|
+
# use. The default is +nil+, which tells the method to make a guess by
|
27
|
+
# peeking at the first indented line, and fall back to a space if there is
|
28
|
+
# none.
|
29
|
+
#
|
30
|
+
# " foo".indent(2) # => " foo"
|
31
|
+
# "foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
|
32
|
+
# "foo".indent(2, "\t") # => "\t\tfoo"
|
33
|
+
#
|
34
|
+
# While +indent_string+ is typically one space or tab, it may be any string.
|
35
|
+
#
|
36
|
+
# The third argument, +indent_empty_lines+, is a flag that says whether
|
37
|
+
# empty lines should be indented. Default is false.
|
38
|
+
#
|
39
|
+
# "foo\n\nbar".indent(2) # => " foo\n\n bar"
|
40
|
+
# "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
|
41
|
+
#
|
42
|
+
def indent(amount, indent_string = nil, indent_empty_lines = false)
|
43
|
+
dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
|
44
|
+
end
|
45
|
+
end
|