activesupport 5.1.1 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +360 -442
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +6 -2
- data/lib/active_support/backtrace_cleaner.rb +31 -3
- data/lib/active_support/benchmarkable.rb +3 -1
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +37 -36
- data/lib/active_support/cache/mem_cache_store.rb +65 -53
- data/lib/active_support/cache/memory_store.rb +61 -33
- data/lib/active_support/cache/null_store.rb +10 -3
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +68 -22
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +305 -127
- data/lib/active_support/callbacks.rb +106 -98
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -1
- data/lib/active_support/configurable.rb +12 -14
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +7 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +3 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +18 -40
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +8 -5
- data/lib/active_support/core_ext/date/conversions.rb +12 -10
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +174 -71
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -5
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +3 -30
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/marshal.rb +4 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +103 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +3 -1
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +2 -1
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +13 -3
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +6 -101
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +22 -2
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +7 -2
- data/lib/active_support/core_ext/object/try.rb +19 -7
- data/lib/active_support/core_ext/object/with_options.rb +4 -2
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +3 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +3 -0
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +76 -20
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +73 -18
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +4 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +11 -6
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +135 -60
- data/lib/active_support/deprecation/behaviors.rb +43 -11
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +30 -15
- data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +9 -2
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +6 -6
- data/lib/active_support/duration/iso8601_serializer.rb +20 -14
- data/lib/active_support/duration.rb +179 -41
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +84 -117
- data/lib/active_support/execution_wrapper.rb +3 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +3 -1
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +134 -37
- data/lib/active_support/i18n.rb +4 -1
- data/lib/active_support/i18n_railtie.rb +20 -11
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +19 -8
- data/lib/active_support/inflector/methods.rb +87 -77
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +13 -3
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -33
- data/lib/active_support/lazy_load_hooks.rb +33 -10
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/log_subscriber.rb +46 -13
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +54 -7
- data/lib/active_support/message_encryptor.rb +101 -33
- data/lib/active_support/message_verifier.rb +85 -14
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +12 -68
- data/lib/active_support/multibyte/unicode.rb +17 -327
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +118 -16
- data/lib/active_support/notifications/instrumenter.rb +73 -9
- data/lib/active_support/notifications.rb +74 -8
- data/lib/active_support/number_helper/number_converter.rb +7 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +8 -7
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +16 -53
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +41 -12
- data/lib/active_support/option_merger.rb +24 -3
- data/lib/active_support/ordered_hash.rb +3 -1
- data/lib/active_support/ordered_options.rb +17 -5
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +3 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +60 -9
- data/lib/active_support/reloader.rb +11 -10
- data/lib/active_support/rescuable.rb +7 -6
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +6 -3
- data/lib/active_support/subscriber.rb +74 -24
- data/lib/active_support/tagged_logging.rb +44 -8
- data/lib/active_support/test_case.rb +94 -2
- data/lib/active_support/testing/assertions.rb +58 -20
- data/lib/active_support/testing/autorun.rb +2 -4
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -1
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +8 -4
- data/lib/active_support/testing/method_call_assertions.rb +30 -1
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +3 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +78 -13
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +113 -41
- data/lib/active_support/values/time_zone.rb +55 -25
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini/jdom.rb +5 -4
- data/lib/active_support/xml_mini/libxml.rb +4 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
- data/lib/active_support/xml_mini/nokogiri.rb +4 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
- data/lib/active_support/xml_mini/rexml.rb +12 -3
- data/lib/active_support/xml_mini.rb +5 -11
- data/lib/active_support.rb +18 -13
- metadata +81 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/values/unicode_tables.dat +0 -0
data/lib/active_support/i18n.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/deep_merge"
|
2
4
|
require "active_support/core_ext/hash/except"
|
3
5
|
require "active_support/core_ext/hash/slice"
|
@@ -10,4 +12,5 @@ end
|
|
10
12
|
require "active_support/lazy_load_hooks"
|
11
13
|
|
12
14
|
ActiveSupport.run_load_hooks(:i18n)
|
13
|
-
I18n.load_path <<
|
15
|
+
I18n.load_path << File.expand_path("locale/en.yml", __dir__)
|
16
|
+
I18n.load_path << File.expand_path("locale/en.rb", __dir__)
|
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support"
|
2
|
-
require "active_support/file_update_checker"
|
3
4
|
require "active_support/core_ext/array/wrap"
|
4
5
|
|
5
6
|
# :enddoc:
|
@@ -11,6 +12,8 @@ module I18n
|
|
11
12
|
config.i18n.load_path = []
|
12
13
|
config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
|
13
14
|
|
15
|
+
config.eager_load_namespaces << I18n
|
16
|
+
|
14
17
|
# Set the i18n configuration after initialization since a lot of
|
15
18
|
# configuration is still usually done in application initializers.
|
16
19
|
config.after_initialize do |app|
|
@@ -42,11 +45,13 @@ module I18n
|
|
42
45
|
case setting
|
43
46
|
when :railties_load_path
|
44
47
|
reloadable_paths = value
|
45
|
-
app.config.i18n.load_path.unshift(*value.
|
48
|
+
app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
|
46
49
|
when :load_path
|
47
50
|
I18n.load_path += value
|
51
|
+
when :raise_on_missing_translations
|
52
|
+
forward_raise_on_missing_translations_config(app)
|
48
53
|
else
|
49
|
-
I18n.
|
54
|
+
I18n.public_send("#{setting}=", value)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
@@ -58,24 +63,28 @@ module I18n
|
|
58
63
|
directories = watched_dirs_with_extensions(reloadable_paths)
|
59
64
|
reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
|
60
65
|
I18n.load_path.keep_if { |p| File.exist?(p) }
|
61
|
-
I18n.load_path |= reloadable_paths.
|
62
|
-
|
63
|
-
I18n.reload!
|
66
|
+
I18n.load_path |= reloadable_paths.flat_map(&:existent)
|
64
67
|
end
|
65
68
|
|
66
69
|
app.reloaders << reloader
|
67
70
|
app.reloader.to_run do
|
68
71
|
reloader.execute_if_updated { require_unload_lock! }
|
69
|
-
# TODO: remove the following line as soon as the return value of
|
70
|
-
# callbacks is ignored, that is, returning `false` does not
|
71
|
-
# display a deprecation warning or halts the callback chain.
|
72
|
-
true
|
73
72
|
end
|
74
73
|
reloader.execute
|
75
74
|
|
76
75
|
@i18n_inited = true
|
77
76
|
end
|
78
77
|
|
78
|
+
def self.forward_raise_on_missing_translations_config(app)
|
79
|
+
ActiveSupport.on_load(:action_view) do
|
80
|
+
self.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
|
81
|
+
end
|
82
|
+
|
83
|
+
ActiveSupport.on_load(:action_controller) do
|
84
|
+
AbstractController::Translation.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
79
88
|
def self.include_fallbacks_module
|
80
89
|
I18n.backend.class.include(I18n::Backend::Fallbacks)
|
81
90
|
end
|
@@ -90,7 +99,7 @@ module I18n
|
|
90
99
|
when Hash, Array
|
91
100
|
Array.wrap(fallbacks)
|
92
101
|
else # TrueClass
|
93
|
-
[]
|
102
|
+
[I18n.default_locale]
|
94
103
|
end
|
95
104
|
|
96
105
|
I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
|
@@ -1,6 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent/map"
|
2
|
-
require "active_support/core_ext/array/prepend_and_append"
|
3
|
-
require "active_support/core_ext/regexp"
|
4
4
|
require "active_support/i18n"
|
5
5
|
|
6
6
|
module ActiveSupport
|
@@ -64,17 +64,21 @@ module ActiveSupport
|
|
64
64
|
@__instance__[locale] ||= new
|
65
65
|
end
|
66
66
|
|
67
|
-
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms
|
67
|
+
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms
|
68
|
+
|
69
|
+
attr_reader :acronyms_camelize_regex, :acronyms_underscore_regex # :nodoc:
|
68
70
|
|
69
71
|
def initialize
|
70
|
-
@plurals, @singulars, @uncountables, @humans, @acronyms
|
72
|
+
@plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
|
73
|
+
define_acronym_regex_patterns
|
71
74
|
end
|
72
75
|
|
73
76
|
# Private, for the test suite.
|
74
77
|
def initialize_dup(orig) # :nodoc:
|
75
|
-
%w(plurals singulars uncountables humans acronyms
|
76
|
-
instance_variable_set("@#{scope}", orig.
|
78
|
+
%w(plurals singulars uncountables humans acronyms).each do |scope|
|
79
|
+
instance_variable_set("@#{scope}", orig.public_send(scope).dup)
|
77
80
|
end
|
81
|
+
define_acronym_regex_patterns
|
78
82
|
end
|
79
83
|
|
80
84
|
# Specifies a new acronym. An acronym must be specified as it will appear
|
@@ -128,7 +132,7 @@ module ActiveSupport
|
|
128
132
|
# camelize 'mcdonald' # => 'McDonald'
|
129
133
|
def acronym(word)
|
130
134
|
@acronyms[word.downcase] = word
|
131
|
-
|
135
|
+
define_acronym_regex_patterns
|
132
136
|
end
|
133
137
|
|
134
138
|
# Specifies a new pluralization rule and its replacement. The rule can
|
@@ -219,10 +223,17 @@ module ActiveSupport
|
|
219
223
|
case scope
|
220
224
|
when :all
|
221
225
|
@plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
|
222
|
-
|
226
|
+
else
|
223
227
|
instance_variable_set "@#{scope}", []
|
224
228
|
end
|
225
229
|
end
|
230
|
+
|
231
|
+
private
|
232
|
+
def define_acronym_regex_patterns
|
233
|
+
@acronym_regex = @acronyms.empty? ? /(?=a)b/ : /#{@acronyms.values.join("|")}/
|
234
|
+
@acronyms_camelize_regex = /^(?:#{@acronym_regex}(?=\b|[A-Z_])|\w)/
|
235
|
+
@acronyms_underscore_regex = /(?:(?<=([A-Za-z\d]))|\b)(#{@acronym_regex})(?=\b|[^a-z])/
|
236
|
+
end
|
226
237
|
end
|
227
238
|
|
228
239
|
# Yields a singleton instance of Inflector::Inflections so you can specify
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/inflections"
|
2
|
-
require "active_support/core_ext/
|
4
|
+
require "active_support/core_ext/object/blank"
|
3
5
|
|
4
6
|
module ActiveSupport
|
5
7
|
# The Inflector transforms words from singular to plural, class names to table
|
@@ -28,7 +30,7 @@ module ActiveSupport
|
|
28
30
|
# pluralize('CamelOctopus') # => "CamelOctopi"
|
29
31
|
# pluralize('ley', :es) # => "leyes"
|
30
32
|
def pluralize(word, locale = :en)
|
31
|
-
apply_inflections(word, inflections(locale).plurals)
|
33
|
+
apply_inflections(word, inflections(locale).plurals, locale)
|
32
34
|
end
|
33
35
|
|
34
36
|
# The reverse of #pluralize, returns the singular form of a word in a
|
@@ -45,7 +47,7 @@ module ActiveSupport
|
|
45
47
|
# singularize('CamelOctopi') # => "CamelOctopus"
|
46
48
|
# singularize('leyes', :es) # => "ley"
|
47
49
|
def singularize(word, locale = :en)
|
48
|
-
apply_inflections(word, inflections(locale).singulars)
|
50
|
+
apply_inflections(word, inflections(locale).singulars, locale)
|
49
51
|
end
|
50
52
|
|
51
53
|
# Converts strings to UpperCamelCase.
|
@@ -69,10 +71,10 @@ module ActiveSupport
|
|
69
71
|
if uppercase_first_letter
|
70
72
|
string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
|
71
73
|
else
|
72
|
-
string = string.sub(
|
74
|
+
string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase }
|
73
75
|
end
|
74
76
|
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
|
75
|
-
string.gsub!("/"
|
77
|
+
string.gsub!("/", "::")
|
76
78
|
string
|
77
79
|
end
|
78
80
|
|
@@ -89,11 +91,11 @@ module ActiveSupport
|
|
89
91
|
# camelize(underscore('SSLError')) # => "SslError"
|
90
92
|
def underscore(camel_cased_word)
|
91
93
|
return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
|
92
|
-
word = camel_cased_word.to_s.gsub("::"
|
93
|
-
word.gsub!(
|
94
|
-
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'
|
95
|
-
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'
|
96
|
-
word.tr!("-"
|
94
|
+
word = camel_cased_word.to_s.gsub("::", "/")
|
95
|
+
word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
|
96
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
97
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
98
|
+
word.tr!("-", "_")
|
97
99
|
word.downcase!
|
98
100
|
word
|
99
101
|
end
|
@@ -108,33 +110,38 @@ module ActiveSupport
|
|
108
110
|
# * Replaces underscores with spaces, if any.
|
109
111
|
# * Downcases all words except acronyms.
|
110
112
|
# * Capitalizes the first word.
|
111
|
-
#
|
112
113
|
# The capitalization of the first word can be turned off by setting the
|
113
114
|
# +:capitalize+ option to false (default is true).
|
114
115
|
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# humanize('
|
116
|
+
# The trailing '_id' can be kept and capitalized by setting the
|
117
|
+
# optional parameter +keep_id_suffix+ to true (default is false).
|
118
|
+
#
|
119
|
+
# humanize('employee_salary') # => "Employee salary"
|
120
|
+
# humanize('author_id') # => "Author"
|
121
|
+
# humanize('author_id', capitalize: false) # => "author"
|
122
|
+
# humanize('_id') # => "Id"
|
123
|
+
# humanize('author_id', keep_id_suffix: true) # => "Author Id"
|
119
124
|
#
|
120
125
|
# If "SSL" was defined to be an acronym:
|
121
126
|
#
|
122
127
|
# humanize('ssl_error') # => "SSL error"
|
123
128
|
#
|
124
|
-
def humanize(lower_case_and_underscored_word,
|
129
|
+
def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
|
125
130
|
result = lower_case_and_underscored_word.to_s.dup
|
126
131
|
|
127
132
|
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
128
133
|
|
129
|
-
result.sub!(/\A_+/, ""
|
130
|
-
|
131
|
-
|
134
|
+
result.sub!(/\A_+/, "")
|
135
|
+
unless keep_id_suffix
|
136
|
+
result.delete_suffix!("_id")
|
137
|
+
end
|
138
|
+
result.tr!("_", " ")
|
132
139
|
|
133
140
|
result.gsub!(/([a-z\d]*)/i) do |match|
|
134
|
-
"#{inflections.acronyms[match] || match.downcase}"
|
141
|
+
"#{inflections.acronyms[match.downcase] || match.downcase}"
|
135
142
|
end
|
136
143
|
|
137
|
-
if
|
144
|
+
if capitalize
|
138
145
|
result.sub!(/\A\w/) { |match| match.upcase }
|
139
146
|
end
|
140
147
|
|
@@ -154,14 +161,21 @@ module ActiveSupport
|
|
154
161
|
# create a nicer looking title. +titleize+ is meant for creating pretty
|
155
162
|
# output. It is not used in the Rails internals.
|
156
163
|
#
|
164
|
+
# The trailing '_id','Id'.. can be kept and capitalized by setting the
|
165
|
+
# optional parameter +keep_id_suffix+ to true.
|
166
|
+
# By default, this parameter is false.
|
167
|
+
#
|
157
168
|
# +titleize+ is also aliased as +titlecase+.
|
158
169
|
#
|
159
|
-
# titleize('man from the boondocks')
|
160
|
-
# titleize('x-men: the last stand')
|
161
|
-
# titleize('TheManWithoutAPast')
|
162
|
-
# titleize('raiders_of_the_lost_ark')
|
163
|
-
|
164
|
-
|
170
|
+
# titleize('man from the boondocks') # => "Man From The Boondocks"
|
171
|
+
# titleize('x-men: the last stand') # => "X Men: The Last Stand"
|
172
|
+
# titleize('TheManWithoutAPast') # => "The Man Without A Past"
|
173
|
+
# titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
|
174
|
+
# titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
|
175
|
+
def titleize(word, keep_id_suffix: false)
|
176
|
+
humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`()])[a-z]/) do |match|
|
177
|
+
match.capitalize
|
178
|
+
end
|
165
179
|
end
|
166
180
|
|
167
181
|
# Creates the name of a table like Rails does for models to table names.
|
@@ -183,17 +197,17 @@ module ActiveSupport
|
|
183
197
|
#
|
184
198
|
# Singular names are not handled correctly:
|
185
199
|
#
|
186
|
-
# classify('calculus') # => "
|
200
|
+
# classify('calculus') # => "Calculu"
|
187
201
|
def classify(table_name)
|
188
202
|
# strip out any leading schema name
|
189
|
-
camelize(singularize(table_name.to_s.sub(/.*\./, ""
|
203
|
+
camelize(singularize(table_name.to_s.sub(/.*\./, "")))
|
190
204
|
end
|
191
205
|
|
192
206
|
# Replaces underscores with dashes in the string.
|
193
207
|
#
|
194
208
|
# dasherize('puni_puni') # => "puni-puni"
|
195
209
|
def dasherize(underscored_word)
|
196
|
-
underscored_word.tr("_"
|
210
|
+
underscored_word.tr("_", "-")
|
197
211
|
end
|
198
212
|
|
199
213
|
# Removes the module part from the expression in the string.
|
@@ -256,32 +270,36 @@ module ActiveSupport
|
|
256
270
|
# NameError is raised when the name is not in CamelCase or the constant is
|
257
271
|
# unknown.
|
258
272
|
def constantize(camel_cased_word)
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
if
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
const
|
273
|
+
if camel_cased_word.blank? || !camel_cased_word.include?("::")
|
274
|
+
Object.const_get(camel_cased_word)
|
275
|
+
else
|
276
|
+
names = camel_cased_word.split("::")
|
277
|
+
|
278
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
279
|
+
Object.const_get(camel_cased_word) if names.empty?
|
280
|
+
|
281
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
282
|
+
names.shift if names.size > 1 && names.first.empty?
|
283
|
+
|
284
|
+
names.inject(Object) do |constant, name|
|
285
|
+
if constant == Object
|
286
|
+
constant.const_get(name)
|
287
|
+
else
|
288
|
+
candidate = constant.const_get(name)
|
289
|
+
next candidate if constant.const_defined?(name, false)
|
290
|
+
next candidate unless Object.const_defined?(name)
|
291
|
+
|
292
|
+
# Go down the ancestors to check if it is owned directly. The check
|
293
|
+
# stops when we reach Object or the end of ancestors tree.
|
294
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
295
|
+
break const if ancestor == Object
|
296
|
+
break ancestor if ancestor.const_defined?(name, false)
|
297
|
+
const
|
298
|
+
end
|
299
|
+
|
300
|
+
# owner is in Object, so raise
|
301
|
+
constant.const_get(name, false)
|
281
302
|
end
|
282
|
-
|
283
|
-
# owner is in Object, so raise
|
284
|
-
constant.const_get(name, false)
|
285
303
|
end
|
286
304
|
end
|
287
305
|
end
|
@@ -313,8 +331,9 @@ module ActiveSupport
|
|
313
331
|
rescue NameError => e
|
314
332
|
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
315
333
|
e.name.to_s == camel_cased_word.to_s)
|
316
|
-
rescue
|
317
|
-
|
334
|
+
rescue LoadError => e
|
335
|
+
message = e.respond_to?(:original_message) ? e.original_message : e.message
|
336
|
+
raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(message)
|
318
337
|
end
|
319
338
|
|
320
339
|
# Returns the suffix that should be added to a number to denote the position
|
@@ -327,18 +346,7 @@ module ActiveSupport
|
|
327
346
|
# ordinal(-11) # => "th"
|
328
347
|
# ordinal(-1021) # => "st"
|
329
348
|
def ordinal(number)
|
330
|
-
|
331
|
-
|
332
|
-
if (11..13).include?(abs_number % 100)
|
333
|
-
"th"
|
334
|
-
else
|
335
|
-
case abs_number % 10
|
336
|
-
when 1; "st"
|
337
|
-
when 2; "nd"
|
338
|
-
when 3; "rd"
|
339
|
-
else "th"
|
340
|
-
end
|
341
|
-
end
|
349
|
+
I18n.translate("number.nth.ordinals", number: number)
|
342
350
|
end
|
343
351
|
|
344
352
|
# Turns a number into an ordinal string used to denote the position in an
|
@@ -351,36 +359,38 @@ module ActiveSupport
|
|
351
359
|
# ordinalize(-11) # => "-11th"
|
352
360
|
# ordinalize(-1021) # => "-1021st"
|
353
361
|
def ordinalize(number)
|
354
|
-
"
|
362
|
+
I18n.translate("number.nth.ordinalized", number: number)
|
355
363
|
end
|
356
364
|
|
357
365
|
private
|
358
|
-
|
359
366
|
# Mounts a regular expression, returned as a string to ease interpolation,
|
360
367
|
# that will match part by part the given constant.
|
361
368
|
#
|
362
369
|
# const_regexp("Foo::Bar::Baz") # => "Foo(::Bar(::Baz)?)?"
|
363
370
|
# const_regexp("::") # => "::"
|
364
371
|
def const_regexp(camel_cased_word)
|
365
|
-
parts = camel_cased_word.split("::"
|
372
|
+
parts = camel_cased_word.split("::")
|
366
373
|
|
367
374
|
return Regexp.escape(camel_cased_word) if parts.blank?
|
368
375
|
|
369
376
|
last = parts.pop
|
370
377
|
|
371
|
-
parts.reverse
|
378
|
+
parts.reverse!.inject(last) do |acc, part|
|
372
379
|
part.empty? ? acc : "#{part}(::#{acc})?"
|
373
380
|
end
|
374
381
|
end
|
375
382
|
|
376
383
|
# Applies inflection rules for +singularize+ and +pluralize+.
|
377
384
|
#
|
378
|
-
#
|
379
|
-
#
|
380
|
-
|
385
|
+
# If passed an optional +locale+ parameter, the uncountables will be
|
386
|
+
# found for that locale.
|
387
|
+
#
|
388
|
+
# apply_inflections('post', inflections.plurals, :en) # => "posts"
|
389
|
+
# apply_inflections('posts', inflections.singulars, :en) # => "post"
|
390
|
+
def apply_inflections(word, rules, locale = :en)
|
381
391
|
result = word.to_s.dup
|
382
392
|
|
383
|
-
if word.empty? || inflections.uncountables.uncountable?(result)
|
393
|
+
if word.empty? || inflections(locale).uncountables.uncountable?(result)
|
384
394
|
result
|
385
395
|
else
|
386
396
|
rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
|
@@ -1,8 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/string/multibyte"
|
2
4
|
require "active_support/i18n"
|
3
5
|
|
4
6
|
module ActiveSupport
|
5
7
|
module Inflector
|
8
|
+
ALLOWED_ENCODINGS_FOR_TRANSLITERATE = [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030].freeze
|
9
|
+
|
6
10
|
# Replaces non-ASCII characters with an ASCII approximation, or if none
|
7
11
|
# exists, a replacement character which defaults to "?".
|
8
12
|
#
|
@@ -49,46 +53,80 @@ module ActiveSupport
|
|
49
53
|
#
|
50
54
|
# Now you can have different transliterations for each locale:
|
51
55
|
#
|
52
|
-
#
|
53
|
-
# transliterate('Jürgen')
|
56
|
+
# transliterate('Jürgen', locale: :en)
|
54
57
|
# # => "Jurgen"
|
55
58
|
#
|
56
|
-
#
|
57
|
-
# transliterate('Jürgen')
|
59
|
+
# transliterate('Jürgen', locale: :de)
|
58
60
|
# # => "Juergen"
|
59
|
-
|
61
|
+
#
|
62
|
+
# Transliteration is restricted to UTF-8, US-ASCII and GB18030 strings
|
63
|
+
# Other encodings will raise an ArgumentError.
|
64
|
+
def transliterate(string, replacement = "?", locale: nil)
|
65
|
+
string = string.dup if string.frozen?
|
60
66
|
raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
|
67
|
+
raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.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
|
61
75
|
|
62
|
-
|
63
|
-
|
64
|
-
|
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
98
|
# parameterize("Donald E. Knuth") # => "donald-e-knuth"
|
71
|
-
# parameterize("^
|
99
|
+
# parameterize("^très|Jolie-- ") # => "tres-jolie"
|
72
100
|
#
|
73
|
-
# To use a custom separator, override the
|
101
|
+
# To use a custom separator, override the +separator+ argument.
|
74
102
|
#
|
75
|
-
#
|
76
|
-
#
|
103
|
+
# parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
|
104
|
+
# parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
|
77
105
|
#
|
78
|
-
# To preserve the case of the characters in a string, use the
|
106
|
+
# To preserve the case of the characters in a string, use the +preserve_case+ argument.
|
79
107
|
#
|
80
108
|
# parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
|
81
|
-
# parameterize("^
|
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--"
|
82
116
|
#
|
83
|
-
|
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)
|
84
122
|
# Replace accented chars with their ASCII equivalents.
|
85
|
-
parameterized_string = transliterate(string)
|
123
|
+
parameterized_string = transliterate(string, locale: locale)
|
86
124
|
|
87
125
|
# Turn unwanted chars into the separator.
|
88
126
|
parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
|
89
127
|
|
90
128
|
unless separator.nil? || separator.empty?
|
91
|
-
if separator == "-"
|
129
|
+
if separator == "-"
|
92
130
|
re_duplicate_separator = /-{2,}/
|
93
131
|
re_leading_trailing_separator = /^-|-$/i
|
94
132
|
else
|
@@ -99,7 +137,7 @@ module ActiveSupport
|
|
99
137
|
# No more than one of the separator in a row.
|
100
138
|
parameterized_string.gsub!(re_duplicate_separator, separator)
|
101
139
|
# Remove leading/trailing separator.
|
102
|
-
parameterized_string.gsub!(re_leading_trailing_separator, ""
|
140
|
+
parameterized_string.gsub!(re_leading_trailing_separator, "")
|
103
141
|
end
|
104
142
|
|
105
143
|
parameterized_string.downcase! unless preserve_case
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/module/attribute_accessors"
|
2
4
|
require "active_support/core_ext/module/delegation"
|
3
5
|
require "json"
|
@@ -8,8 +10,8 @@ module ActiveSupport
|
|
8
10
|
|
9
11
|
module JSON
|
10
12
|
# matches YAML-formatted dates
|
11
|
-
DATE_REGEX =
|
12
|
-
DATETIME_REGEX =
|
13
|
+
DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/
|
14
|
+
DATETIME_REGEX = /\A(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)\z/
|
13
15
|
|
14
16
|
class << self
|
15
17
|
# Parses a JSON string (JavaScript Object Notation) into a hash.
|
@@ -42,33 +44,32 @@ module ActiveSupport
|
|
42
44
|
end
|
43
45
|
|
44
46
|
private
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
47
|
+
def convert_dates_from(data)
|
48
|
+
case data
|
49
|
+
when nil
|
50
|
+
nil
|
51
|
+
when DATE_REGEX
|
52
|
+
begin
|
53
|
+
Date.parse(data)
|
54
|
+
rescue ArgumentError
|
55
|
+
data
|
56
|
+
end
|
57
|
+
when DATETIME_REGEX
|
58
|
+
begin
|
59
|
+
Time.zone.parse(data)
|
60
|
+
rescue ArgumentError
|
61
|
+
data
|
62
|
+
end
|
63
|
+
when Array
|
64
|
+
data.map! { |d| convert_dates_from(d) }
|
65
|
+
when Hash
|
66
|
+
data.transform_values! do |value|
|
67
|
+
convert_dates_from(value)
|
68
|
+
end
|
69
|
+
else
|
60
70
|
data
|
61
71
|
end
|
62
|
-
when Array
|
63
|
-
data.map! { |d| convert_dates_from(d) }
|
64
|
-
when Hash
|
65
|
-
data.each do |key, value|
|
66
|
-
data[key] = convert_dates_from(value)
|
67
|
-
end
|
68
|
-
else
|
69
|
-
data
|
70
72
|
end
|
71
|
-
end
|
72
73
|
end
|
73
74
|
end
|
74
75
|
end
|