activesupport 4.2.11.1 → 6.1.7.3
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 +464 -391
- 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 +50 -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 +61 -55
- data/lib/active_support/cache/mem_cache_store.rb +115 -100
- data/lib/active_support/cache/memory_store.rb +81 -58
- 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 +90 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +386 -225
- data/lib/active_support/callbacks.rb +661 -594
- data/lib/active_support/concern.rb +80 -7
- 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 +16 -17
- data/lib/active_support/configuration_file.rb +51 -0
- 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/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- 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 +52 -48
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -25
- 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 +27 -24
- 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 +167 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +19 -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 +8 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +186 -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/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 +13 -10
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +20 -43
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +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 +10 -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 +63 -69
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +148 -0
- data/lib/active_support/core_ext/module/concerning.rb +19 -14
- data/lib/active_support/core_ext/module/delegation.rb +164 -51
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +23 -22
- 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 +51 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +133 -136
- 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 +63 -21
- 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 +82 -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_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -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 +102 -26
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +125 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- 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/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +137 -53
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +22 -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 +11 -8
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +210 -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 +120 -0
- data/lib/active_support/dependencies.rb +241 -175
- data/lib/active_support/deprecation/behaviors.rb +58 -12
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- 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 +59 -0
- data/lib/active_support/duration.rb +364 -39
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +170 -0
- data/lib/active_support/execution_wrapper.rb +132 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +7 -5
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +171 -48
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +47 -16
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -14
- data/lib/active_support/inflector/methods.rb +186 -169
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +22 -61
- 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 +9 -3
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +52 -19
- data/lib/active_support/logger.rb +10 -24
- data/lib/active_support/logger_silence.rb +14 -20
- data/lib/active_support/logger_thread_safe_level.rb +56 -10
- data/lib/active_support/message_encryptor.rb +167 -57
- data/lib/active_support/message_verifier.rb +151 -18
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +35 -80
- data/lib/active_support/multibyte/unicode.rb +22 -330
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +125 -23
- data/lib/active_support/notifications/instrumenter.rb +98 -16
- data/lib/active_support/notifications.rb +82 -14
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -14
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +14 -11
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +12 -10
- 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 +29 -57
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +123 -71
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +35 -7
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +10 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +66 -10
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +13 -4
- data/lib/active_support/subscriber.rb +80 -31
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +158 -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/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +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 +121 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +215 -51
- data/lib/active_support/values/time_zone.rb +223 -71
- 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 +18 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +25 -11
- metadata +100 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- 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/hash/compact.rb +0 -24
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -23
- 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/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- 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,7 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "active_support/inflections"
|
4
|
+
require "active_support/core_ext/object/blank"
|
4
5
|
|
5
6
|
module ActiveSupport
|
6
7
|
# The Inflector transforms words from singular to plural, class names to table
|
@@ -22,58 +23,58 @@ module ActiveSupport
|
|
22
23
|
# pluralized using rules defined for that language. By default,
|
23
24
|
# this parameter is set to <tt>:en</tt>.
|
24
25
|
#
|
25
|
-
# 'post'
|
26
|
-
# 'octopus'
|
27
|
-
# 'sheep'
|
28
|
-
# 'words'
|
29
|
-
# 'CamelOctopus'
|
30
|
-
# 'ley'
|
26
|
+
# pluralize('post') # => "posts"
|
27
|
+
# pluralize('octopus') # => "octopi"
|
28
|
+
# pluralize('sheep') # => "sheep"
|
29
|
+
# pluralize('words') # => "words"
|
30
|
+
# pluralize('CamelOctopus') # => "CamelOctopi"
|
31
|
+
# pluralize('ley', :es) # => "leyes"
|
31
32
|
def pluralize(word, locale = :en)
|
32
|
-
apply_inflections(word, inflections(locale).plurals)
|
33
|
+
apply_inflections(word, inflections(locale).plurals, locale)
|
33
34
|
end
|
34
35
|
|
35
|
-
# The reverse of
|
36
|
+
# The reverse of #pluralize, returns the singular form of a word in a
|
36
37
|
# string.
|
37
38
|
#
|
38
39
|
# If passed an optional +locale+ parameter, the word will be
|
39
40
|
# singularized using rules defined for that language. By default,
|
40
41
|
# this parameter is set to <tt>:en</tt>.
|
41
42
|
#
|
42
|
-
# 'posts'
|
43
|
-
# 'octopi'
|
44
|
-
# 'sheep'
|
45
|
-
# 'word'
|
46
|
-
# 'CamelOctopi'
|
47
|
-
# 'leyes'
|
43
|
+
# singularize('posts') # => "post"
|
44
|
+
# singularize('octopi') # => "octopus"
|
45
|
+
# singularize('sheep') # => "sheep"
|
46
|
+
# singularize('word') # => "word"
|
47
|
+
# singularize('CamelOctopi') # => "CamelOctopus"
|
48
|
+
# singularize('leyes', :es) # => "ley"
|
48
49
|
def singularize(word, locale = :en)
|
49
|
-
apply_inflections(word, inflections(locale).singulars)
|
50
|
+
apply_inflections(word, inflections(locale).singulars, locale)
|
50
51
|
end
|
51
52
|
|
52
|
-
#
|
53
|
-
#
|
53
|
+
# Converts strings to UpperCamelCase.
|
54
|
+
# If the +uppercase_first_letter+ parameter is set to false, then produces
|
54
55
|
# lowerCamelCase.
|
55
56
|
#
|
56
|
-
#
|
57
|
+
# Also converts '/' to '::' which is useful for converting
|
57
58
|
# paths to namespaces.
|
58
59
|
#
|
59
|
-
# 'active_model'
|
60
|
-
# 'active_model'
|
61
|
-
# 'active_model/errors'
|
62
|
-
# 'active_model/errors'
|
60
|
+
# camelize('active_model') # => "ActiveModel"
|
61
|
+
# camelize('active_model', false) # => "activeModel"
|
62
|
+
# camelize('active_model/errors') # => "ActiveModel::Errors"
|
63
|
+
# camelize('active_model/errors', false) # => "activeModel::Errors"
|
63
64
|
#
|
64
65
|
# As a rule of thumb you can think of +camelize+ as the inverse of
|
65
|
-
#
|
66
|
+
# #underscore, though there are cases where that does not hold:
|
66
67
|
#
|
67
|
-
# 'SSLError'
|
68
|
+
# camelize(underscore('SSLError')) # => "SslError"
|
68
69
|
def camelize(term, uppercase_first_letter = true)
|
69
70
|
string = term.to_s
|
70
71
|
if uppercase_first_letter
|
71
|
-
string = string.sub(/^[a-z\d]*/) { inflections.acronyms[
|
72
|
+
string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
|
72
73
|
else
|
73
|
-
string = string.sub(
|
74
|
+
string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase }
|
74
75
|
end
|
75
76
|
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
76
|
-
string.gsub!(
|
77
|
+
string.gsub!("/", "::")
|
77
78
|
string
|
78
79
|
end
|
79
80
|
|
@@ -81,19 +82,18 @@ module ActiveSupport
|
|
81
82
|
#
|
82
83
|
# Changes '::' to '/' to convert namespaces to paths.
|
83
84
|
#
|
84
|
-
# 'ActiveModel'
|
85
|
-
# 'ActiveModel::Errors'
|
85
|
+
# underscore('ActiveModel') # => "active_model"
|
86
|
+
# underscore('ActiveModel::Errors') # => "active_model/errors"
|
86
87
|
#
|
87
88
|
# As a rule of thumb you can think of +underscore+ as the inverse of
|
88
|
-
#
|
89
|
+
# #camelize, though there are cases where that does not hold:
|
89
90
|
#
|
90
|
-
# 'SSLError'
|
91
|
+
# camelize(underscore('SSLError')) # => "SslError"
|
91
92
|
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
|
96
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
93
|
+
return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
|
94
|
+
word = camel_cased_word.to_s.gsub("::", "/")
|
95
|
+
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
96
|
+
word.gsub!(/([A-Z])(?=[A-Z][a-z])|([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.delete_suffix!("_id")
|
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,47 +262,51 @@ 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
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
if
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
const
|
272
|
+
if camel_cased_word.blank? || !camel_cased_word.include?("::")
|
273
|
+
Object.const_get(camel_cased_word)
|
274
|
+
else
|
275
|
+
names = camel_cased_word.split("::")
|
276
|
+
|
277
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
278
|
+
Object.const_get(camel_cased_word) if names.empty?
|
279
|
+
|
280
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
281
|
+
names.shift if names.size > 1 && names.first.empty?
|
282
|
+
|
283
|
+
names.inject(Object) do |constant, name|
|
284
|
+
if constant == Object
|
285
|
+
constant.const_get(name)
|
286
|
+
else
|
287
|
+
candidate = constant.const_get(name)
|
288
|
+
next candidate if constant.const_defined?(name, false)
|
289
|
+
next candidate unless Object.const_defined?(name)
|
290
|
+
|
291
|
+
# Go down the ancestors to check if it is owned directly. The check
|
292
|
+
# stops when we reach Object or the end of ancestors tree.
|
293
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
294
|
+
break const if ancestor == Object
|
295
|
+
break ancestor if ancestor.const_defined?(name, false)
|
296
|
+
const
|
297
|
+
end
|
298
|
+
|
299
|
+
# owner is in Object, so raise
|
300
|
+
constant.const_get(name, false)
|
273
301
|
end
|
274
|
-
|
275
|
-
# owner is in Object, so raise
|
276
|
-
constant.const_get(name, false)
|
277
302
|
end
|
278
303
|
end
|
279
304
|
end
|
280
305
|
|
281
306
|
# Tries to find a constant with the name specified in the argument string.
|
282
307
|
#
|
283
|
-
# 'Module'
|
284
|
-
# '
|
308
|
+
# safe_constantize('Module') # => Module
|
309
|
+
# safe_constantize('Foo::Bar') # => Foo::Bar
|
285
310
|
#
|
286
311
|
# The name is assumed to be the one of a top-level constant, no matter
|
287
312
|
# whether it starts with "::" or not. No lexical context is taken into
|
@@ -290,23 +315,24 @@ module ActiveSupport
|
|
290
315
|
# C = 'outside'
|
291
316
|
# module M
|
292
317
|
# C = 'inside'
|
293
|
-
# C
|
294
|
-
# 'C'
|
318
|
+
# C # => 'inside'
|
319
|
+
# safe_constantize('C') # => 'outside', same as ::C
|
295
320
|
# end
|
296
321
|
#
|
297
322
|
# +nil+ is returned when the name is not in CamelCase or the constant (or
|
298
323
|
# part of it) is unknown.
|
299
324
|
#
|
300
|
-
# 'blargle'
|
301
|
-
# 'UnknownModule'
|
302
|
-
# 'UnknownModule::Foo::Bar'
|
325
|
+
# safe_constantize('blargle') # => nil
|
326
|
+
# safe_constantize('UnknownModule') # => nil
|
327
|
+
# safe_constantize('UnknownModule::Foo::Bar') # => nil
|
303
328
|
def safe_constantize(camel_cased_word)
|
304
329
|
constantize(camel_cased_word)
|
305
330
|
rescue NameError => e
|
306
331
|
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
307
332
|
e.name.to_s == camel_cased_word.to_s)
|
308
|
-
rescue
|
309
|
-
|
333
|
+
rescue LoadError => e
|
334
|
+
message = e.respond_to?(:original_message) ? e.original_message : e.message
|
335
|
+
raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(message)
|
310
336
|
end
|
311
337
|
|
312
338
|
# Returns the suffix that should be added to a number to denote the position
|
@@ -319,18 +345,7 @@ module ActiveSupport
|
|
319
345
|
# ordinal(-11) # => "th"
|
320
346
|
# ordinal(-1021) # => "st"
|
321
347
|
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
|
348
|
+
I18n.translate("number.nth.ordinals", number: number)
|
334
349
|
end
|
335
350
|
|
336
351
|
# Turns a number into an ordinal string used to denote the position in an
|
@@ -343,41 +358,43 @@ module ActiveSupport
|
|
343
358
|
# ordinalize(-11) # => "-11th"
|
344
359
|
# ordinalize(-1021) # => "-1021st"
|
345
360
|
def ordinalize(number)
|
346
|
-
"
|
361
|
+
I18n.translate("number.nth.ordinalized", number: number)
|
347
362
|
end
|
348
363
|
|
349
364
|
private
|
365
|
+
# Mounts a regular expression, returned as a string to ease interpolation,
|
366
|
+
# that will match part by part the given constant.
|
367
|
+
#
|
368
|
+
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
369
|
+
# const_regexp("::") # => "::"
|
370
|
+
def const_regexp(camel_cased_word)
|
371
|
+
parts = camel_cased_word.split("::")
|
350
372
|
|
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?
|
373
|
+
return Regexp.escape(camel_cased_word) if parts.blank?
|
360
374
|
|
361
|
-
|
375
|
+
last = parts.pop
|
362
376
|
|
363
|
-
|
364
|
-
|
377
|
+
parts.reverse!.inject(last) do |acc, part|
|
378
|
+
part.empty? ? acc : "#{part}(::#{acc})?"
|
379
|
+
end
|
365
380
|
end
|
366
|
-
end
|
367
|
-
|
368
|
-
# Applies inflection rules for +singularize+ and +pluralize+.
|
369
|
-
#
|
370
|
-
# apply_inflections('post', inflections.plurals) # => "posts"
|
371
|
-
# apply_inflections('posts', inflections.singulars) # => "post"
|
372
|
-
def apply_inflections(word, rules)
|
373
|
-
result = word.to_s.dup
|
374
381
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
382
|
+
# Applies inflection rules for +singularize+ and +pluralize+.
|
383
|
+
#
|
384
|
+
# If passed an optional +locale+ parameter, the uncountables will be
|
385
|
+
# found for that locale.
|
386
|
+
#
|
387
|
+
# apply_inflections('post', inflections.plurals, :en) # => "posts"
|
388
|
+
# apply_inflections('posts', inflections.singulars, :en) # => "post"
|
389
|
+
def apply_inflections(word, rules, locale = :en)
|
390
|
+
result = word.to_s.dup
|
391
|
+
|
392
|
+
if word.empty? || inflections(locale).uncountables.uncountable?(result)
|
393
|
+
result
|
394
|
+
else
|
395
|
+
rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
396
|
+
result
|
397
|
+
end
|
380
398
|
end
|
381
|
-
end
|
382
399
|
end
|
383
400
|
end
|