activesupport 4.0.13 → 5.2.5
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 +412 -444
- data/MIT-LICENSE +2 -2
- data/README.rdoc +8 -4
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +14 -12
- data/lib/active_support/benchmarkable.rb +6 -14
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +67 -51
- data/lib/active_support/cache/mem_cache_store.rb +95 -97
- data/lib/active_support/cache/memory_store.rb +28 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +466 -0
- data/lib/active_support/cache/strategy/local_cache.rb +70 -56
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +331 -206
- data/lib/active_support/callbacks.rb +697 -426
- data/lib/active_support/concern.rb +32 -10
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +227 -0
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/core_ext/array/access.rb +39 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -35
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +23 -13
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -5
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -7
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +41 -23
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/class/subclasses.rb +20 -8
- data/lib/active_support/core_ext/class.rb +4 -4
- 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 +21 -9
- data/lib/active_support/core_ext/date/conversions.rb +32 -22
- data/lib/active_support/core_ext/date/zones.rb +5 -34
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +199 -57
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
- 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 +78 -37
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -13
- data/lib/active_support/core_ext/date_time.rb +7 -4
- data/lib/active_support/core_ext/digest/uuid.rb +53 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +113 -29
- 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 +29 -0
- data/lib/active_support/core_ext/hash/conversions.rb +71 -49
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +12 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +50 -38
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +12 -6
- data/lib/active_support/core_ext/hash/transform_values.rb +32 -0
- data/lib/active_support/core_ext/hash.rb +11 -8
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +5 -74
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +6 -4
- data/lib/active_support/core_ext/load_error.rb +5 -21
- data/lib/active_support/core_ext/marshal.rb +13 -10
- 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 -8
- data/lib/active_support/core_ext/module/attribute_accessors.rb +170 -21
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +134 -0
- data/lib/active_support/core_ext/module/delegation.rb +135 -45
- data/lib/active_support/core_ext/module/deprecation.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +9 -25
- data/lib/active_support/core_ext/module/reachable.rb +5 -2
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +14 -10
- 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 +79 -74
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +37 -50
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +70 -19
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
- data/lib/active_support/core_ext/object/duplicable.rb +100 -34
- data/lib/active_support/core_ext/object/inclusion.rb +18 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +227 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +21 -8
- data/lib/active_support/core_ext/object/try.rb +94 -24
- data/lib/active_support/core_ext/object/with_options.rb +45 -5
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/range/compare_range.rb +61 -0
- data/lib/active_support/core_ext/range/conversions.rb +27 -7
- data/lib/active_support/core_ext/range/each.rb +19 -17
- data/lib/active_support/core_ext/range/include_range.rb +2 -22
- 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 +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string/access.rb +41 -39
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +17 -13
- data/lib/active_support/core_ext/string/exclude.rb +5 -3
- data/lib/active_support/core_ext/string/filters.rb +55 -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 +15 -7
- data/lib/active_support/core_ext/string/output_safety.rb +114 -54
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +4 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -1
- 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 +123 -110
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +23 -14
- data/lib/active_support/core_ext/time/zones.rb +42 -26
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/uri.rb +6 -8
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies/autoload.rb +3 -1
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies.rb +196 -166
- data/lib/active_support/deprecation/behaviors.rb +48 -15
- 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 +66 -20
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +14 -11
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/duration.rb +354 -34
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +205 -0
- data/lib/active_support/execution_wrapper.rb +128 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +63 -37
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +158 -35
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +38 -20
- data/lib/active_support/inflections.rb +19 -12
- data/lib/active_support/inflector/inflections.rb +79 -30
- data/lib/active_support/inflector/methods.rb +197 -129
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +21 -25
- data/lib/active_support/json/encoding.rb +84 -292
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +26 -28
- data/lib/active_support/lazy_load_hooks.rb +51 -21
- 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 +13 -10
- data/lib/active_support/logger.rb +54 -3
- data/lib/active_support/logger_silence.rb +12 -7
- data/lib/active_support/logger_thread_safe_level.rb +34 -0
- data/lib/active_support/message_encryptor.rb +173 -50
- data/lib/active_support/message_verifier.rb +159 -22
- data/lib/active_support/messages/metadata.rb +71 -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 +38 -26
- data/lib/active_support/multibyte/unicode.rb +138 -146
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +23 -16
- data/lib/active_support/notifications/instrumenter.rb +29 -8
- data/lib/active_support/notifications.rb +22 -13
- data/lib/active_support/number_helper/number_converter.rb +184 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +29 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +59 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +14 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +54 -0
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +125 -391
- data/lib/active_support/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +31 -5
- data/lib/active_support/per_thread_registry.rb +19 -11
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +16 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +131 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +31 -0
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +54 -17
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +42 -37
- data/lib/active_support/testing/assertions.rb +126 -39
- data/lib/active_support/testing/autorun.rb +5 -3
- data/lib/active_support/testing/constant_lookup.rb +3 -6
- data/lib/active_support/testing/declarative.rb +10 -22
- data/lib/active_support/testing/deprecation.rb +14 -10
- data/lib/active_support/testing/file_fixtures.rb +36 -0
- data/lib/active_support/testing/isolation.rb +55 -86
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +30 -10
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +5 -3
- data/lib/active_support/testing/time_helpers.rb +200 -0
- data/lib/active_support/time.rb +13 -13
- data/lib/active_support/time_with_zone.rb +223 -73
- data/lib/active_support/values/time_zone.rb +261 -126
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +6 -7
- data/lib/active_support/xml_mini/jdom.rb +116 -113
- data/lib/active_support/xml_mini/libxml.rb +17 -16
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +15 -15
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +17 -16
- data/lib/active_support/xml_mini.rb +69 -51
- data/lib/active_support.rb +29 -3
- metadata +84 -54
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
- data/lib/active_support/core_ext/date_time/zones.rb +0 -24
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -79
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
@@ -1,16 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/xml_mini"
|
4
|
+
require "active_support/time"
|
5
|
+
require "active_support/core_ext/object/blank"
|
6
|
+
require "active_support/core_ext/object/to_param"
|
7
|
+
require "active_support/core_ext/object/to_query"
|
8
|
+
require "active_support/core_ext/array/wrap"
|
9
|
+
require "active_support/core_ext/hash/reverse_merge"
|
10
|
+
require "active_support/core_ext/string/inflections"
|
9
11
|
|
10
12
|
class Hash
|
11
13
|
# Returns a string containing an XML representation of its receiver:
|
12
14
|
#
|
13
|
-
# {
|
15
|
+
# { foo: 1, bar: 2 }.to_xml
|
14
16
|
# # =>
|
15
17
|
# # <?xml version="1.0" encoding="UTF-8"?>
|
16
18
|
# # <hash>
|
@@ -31,7 +33,7 @@ class Hash
|
|
31
33
|
# with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The
|
32
34
|
# callable can add nodes by using <tt>options[:builder]</tt>.
|
33
35
|
#
|
34
|
-
#
|
36
|
+
# {foo: lambda { |options, key| options[:builder].b(key) }}.to_xml
|
35
37
|
# # => "<b>foo</b>"
|
36
38
|
#
|
37
39
|
# * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
|
@@ -43,7 +45,10 @@ class Hash
|
|
43
45
|
# end
|
44
46
|
#
|
45
47
|
# { foo: Foo.new }.to_xml(skip_instruct: true)
|
46
|
-
# # =>
|
48
|
+
# # =>
|
49
|
+
# # <hash>
|
50
|
+
# # <bar>fooing!</bar>
|
51
|
+
# # </hash>
|
47
52
|
#
|
48
53
|
# * Otherwise, a node with +key+ as tag is created with a string representation of
|
49
54
|
# +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
|
@@ -52,8 +57,7 @@ class Hash
|
|
52
57
|
#
|
53
58
|
# XML_TYPE_NAMES = {
|
54
59
|
# "Symbol" => "symbol",
|
55
|
-
# "
|
56
|
-
# "Bignum" => "integer",
|
60
|
+
# "Integer" => "integer",
|
57
61
|
# "BigDecimal" => "decimal",
|
58
62
|
# "Float" => "float",
|
59
63
|
# "TrueClass" => "boolean",
|
@@ -69,11 +73,11 @@ class Hash
|
|
69
73
|
# configure your own builder with the <tt>:builder</tt> option. The method also accepts
|
70
74
|
# options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
|
71
75
|
def to_xml(options = {})
|
72
|
-
require
|
76
|
+
require "active_support/builder" unless defined?(Builder)
|
73
77
|
|
74
78
|
options = options.dup
|
75
79
|
options[:indent] ||= 2
|
76
|
-
options[:root] ||=
|
80
|
+
options[:root] ||= "hash"
|
77
81
|
options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
|
78
82
|
|
79
83
|
builder = options[:builder]
|
@@ -102,8 +106,26 @@ class Hash
|
|
102
106
|
# hash = Hash.from_xml(xml)
|
103
107
|
# # => {"hash"=>{"foo"=>1, "bar"=>2}}
|
104
108
|
#
|
105
|
-
# DisallowedType is
|
106
|
-
# <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to
|
109
|
+
# +DisallowedType+ is raised if the XML contains attributes with <tt>type="yaml"</tt> or
|
110
|
+
# <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to
|
111
|
+
# parse this XML.
|
112
|
+
#
|
113
|
+
# Custom +disallowed_types+ can also be passed in the form of an
|
114
|
+
# array.
|
115
|
+
#
|
116
|
+
# xml = <<-XML
|
117
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
118
|
+
# <hash>
|
119
|
+
# <foo type="integer">1</foo>
|
120
|
+
# <bar type="string">"David"</bar>
|
121
|
+
# </hash>
|
122
|
+
# XML
|
123
|
+
#
|
124
|
+
# hash = Hash.from_xml(xml, ['integer'])
|
125
|
+
# # => ActiveSupport::XMLConverter::DisallowedType: Disallowed type attribute: "integer"
|
126
|
+
#
|
127
|
+
# Note that passing custom disallowed types will override the default types,
|
128
|
+
# which are Symbol and YAML.
|
107
129
|
def from_xml(xml, disallowed_types = nil)
|
108
130
|
ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
|
109
131
|
end
|
@@ -117,6 +139,8 @@ end
|
|
117
139
|
|
118
140
|
module ActiveSupport
|
119
141
|
class XMLConverter # :nodoc:
|
142
|
+
# Raised if the XML contains attributes with type="yaml" or
|
143
|
+
# type="symbol". Read Hash#from_xml for more details.
|
120
144
|
class DisallowedType < StandardError
|
121
145
|
def initialize(type)
|
122
146
|
super "Disallowed type attribute: #{type.inspect}"
|
@@ -137,36 +161,36 @@ module ActiveSupport
|
|
137
161
|
private
|
138
162
|
def normalize_keys(params)
|
139
163
|
case params
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
164
|
+
when Hash
|
165
|
+
Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
|
166
|
+
when Array
|
167
|
+
params.map { |v| normalize_keys(v) }
|
168
|
+
else
|
169
|
+
params
|
146
170
|
end
|
147
171
|
end
|
148
172
|
|
149
173
|
def deep_to_h(value)
|
150
174
|
case value
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
175
|
+
when Hash
|
176
|
+
process_hash(value)
|
177
|
+
when Array
|
178
|
+
process_array(value)
|
179
|
+
when String
|
180
|
+
value
|
181
|
+
else
|
182
|
+
raise "can't typecast #{value.class.name} - #{value.inspect}"
|
159
183
|
end
|
160
184
|
end
|
161
185
|
|
162
186
|
def process_hash(value)
|
163
|
-
if value.include?(
|
164
|
-
raise DisallowedType, value[
|
187
|
+
if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
|
188
|
+
raise DisallowedType, value["type"]
|
165
189
|
end
|
166
190
|
|
167
191
|
if become_array?(value)
|
168
|
-
_, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) })
|
169
|
-
if entries.nil? || value[
|
192
|
+
_, entries = Array.wrap(value.detect { |k, v| not v.is_a?(String) })
|
193
|
+
if entries.nil? || value["__content__"].try(:empty?)
|
170
194
|
[]
|
171
195
|
else
|
172
196
|
case entries
|
@@ -182,28 +206,28 @@ module ActiveSupport
|
|
182
206
|
process_content(value)
|
183
207
|
|
184
208
|
elsif become_empty_string?(value)
|
185
|
-
|
209
|
+
""
|
186
210
|
elsif become_hash?(value)
|
187
|
-
xml_value = Hash[value.map { |k,v| [k, deep_to_h(v)] }]
|
211
|
+
xml_value = Hash[value.map { |k, v| [k, deep_to_h(v)] }]
|
188
212
|
|
189
213
|
# Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
|
190
214
|
# how multipart uploaded files from HTML appear
|
191
|
-
xml_value[
|
215
|
+
xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
|
192
216
|
end
|
193
217
|
end
|
194
218
|
|
195
219
|
def become_content?(value)
|
196
|
-
value[
|
220
|
+
value["type"] == "file" || (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
|
197
221
|
end
|
198
222
|
|
199
223
|
def become_array?(value)
|
200
|
-
value[
|
224
|
+
value["type"] == "array"
|
201
225
|
end
|
202
226
|
|
203
227
|
def become_empty_string?(value)
|
204
|
-
# {"string" => true}
|
228
|
+
# { "string" => true }
|
205
229
|
# No tests fail when the second term is removed.
|
206
|
-
value[
|
230
|
+
value["type"] == "string" && value["nil"] != "true"
|
207
231
|
end
|
208
232
|
|
209
233
|
def become_hash?(value)
|
@@ -212,19 +236,19 @@ module ActiveSupport
|
|
212
236
|
|
213
237
|
def nothing?(value)
|
214
238
|
# blank or nil parsed values are represented by nil
|
215
|
-
value.blank? || value[
|
239
|
+
value.blank? || value["nil"] == "true"
|
216
240
|
end
|
217
241
|
|
218
242
|
def garbage?(value)
|
219
243
|
# If the type is the only element which makes it then
|
220
244
|
# this still makes the value nil, except if type is
|
221
|
-
#
|
222
|
-
value[
|
245
|
+
# an XML node(where type['value'] is a Hash)
|
246
|
+
value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
|
223
247
|
end
|
224
248
|
|
225
249
|
def process_content(value)
|
226
|
-
content = value[
|
227
|
-
if parser = ActiveSupport::XmlMini::PARSING[value[
|
250
|
+
content = value["__content__"]
|
251
|
+
if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
|
228
252
|
parser.arity == 1 ? parser.call(content) : parser.call(content, value)
|
229
253
|
else
|
230
254
|
content
|
@@ -235,7 +259,5 @@ module ActiveSupport
|
|
235
259
|
value.map! { |i| deep_to_h(i) }
|
236
260
|
value.length > 1 ? value : value.first
|
237
261
|
end
|
238
|
-
|
239
262
|
end
|
240
263
|
end
|
241
|
-
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
3
5
|
#
|
4
6
|
# h1 = { a: true, b: { c: [1, 2, 3] } }
|
5
7
|
# h2 = { a: false, b: { x: [3, 4, 5] } }
|
6
8
|
#
|
7
|
-
# h1.deep_merge(h2)
|
9
|
+
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
8
10
|
#
|
9
11
|
# Like with Hash#merge in the standard library, a block can be provided
|
10
12
|
# to merge values:
|
@@ -19,20 +21,14 @@ class Hash
|
|
19
21
|
|
20
22
|
# Same as +deep_merge+, but modifies +self+.
|
21
23
|
def deep_merge!(other_hash, &block)
|
22
|
-
other_hash
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
merge!(other_hash) do |key, this_val, other_val|
|
25
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
26
|
+
this_val.deep_merge(other_val, &block)
|
27
|
+
elsif block_given?
|
28
|
+
block.call(key, this_val, other_val)
|
27
29
|
else
|
28
|
-
|
29
|
-
block.call(current_key, this_value, other_value)
|
30
|
-
else
|
31
|
-
other_value
|
32
|
-
end
|
30
|
+
other_val
|
33
31
|
end
|
34
32
|
end
|
35
|
-
|
36
|
-
self
|
37
33
|
end
|
38
34
|
end
|
@@ -1,13 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
|
-
#
|
3
|
-
#
|
4
|
+
# Returns a hash that includes everything except given keys.
|
5
|
+
# hash = { a: true, b: false, c: nil }
|
6
|
+
# hash.except(:c) # => { a: true, b: false }
|
7
|
+
# hash.except(:a, :b) # => { c: nil }
|
8
|
+
# hash # => { a: true, b: false, c: nil }
|
4
9
|
#
|
10
|
+
# This is useful for limiting a set of parameters to everything but a few known toggles:
|
5
11
|
# @person.update(params[:person].except(:admin))
|
6
12
|
def except(*keys)
|
7
13
|
dup.except!(*keys)
|
8
14
|
end
|
9
15
|
|
10
|
-
#
|
16
|
+
# Removes the given keys from hash and returns it.
|
17
|
+
# hash = { a: true, b: false, c: nil }
|
18
|
+
# hash.except!(:c) # => { a: true, b: false }
|
19
|
+
# hash # => { a: true, b: false }
|
11
20
|
def except!(*keys)
|
12
21
|
keys.each { |key| delete(key) }
|
13
22
|
self
|
@@ -1,12 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "active_support/hash_with_indifferent_access"
|
4
4
|
|
5
|
+
class Hash
|
5
6
|
# Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
|
6
7
|
#
|
7
8
|
# { a: 1 }.with_indifferent_access['a'] # => 1
|
8
9
|
def with_indifferent_access
|
9
|
-
ActiveSupport::HashWithIndifferentAccess.
|
10
|
+
ActiveSupport::HashWithIndifferentAccess.new(self)
|
10
11
|
end
|
11
12
|
|
12
13
|
# Called when object is nested under an object that receives
|
@@ -18,5 +19,6 @@ class Hash
|
|
18
19
|
#
|
19
20
|
# b = { b: 1 }
|
20
21
|
# { a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
|
22
|
+
# # => {"b"=>1}
|
21
23
|
alias nested_under_indifferent_access with_indifferent_access
|
22
24
|
end
|
@@ -1,131 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
|
-
#
|
4
|
+
# Returns a new hash with all keys converted using the +block+ operation.
|
3
5
|
#
|
4
6
|
# hash = { name: 'Rob', age: '28' }
|
5
7
|
#
|
6
|
-
# hash.transform_keys{ |key| key.to_s.upcase }
|
7
|
-
#
|
8
|
+
# hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
|
9
|
+
#
|
10
|
+
# If you do not provide a +block+, it will return an Enumerator
|
11
|
+
# for chaining with other methods:
|
12
|
+
#
|
13
|
+
# hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
|
8
14
|
def transform_keys
|
15
|
+
return enum_for(:transform_keys) { size } unless block_given?
|
9
16
|
result = {}
|
10
17
|
each_key do |key|
|
11
18
|
result[yield(key)] = self[key]
|
12
19
|
end
|
13
20
|
result
|
14
|
-
end
|
21
|
+
end unless method_defined? :transform_keys
|
15
22
|
|
16
|
-
# Destructively
|
17
|
-
# Same as transform_keys but modifies +self+.
|
23
|
+
# Destructively converts all keys using the +block+ operations.
|
24
|
+
# Same as +transform_keys+ but modifies +self+.
|
18
25
|
def transform_keys!
|
26
|
+
return enum_for(:transform_keys!) { size } unless block_given?
|
19
27
|
keys.each do |key|
|
20
28
|
self[yield(key)] = delete(key)
|
21
29
|
end
|
22
30
|
self
|
23
|
-
end
|
31
|
+
end unless method_defined? :transform_keys!
|
24
32
|
|
25
|
-
#
|
33
|
+
# Returns a new hash with all keys converted to strings.
|
26
34
|
#
|
27
35
|
# hash = { name: 'Rob', age: '28' }
|
28
36
|
#
|
29
37
|
# hash.stringify_keys
|
30
|
-
#
|
38
|
+
# # => {"name"=>"Rob", "age"=>"28"}
|
31
39
|
def stringify_keys
|
32
|
-
transform_keys
|
40
|
+
transform_keys(&:to_s)
|
33
41
|
end
|
34
42
|
|
35
|
-
# Destructively
|
43
|
+
# Destructively converts all keys to strings. Same as
|
36
44
|
# +stringify_keys+, but modifies +self+.
|
37
45
|
def stringify_keys!
|
38
|
-
transform_keys!
|
46
|
+
transform_keys!(&:to_s)
|
39
47
|
end
|
40
48
|
|
41
|
-
#
|
49
|
+
# Returns a new hash with all keys converted to symbols, as long as
|
42
50
|
# they respond to +to_sym+.
|
43
51
|
#
|
44
52
|
# hash = { 'name' => 'Rob', 'age' => '28' }
|
45
53
|
#
|
46
54
|
# hash.symbolize_keys
|
47
|
-
#
|
55
|
+
# # => {:name=>"Rob", :age=>"28"}
|
48
56
|
def symbolize_keys
|
49
|
-
transform_keys{ |key| key.to_sym rescue key }
|
57
|
+
transform_keys { |key| key.to_sym rescue key }
|
50
58
|
end
|
51
59
|
alias_method :to_options, :symbolize_keys
|
52
60
|
|
53
|
-
# Destructively
|
61
|
+
# Destructively converts all keys to symbols, as long as they respond
|
54
62
|
# to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
|
55
63
|
def symbolize_keys!
|
56
|
-
transform_keys!{ |key| key.to_sym rescue key }
|
64
|
+
transform_keys! { |key| key.to_sym rescue key }
|
57
65
|
end
|
58
66
|
alias_method :to_options!, :symbolize_keys!
|
59
67
|
|
60
|
-
#
|
61
|
-
# on a mismatch.
|
62
|
-
#
|
68
|
+
# Validates all keys in a hash match <tt>*valid_keys</tt>, raising
|
69
|
+
# +ArgumentError+ on a mismatch.
|
70
|
+
#
|
71
|
+
# Note that keys are treated differently than HashWithIndifferentAccess,
|
72
|
+
# meaning that string and symbol keys will not match.
|
63
73
|
#
|
64
|
-
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
|
65
|
-
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
|
74
|
+
# { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
|
75
|
+
# { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
|
66
76
|
# { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
67
77
|
def assert_valid_keys(*valid_keys)
|
68
78
|
valid_keys.flatten!
|
69
79
|
each_key do |k|
|
70
|
-
|
80
|
+
unless valid_keys.include?(k)
|
81
|
+
raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
|
82
|
+
end
|
71
83
|
end
|
72
84
|
end
|
73
85
|
|
74
|
-
#
|
86
|
+
# Returns a new hash with all keys converted by the block operation.
|
75
87
|
# This includes the keys from the root hash and from all
|
76
88
|
# nested hashes and arrays.
|
77
89
|
#
|
78
90
|
# hash = { person: { name: 'Rob', age: '28' } }
|
79
91
|
#
|
80
92
|
# hash.deep_transform_keys{ |key| key.to_s.upcase }
|
81
|
-
# # => {
|
93
|
+
# # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
|
82
94
|
def deep_transform_keys(&block)
|
83
95
|
_deep_transform_keys_in_object(self, &block)
|
84
96
|
end
|
85
97
|
|
86
|
-
# Destructively
|
98
|
+
# Destructively converts all keys by using the block operation.
|
87
99
|
# This includes the keys from the root hash and from all
|
88
100
|
# nested hashes and arrays.
|
89
101
|
def deep_transform_keys!(&block)
|
90
102
|
_deep_transform_keys_in_object!(self, &block)
|
91
103
|
end
|
92
104
|
|
93
|
-
#
|
105
|
+
# Returns a new hash with all keys converted to strings.
|
94
106
|
# This includes the keys from the root hash and from all
|
95
107
|
# nested hashes and arrays.
|
96
108
|
#
|
97
109
|
# hash = { person: { name: 'Rob', age: '28' } }
|
98
110
|
#
|
99
111
|
# hash.deep_stringify_keys
|
100
|
-
# # => {
|
112
|
+
# # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
|
101
113
|
def deep_stringify_keys
|
102
|
-
deep_transform_keys
|
114
|
+
deep_transform_keys(&:to_s)
|
103
115
|
end
|
104
116
|
|
105
|
-
# Destructively
|
117
|
+
# Destructively converts all keys to strings.
|
106
118
|
# This includes the keys from the root hash and from all
|
107
119
|
# nested hashes and arrays.
|
108
120
|
def deep_stringify_keys!
|
109
|
-
deep_transform_keys!
|
121
|
+
deep_transform_keys!(&:to_s)
|
110
122
|
end
|
111
123
|
|
112
|
-
#
|
124
|
+
# Returns a new hash with all keys converted to symbols, as long as
|
113
125
|
# they respond to +to_sym+. This includes the keys from the root hash
|
114
126
|
# and from all nested hashes and arrays.
|
115
127
|
#
|
116
128
|
# hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
|
117
129
|
#
|
118
130
|
# hash.deep_symbolize_keys
|
119
|
-
# # => {
|
131
|
+
# # => {:person=>{:name=>"Rob", :age=>"28"}}
|
120
132
|
def deep_symbolize_keys
|
121
|
-
deep_transform_keys{ |key| key.to_sym rescue key }
|
133
|
+
deep_transform_keys { |key| key.to_sym rescue key }
|
122
134
|
end
|
123
135
|
|
124
|
-
# Destructively
|
136
|
+
# Destructively converts all keys to symbols, as long as they respond
|
125
137
|
# to +to_sym+. This includes the keys from the root hash and from all
|
126
138
|
# nested hashes and arrays.
|
127
139
|
def deep_symbolize_keys!
|
128
|
-
deep_transform_keys!{ |key| key.to_sym rescue key }
|
140
|
+
deep_transform_keys! { |key| key.to_sym rescue key }
|
129
141
|
end
|
130
142
|
|
131
143
|
private
|
@@ -137,7 +149,7 @@ class Hash
|
|
137
149
|
result[yield(key)] = _deep_transform_keys_in_object(value, &block)
|
138
150
|
end
|
139
151
|
when Array
|
140
|
-
object.map {|e| _deep_transform_keys_in_object(e, &block) }
|
152
|
+
object.map { |e| _deep_transform_keys_in_object(e, &block) }
|
141
153
|
else
|
142
154
|
object
|
143
155
|
end
|
@@ -152,7 +164,7 @@ class Hash
|
|
152
164
|
end
|
153
165
|
object
|
154
166
|
when Array
|
155
|
-
object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
|
167
|
+
object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
|
156
168
|
else
|
157
169
|
object
|
158
170
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Merges the caller into +other_hash+. For example,
|
3
5
|
#
|
@@ -12,11 +14,12 @@ class Hash
|
|
12
14
|
def reverse_merge(other_hash)
|
13
15
|
other_hash.merge(self)
|
14
16
|
end
|
17
|
+
alias_method :with_defaults, :reverse_merge
|
15
18
|
|
16
19
|
# Destructive +reverse_merge+.
|
17
20
|
def reverse_merge!(other_hash)
|
18
|
-
|
19
|
-
merge!( other_hash ){|key,left,right| left }
|
21
|
+
replace(reverse_merge(other_hash))
|
20
22
|
end
|
21
23
|
alias_method :reverse_update, :reverse_merge!
|
24
|
+
alias_method :with_defaults!, :reverse_merge!
|
22
25
|
end
|
@@ -1,6 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
|
-
#
|
3
|
-
#
|
4
|
+
# Slices a hash to include only the given keys. Returns a hash containing
|
5
|
+
# the given keys.
|
6
|
+
#
|
7
|
+
# { a: 1, b: 2, c: 3, d: 4 }.slice(:a, :b)
|
8
|
+
# # => {:a=>1, :b=>2}
|
9
|
+
#
|
10
|
+
# This is useful for limiting an options hash to valid keys before
|
11
|
+
# passing to a method:
|
4
12
|
#
|
5
13
|
# def search(criteria = {})
|
6
14
|
# criteria.assert_valid_keys(:mass, :velocity, :time)
|
@@ -13,9 +21,8 @@ class Hash
|
|
13
21
|
# valid_keys = [:mass, :velocity, :time]
|
14
22
|
# search(options.slice(*valid_keys))
|
15
23
|
def slice(*keys)
|
16
|
-
keys.
|
17
|
-
|
18
|
-
end
|
24
|
+
keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
|
25
|
+
end unless method_defined?(:slice)
|
19
26
|
|
20
27
|
# Replaces the hash with only the given keys.
|
21
28
|
# Returns a hash containing the removed key/value pairs.
|
@@ -23,7 +30,6 @@ class Hash
|
|
23
30
|
# { a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b)
|
24
31
|
# # => {:c=>3, :d=>4}
|
25
32
|
def slice!(*keys)
|
26
|
-
keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
|
27
33
|
omit = slice(*self.keys - keys)
|
28
34
|
hash = slice(*keys)
|
29
35
|
hash.default = default
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# Returns a new hash with the results of running +block+ once for every value.
|
5
|
+
# The keys are unchanged.
|
6
|
+
#
|
7
|
+
# { a: 1, b: 2, c: 3 }.transform_values { |x| x * 2 } # => { a: 2, b: 4, c: 6 }
|
8
|
+
#
|
9
|
+
# If you do not provide a +block+, it will return an Enumerator
|
10
|
+
# for chaining with other methods:
|
11
|
+
#
|
12
|
+
# { a: 1, b: 2 }.transform_values.with_index { |v, i| [v, i].join.to_i } # => { a: 10, b: 21 }
|
13
|
+
def transform_values
|
14
|
+
return enum_for(:transform_values) { size } unless block_given?
|
15
|
+
return {} if empty?
|
16
|
+
result = self.class.new
|
17
|
+
each do |key, value|
|
18
|
+
result[key] = yield(value)
|
19
|
+
end
|
20
|
+
result
|
21
|
+
end unless method_defined? :transform_values
|
22
|
+
|
23
|
+
# Destructively converts all values using the +block+ operations.
|
24
|
+
# Same as +transform_values+ but modifies +self+.
|
25
|
+
def transform_values!
|
26
|
+
return enum_for(:transform_values!) { size } unless block_given?
|
27
|
+
each do |key, value|
|
28
|
+
self[key] = yield(value)
|
29
|
+
end
|
30
|
+
end unless method_defined? :transform_values!
|
31
|
+
# TODO: Remove this file when supporting only Ruby 2.4+.
|
32
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/compact"
|
4
|
+
require "active_support/core_ext/hash/conversions"
|
5
|
+
require "active_support/core_ext/hash/deep_merge"
|
6
|
+
require "active_support/core_ext/hash/except"
|
7
|
+
require "active_support/core_ext/hash/indifferent_access"
|
8
|
+
require "active_support/core_ext/hash/keys"
|
9
|
+
require "active_support/core_ext/hash/reverse_merge"
|
10
|
+
require "active_support/core_ext/hash/slice"
|
11
|
+
require "active_support/core_ext/hash/transform_values"
|