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
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "active_support/inflections"
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
# The Inflector transforms words from singular to plural, class names to table
|
@@ -22,58 +22,58 @@ module ActiveSupport
|
|
22
22
|
# pluralized using rules defined for that language. By default,
|
23
23
|
# this parameter is set to <tt>:en</tt>.
|
24
24
|
#
|
25
|
-
# 'post'
|
26
|
-
# 'octopus'
|
27
|
-
# 'sheep'
|
28
|
-
# 'words'
|
29
|
-
# 'CamelOctopus'
|
30
|
-
# 'ley'
|
25
|
+
# pluralize('post') # => "posts"
|
26
|
+
# pluralize('octopus') # => "octopi"
|
27
|
+
# pluralize('sheep') # => "sheep"
|
28
|
+
# pluralize('words') # => "words"
|
29
|
+
# pluralize('CamelOctopus') # => "CamelOctopi"
|
30
|
+
# pluralize('ley', :es) # => "leyes"
|
31
31
|
def pluralize(word, locale = :en)
|
32
|
-
apply_inflections(word, inflections(locale).plurals)
|
32
|
+
apply_inflections(word, inflections(locale).plurals, locale)
|
33
33
|
end
|
34
34
|
|
35
|
-
# The reverse of
|
35
|
+
# The reverse of #pluralize, returns the singular form of a word in a
|
36
36
|
# string.
|
37
37
|
#
|
38
38
|
# If passed an optional +locale+ parameter, the word will be
|
39
39
|
# singularized using rules defined for that language. By default,
|
40
40
|
# this parameter is set to <tt>:en</tt>.
|
41
41
|
#
|
42
|
-
# 'posts'
|
43
|
-
# 'octopi'
|
44
|
-
# 'sheep'
|
45
|
-
# 'word'
|
46
|
-
# 'CamelOctopi'
|
47
|
-
# 'leyes'
|
42
|
+
# singularize('posts') # => "post"
|
43
|
+
# singularize('octopi') # => "octopus"
|
44
|
+
# singularize('sheep') # => "sheep"
|
45
|
+
# singularize('word') # => "word"
|
46
|
+
# singularize('CamelOctopi') # => "CamelOctopus"
|
47
|
+
# singularize('leyes', :es) # => "ley"
|
48
48
|
def singularize(word, locale = :en)
|
49
|
-
apply_inflections(word, inflections(locale).singulars)
|
49
|
+
apply_inflections(word, inflections(locale).singulars, locale)
|
50
50
|
end
|
51
51
|
|
52
|
-
#
|
53
|
-
#
|
52
|
+
# Converts strings to UpperCamelCase.
|
53
|
+
# If the +uppercase_first_letter+ parameter is set to false, then produces
|
54
54
|
# lowerCamelCase.
|
55
55
|
#
|
56
|
-
#
|
56
|
+
# Also converts '/' to '::' which is useful for converting
|
57
57
|
# paths to namespaces.
|
58
58
|
#
|
59
|
-
# 'active_model'
|
60
|
-
# 'active_model'
|
61
|
-
# 'active_model/errors'
|
62
|
-
# 'active_model/errors'
|
59
|
+
# camelize('active_model') # => "ActiveModel"
|
60
|
+
# camelize('active_model', false) # => "activeModel"
|
61
|
+
# camelize('active_model/errors') # => "ActiveModel::Errors"
|
62
|
+
# camelize('active_model/errors', false) # => "activeModel::Errors"
|
63
63
|
#
|
64
64
|
# As a rule of thumb you can think of +camelize+ as the inverse of
|
65
|
-
#
|
65
|
+
# #underscore, though there are cases where that does not hold:
|
66
66
|
#
|
67
|
-
# 'SSLError'
|
67
|
+
# camelize(underscore('SSLError')) # => "SslError"
|
68
68
|
def camelize(term, uppercase_first_letter = true)
|
69
69
|
string = term.to_s
|
70
70
|
if uppercase_first_letter
|
71
|
-
string = string.sub(/^[a-z\d]*/) { inflections.acronyms[
|
71
|
+
string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
|
72
72
|
else
|
73
|
-
string = string.sub(
|
73
|
+
string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase }
|
74
74
|
end
|
75
75
|
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
76
|
-
string.gsub!(
|
76
|
+
string.gsub!("/", "::")
|
77
77
|
string
|
78
78
|
end
|
79
79
|
|
@@ -81,19 +81,19 @@ module ActiveSupport
|
|
81
81
|
#
|
82
82
|
# Changes '::' to '/' to convert namespaces to paths.
|
83
83
|
#
|
84
|
-
# 'ActiveModel'
|
85
|
-
# 'ActiveModel::Errors'
|
84
|
+
# underscore('ActiveModel') # => "active_model"
|
85
|
+
# underscore('ActiveModel::Errors') # => "active_model/errors"
|
86
86
|
#
|
87
87
|
# As a rule of thumb you can think of +underscore+ as the inverse of
|
88
|
-
#
|
88
|
+
# #camelize, though there are cases where that does not hold:
|
89
89
|
#
|
90
|
-
# 'SSLError'
|
90
|
+
# camelize(underscore('SSLError')) # => "SslError"
|
91
91
|
def underscore(camel_cased_word)
|
92
|
-
return camel_cased_word unless
|
93
|
-
word = camel_cased_word.to_s.gsub(
|
94
|
-
word.gsub!(
|
95
|
-
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
96
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
92
|
+
return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
|
93
|
+
word = camel_cased_word.to_s.gsub("::", "/")
|
94
|
+
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
95
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
96
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
97
97
|
word.tr!("-", "_")
|
98
98
|
word.downcase!
|
99
99
|
word
|
@@ -101,105 +101,126 @@ module ActiveSupport
|
|
101
101
|
|
102
102
|
# Tweaks an attribute name for display to end users.
|
103
103
|
#
|
104
|
-
# Specifically,
|
105
|
-
#
|
106
|
-
# * Applies human inflection rules to the argument.
|
107
|
-
# * Deletes leading underscores, if any.
|
108
|
-
# * Removes a "_id" suffix if present.
|
109
|
-
# * Replaces underscores with spaces, if any.
|
110
|
-
# * Downcases all words except acronyms.
|
111
|
-
# * Capitalizes the first word.
|
104
|
+
# Specifically, performs these transformations:
|
112
105
|
#
|
106
|
+
# * Applies human inflection rules to the argument.
|
107
|
+
# * Deletes leading underscores, if any.
|
108
|
+
# * Removes a "_id" suffix if present.
|
109
|
+
# * Replaces underscores with spaces, if any.
|
110
|
+
# * Downcases all words except acronyms.
|
111
|
+
# * Capitalizes the first word.
|
113
112
|
# The capitalization of the first word can be turned off by setting the
|
114
113
|
# +:capitalize+ option to false (default is true).
|
115
114
|
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
# humanize('
|
115
|
+
# The trailing '_id' can be kept and capitalized by setting the
|
116
|
+
# optional parameter +keep_id_suffix+ to true (default is false).
|
117
|
+
#
|
118
|
+
# humanize('employee_salary') # => "Employee salary"
|
119
|
+
# humanize('author_id') # => "Author"
|
120
|
+
# humanize('author_id', capitalize: false) # => "author"
|
121
|
+
# humanize('_id') # => "Id"
|
122
|
+
# humanize('author_id', keep_id_suffix: true) # => "Author Id"
|
120
123
|
#
|
121
124
|
# If "SSL" was defined to be an acronym:
|
122
125
|
#
|
123
126
|
# humanize('ssl_error') # => "SSL error"
|
124
127
|
#
|
125
|
-
def humanize(lower_case_and_underscored_word,
|
128
|
+
def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
|
126
129
|
result = lower_case_and_underscored_word.to_s.dup
|
127
130
|
|
128
131
|
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
129
132
|
|
130
|
-
result.sub!(/\A_+/,
|
131
|
-
|
132
|
-
|
133
|
+
result.sub!(/\A_+/, "")
|
134
|
+
unless keep_id_suffix
|
135
|
+
result.sub!(/_id\z/, "")
|
136
|
+
end
|
137
|
+
result.tr!("_", " ")
|
133
138
|
|
134
139
|
result.gsub!(/([a-z\d]*)/i) do |match|
|
135
|
-
"#{inflections.acronyms[match] || match.downcase}"
|
140
|
+
"#{inflections.acronyms[match.downcase] || match.downcase}"
|
136
141
|
end
|
137
142
|
|
138
|
-
if
|
143
|
+
if capitalize
|
139
144
|
result.sub!(/\A\w/) { |match| match.upcase }
|
140
145
|
end
|
141
146
|
|
142
147
|
result
|
143
148
|
end
|
144
149
|
|
150
|
+
# Converts just the first character to uppercase.
|
151
|
+
#
|
152
|
+
# upcase_first('what a Lovely Day') # => "What a Lovely Day"
|
153
|
+
# upcase_first('w') # => "W"
|
154
|
+
# upcase_first('') # => ""
|
155
|
+
def upcase_first(string)
|
156
|
+
string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
|
157
|
+
end
|
158
|
+
|
145
159
|
# Capitalizes all the words and replaces some characters in the string to
|
146
160
|
# create a nicer looking title. +titleize+ is meant for creating pretty
|
147
161
|
# output. It is not used in the Rails internals.
|
148
162
|
#
|
163
|
+
# The trailing '_id','Id'.. can be kept and capitalized by setting the
|
164
|
+
# optional parameter +keep_id_suffix+ to true.
|
165
|
+
# By default, this parameter is false.
|
166
|
+
#
|
149
167
|
# +titleize+ is also aliased as +titlecase+.
|
150
168
|
#
|
151
|
-
# 'man from the boondocks'
|
152
|
-
# 'x-men: the last stand'
|
153
|
-
# 'TheManWithoutAPast'
|
154
|
-
# 'raiders_of_the_lost_ark'
|
155
|
-
|
156
|
-
|
169
|
+
# titleize('man from the boondocks') # => "Man From The Boondocks"
|
170
|
+
# titleize('x-men: the last stand') # => "X Men: The Last Stand"
|
171
|
+
# titleize('TheManWithoutAPast') # => "The Man Without A Past"
|
172
|
+
# titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
|
173
|
+
# titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
|
174
|
+
def titleize(word, keep_id_suffix: false)
|
175
|
+
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`])[a-z]/) do |match|
|
176
|
+
match.capitalize
|
177
|
+
end
|
157
178
|
end
|
158
179
|
|
159
|
-
#
|
160
|
-
# method uses the
|
180
|
+
# Creates the name of a table like Rails does for models to table names.
|
181
|
+
# This method uses the #pluralize method on the last word in the string.
|
161
182
|
#
|
162
|
-
# 'RawScaledScorer'
|
163
|
-
# '
|
164
|
-
# 'fancyCategory'
|
183
|
+
# tableize('RawScaledScorer') # => "raw_scaled_scorers"
|
184
|
+
# tableize('ham_and_egg') # => "ham_and_eggs"
|
185
|
+
# tableize('fancyCategory') # => "fancy_categories"
|
165
186
|
def tableize(class_name)
|
166
187
|
pluralize(underscore(class_name))
|
167
188
|
end
|
168
189
|
|
169
|
-
#
|
190
|
+
# Creates a class name from a plural table name like Rails does for table
|
170
191
|
# names to models. Note that this returns a string and not a Class (To
|
171
|
-
# convert to an actual class follow +classify+ with
|
192
|
+
# convert to an actual class follow +classify+ with #constantize).
|
172
193
|
#
|
173
|
-
# '
|
174
|
-
# 'posts'
|
194
|
+
# classify('ham_and_eggs') # => "HamAndEgg"
|
195
|
+
# classify('posts') # => "Post"
|
175
196
|
#
|
176
197
|
# Singular names are not handled correctly:
|
177
198
|
#
|
178
|
-
# 'calculus'
|
199
|
+
# classify('calculus') # => "Calculu"
|
179
200
|
def classify(table_name)
|
180
201
|
# strip out any leading schema name
|
181
|
-
camelize(singularize(table_name.to_s.sub(/.*\./,
|
202
|
+
camelize(singularize(table_name.to_s.sub(/.*\./, "")))
|
182
203
|
end
|
183
204
|
|
184
205
|
# Replaces underscores with dashes in the string.
|
185
206
|
#
|
186
|
-
# 'puni_puni'
|
207
|
+
# dasherize('puni_puni') # => "puni-puni"
|
187
208
|
def dasherize(underscored_word)
|
188
|
-
underscored_word.tr(
|
209
|
+
underscored_word.tr("_", "-")
|
189
210
|
end
|
190
211
|
|
191
212
|
# Removes the module part from the expression in the string.
|
192
213
|
#
|
193
|
-
# '
|
194
|
-
# 'Inflections'
|
195
|
-
# '::Inflections'
|
196
|
-
# ''
|
214
|
+
# demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
|
215
|
+
# demodulize('Inflections') # => "Inflections"
|
216
|
+
# demodulize('::Inflections') # => "Inflections"
|
217
|
+
# demodulize('') # => ""
|
197
218
|
#
|
198
|
-
# See also
|
219
|
+
# See also #deconstantize.
|
199
220
|
def demodulize(path)
|
200
221
|
path = path.to_s
|
201
|
-
if i = path.rindex(
|
202
|
-
path[(i+2)..-1]
|
222
|
+
if i = path.rindex("::")
|
223
|
+
path[(i + 2)..-1]
|
203
224
|
else
|
204
225
|
path
|
205
226
|
end
|
@@ -207,32 +228,32 @@ module ActiveSupport
|
|
207
228
|
|
208
229
|
# Removes the rightmost segment from the constant expression in the string.
|
209
230
|
#
|
210
|
-
# 'Net::HTTP'
|
211
|
-
# '::Net::HTTP'
|
212
|
-
# 'String'
|
213
|
-
# '::String'
|
214
|
-
# ''
|
231
|
+
# deconstantize('Net::HTTP') # => "Net"
|
232
|
+
# deconstantize('::Net::HTTP') # => "::Net"
|
233
|
+
# deconstantize('String') # => ""
|
234
|
+
# deconstantize('::String') # => ""
|
235
|
+
# deconstantize('') # => ""
|
215
236
|
#
|
216
|
-
# See also
|
237
|
+
# See also #demodulize.
|
217
238
|
def deconstantize(path)
|
218
|
-
path.to_s[0, path.rindex(
|
239
|
+
path.to_s[0, path.rindex("::") || 0] # implementation based on the one in facets' Module#spacename
|
219
240
|
end
|
220
241
|
|
221
242
|
# Creates a foreign key name from a class name.
|
222
243
|
# +separate_class_name_and_id_with_underscore+ sets whether
|
223
244
|
# the method should put '_' between the name and 'id'.
|
224
245
|
#
|
225
|
-
# 'Message'
|
226
|
-
# 'Message'
|
227
|
-
# 'Admin::Post'
|
246
|
+
# foreign_key('Message') # => "message_id"
|
247
|
+
# foreign_key('Message', false) # => "messageid"
|
248
|
+
# foreign_key('Admin::Post') # => "post_id"
|
228
249
|
def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
|
229
250
|
underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
|
230
251
|
end
|
231
252
|
|
232
253
|
# Tries to find a constant with the name specified in the argument string.
|
233
254
|
#
|
234
|
-
# 'Module'
|
235
|
-
# '
|
255
|
+
# constantize('Module') # => Module
|
256
|
+
# constantize('Foo::Bar') # => Foo::Bar
|
236
257
|
#
|
237
258
|
# The name is assumed to be the one of a top-level constant, no matter
|
238
259
|
# whether it starts with "::" or not. No lexical context is taken into
|
@@ -241,14 +262,14 @@ module ActiveSupport
|
|
241
262
|
# C = 'outside'
|
242
263
|
# module M
|
243
264
|
# C = 'inside'
|
244
|
-
# C
|
245
|
-
# 'C'
|
265
|
+
# C # => 'inside'
|
266
|
+
# constantize('C') # => 'outside', same as ::C
|
246
267
|
# end
|
247
268
|
#
|
248
269
|
# NameError is raised when the name is not in CamelCase or the constant is
|
249
270
|
# unknown.
|
250
271
|
def constantize(camel_cased_word)
|
251
|
-
names = camel_cased_word.split(
|
272
|
+
names = camel_cased_word.split("::")
|
252
273
|
|
253
274
|
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
254
275
|
Object.const_get(camel_cased_word) if names.empty?
|
@@ -266,7 +287,7 @@ module ActiveSupport
|
|
266
287
|
|
267
288
|
# Go down the ancestors to check if it is owned directly. The check
|
268
289
|
# stops when we reach Object or the end of ancestors tree.
|
269
|
-
constant = constant.ancestors.inject do |const, ancestor|
|
290
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
270
291
|
break const if ancestor == Object
|
271
292
|
break ancestor if ancestor.const_defined?(name, false)
|
272
293
|
const
|
@@ -280,8 +301,8 @@ module ActiveSupport
|
|
280
301
|
|
281
302
|
# Tries to find a constant with the name specified in the argument string.
|
282
303
|
#
|
283
|
-
# 'Module'
|
284
|
-
# '
|
304
|
+
# safe_constantize('Module') # => Module
|
305
|
+
# safe_constantize('Foo::Bar') # => Foo::Bar
|
285
306
|
#
|
286
307
|
# The name is assumed to be the one of a top-level constant, no matter
|
287
308
|
# whether it starts with "::" or not. No lexical context is taken into
|
@@ -290,23 +311,25 @@ module ActiveSupport
|
|
290
311
|
# C = 'outside'
|
291
312
|
# module M
|
292
313
|
# C = 'inside'
|
293
|
-
# C
|
294
|
-
# 'C'
|
314
|
+
# C # => 'inside'
|
315
|
+
# safe_constantize('C') # => 'outside', same as ::C
|
295
316
|
# end
|
296
317
|
#
|
297
318
|
# +nil+ is returned when the name is not in CamelCase or the constant (or
|
298
319
|
# part of it) is unknown.
|
299
320
|
#
|
300
|
-
# 'blargle'
|
301
|
-
# 'UnknownModule'
|
302
|
-
# 'UnknownModule::Foo::Bar'
|
321
|
+
# safe_constantize('blargle') # => nil
|
322
|
+
# safe_constantize('UnknownModule') # => nil
|
323
|
+
# safe_constantize('UnknownModule::Foo::Bar') # => nil
|
303
324
|
def safe_constantize(camel_cased_word)
|
304
325
|
constantize(camel_cased_word)
|
305
326
|
rescue NameError => e
|
306
327
|
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
307
328
|
e.name.to_s == camel_cased_word.to_s)
|
308
329
|
rescue ArgumentError => e
|
309
|
-
raise unless
|
330
|
+
raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
|
331
|
+
rescue LoadError => e
|
332
|
+
raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(e.message)
|
310
333
|
end
|
311
334
|
|
312
335
|
# Returns the suffix that should be added to a number to denote the position
|
@@ -319,18 +342,7 @@ module ActiveSupport
|
|
319
342
|
# ordinal(-11) # => "th"
|
320
343
|
# ordinal(-1021) # => "st"
|
321
344
|
def ordinal(number)
|
322
|
-
|
323
|
-
|
324
|
-
if (11..13).include?(abs_number % 100)
|
325
|
-
"th"
|
326
|
-
else
|
327
|
-
case abs_number % 10
|
328
|
-
when 1; "st"
|
329
|
-
when 2; "nd"
|
330
|
-
when 3; "rd"
|
331
|
-
else "th"
|
332
|
-
end
|
333
|
-
end
|
345
|
+
I18n.translate("number.nth.ordinals", number: number)
|
334
346
|
end
|
335
347
|
|
336
348
|
# Turns a number into an ordinal string used to denote the position in an
|
@@ -343,41 +355,43 @@ module ActiveSupport
|
|
343
355
|
# ordinalize(-11) # => "-11th"
|
344
356
|
# ordinalize(-1021) # => "-1021st"
|
345
357
|
def ordinalize(number)
|
346
|
-
"
|
358
|
+
I18n.translate("number.nth.ordinalized", number: number)
|
347
359
|
end
|
348
360
|
|
349
361
|
private
|
362
|
+
# Mounts a regular expression, returned as a string to ease interpolation,
|
363
|
+
# that will match part by part the given constant.
|
364
|
+
#
|
365
|
+
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
366
|
+
# const_regexp("::") # => "::"
|
367
|
+
def const_regexp(camel_cased_word)
|
368
|
+
parts = camel_cased_word.split("::")
|
350
369
|
|
351
|
-
|
352
|
-
# that will match part by part the given constant.
|
353
|
-
#
|
354
|
-
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
355
|
-
# const_regexp("::") # => "::"
|
356
|
-
def const_regexp(camel_cased_word) #:nodoc:
|
357
|
-
parts = camel_cased_word.split("::")
|
358
|
-
|
359
|
-
return Regexp.escape(camel_cased_word) if parts.blank?
|
370
|
+
return Regexp.escape(camel_cased_word) if parts.blank?
|
360
371
|
|
361
|
-
|
372
|
+
last = parts.pop
|
362
373
|
|
363
|
-
|
364
|
-
|
374
|
+
parts.reverse.inject(last) do |acc, part|
|
375
|
+
part.empty? ? acc : "#{part}(::#{acc})?"
|
376
|
+
end
|
365
377
|
end
|
366
|
-
end
|
367
378
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
result
|
377
|
-
|
378
|
-
|
379
|
-
|
379
|
+
# Applies inflection rules for +singularize+ and +pluralize+.
|
380
|
+
#
|
381
|
+
# If passed an optional +locale+ parameter, the uncountables will be
|
382
|
+
# found for that locale.
|
383
|
+
#
|
384
|
+
# apply_inflections('post', inflections.plurals, :en) # => "posts"
|
385
|
+
# apply_inflections('posts', inflections.singulars, :en) # => "post"
|
386
|
+
def apply_inflections(word, rules, locale = :en)
|
387
|
+
result = word.to_s.dup
|
388
|
+
|
389
|
+
if word.empty? || inflections(locale).uncountables.uncountable?(result)
|
390
|
+
result
|
391
|
+
else
|
392
|
+
rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
393
|
+
result
|
394
|
+
end
|
380
395
|
end
|
381
|
-
end
|
382
396
|
end
|
383
397
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/multibyte"
|
4
|
+
require "active_support/i18n"
|
4
5
|
|
5
6
|
module ActiveSupport
|
6
7
|
module Inflector
|
7
|
-
|
8
8
|
# Replaces non-ASCII characters with an ASCII approximation, or if none
|
9
9
|
# exists, a replacement character which defaults to "?".
|
10
10
|
#
|
@@ -51,47 +51,97 @@ module ActiveSupport
|
|
51
51
|
#
|
52
52
|
# Now you can have different transliterations for each locale:
|
53
53
|
#
|
54
|
-
#
|
55
|
-
# transliterate('Jürgen')
|
54
|
+
# transliterate('Jürgen', locale: :en)
|
56
55
|
# # => "Jurgen"
|
57
56
|
#
|
58
|
-
#
|
59
|
-
# transliterate('Jürgen')
|
57
|
+
# transliterate('Jürgen', locale: :de)
|
60
58
|
# # => "Juergen"
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
#
|
60
|
+
# Transliteration is restricted to UTF-8, US-ASCII and GB18030 strings
|
61
|
+
# Other encodings will raise an ArgumentError.
|
62
|
+
def transliterate(string, replacement = "?", locale: nil)
|
63
|
+
string = string.dup if string.frozen?
|
64
|
+
raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
|
65
|
+
|
66
|
+
allowed_encodings = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030]
|
67
|
+
raise ArgumentError, "Can not transliterate strings with #{string.encoding} encoding" unless allowed_encodings.include?(string.encoding)
|
68
|
+
|
69
|
+
input_encoding = string.encoding
|
70
|
+
|
71
|
+
# US-ASCII is a subset of UTF-8 so we'll force encoding as UTF-8 if
|
72
|
+
# US-ASCII is given. This way we can let tidy_bytes handle the string
|
73
|
+
# in the same way as we do for UTF-8
|
74
|
+
string.force_encoding(Encoding::UTF_8) if string.encoding == Encoding::US_ASCII
|
75
|
+
|
76
|
+
# GB18030 is Unicode compatible but is not a direct mapping so needs to be
|
77
|
+
# transcoded. Using invalid/undef :replace will result in loss of data in
|
78
|
+
# the event of invalid characters, but since tidy_bytes will replace
|
79
|
+
# invalid/undef with a "?" we're safe to do the same beforehand
|
80
|
+
string.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) if string.encoding == Encoding::GB18030
|
81
|
+
|
82
|
+
transliterated = I18n.transliterate(
|
83
|
+
ActiveSupport::Multibyte::Unicode.tidy_bytes(string).unicode_normalize(:nfc),
|
84
|
+
replacement: replacement,
|
85
|
+
locale: locale
|
86
|
+
)
|
87
|
+
|
88
|
+
# Restore the string encoding of the input if it was not UTF-8.
|
89
|
+
# Apply invalid/undef :replace as tidy_bytes does
|
90
|
+
transliterated.encode!(input_encoding, invalid: :replace, undef: :replace) if input_encoding != transliterated.encoding
|
91
|
+
|
92
|
+
transliterated
|
65
93
|
end
|
66
94
|
|
67
95
|
# Replaces special characters in a string so that it may be used as part of
|
68
96
|
# a 'pretty' URL.
|
69
97
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
# # =>
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
98
|
+
# parameterize("Donald E. Knuth") # => "donald-e-knuth"
|
99
|
+
# parameterize("^très|Jolie-- ") # => "tres-jolie"
|
100
|
+
#
|
101
|
+
# To use a custom separator, override the +separator+ argument.
|
102
|
+
#
|
103
|
+
# parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
|
104
|
+
# parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
|
105
|
+
#
|
106
|
+
# To preserve the case of the characters in a string, use the +preserve_case+ argument.
|
107
|
+
#
|
108
|
+
# parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
|
109
|
+
# parameterize("^très|Jolie-- ", preserve_case: true) # => "tres-Jolie"
|
110
|
+
#
|
111
|
+
# It preserves dashes and underscores unless they are used as separators:
|
112
|
+
#
|
113
|
+
# parameterize("^très|Jolie__ ") # => "tres-jolie__"
|
114
|
+
# parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
|
115
|
+
# parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
|
116
|
+
#
|
117
|
+
# If the optional parameter +locale+ is specified,
|
118
|
+
# the word will be parameterized as a word of that language.
|
119
|
+
# By default, this parameter is set to <tt>nil</tt> and it will use
|
120
|
+
# the configured <tt>I18n.locale<tt>.
|
121
|
+
def parameterize(string, separator: "-", preserve_case: false, locale: nil)
|
122
|
+
# Replace accented chars with their ASCII equivalents.
|
123
|
+
parameterized_string = transliterate(string, locale: locale)
|
124
|
+
|
125
|
+
# Turn unwanted chars into the separator.
|
126
|
+
parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
|
127
|
+
|
128
|
+
unless separator.nil? || separator.empty?
|
129
|
+
if separator == "-"
|
130
|
+
re_duplicate_separator = /-{2,}/
|
131
|
+
re_leading_trailing_separator = /^-|-$/i
|
132
|
+
else
|
133
|
+
re_sep = Regexp.escape(separator)
|
134
|
+
re_duplicate_separator = /#{re_sep}{2,}/
|
135
|
+
re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
|
136
|
+
end
|
88
137
|
# No more than one of the separator in a row.
|
89
|
-
parameterized_string.gsub!(
|
138
|
+
parameterized_string.gsub!(re_duplicate_separator, separator)
|
90
139
|
# Remove leading/trailing separator.
|
91
|
-
parameterized_string.gsub!(
|
140
|
+
parameterized_string.gsub!(re_leading_trailing_separator, "")
|
92
141
|
end
|
93
|
-
parameterized_string.downcase
|
94
|
-
end
|
95
142
|
|
143
|
+
parameterized_string.downcase! unless preserve_case
|
144
|
+
parameterized_string
|
145
|
+
end
|
96
146
|
end
|
97
147
|
end
|