hashie 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +56 -0
- data/CONTRIBUTING.md +38 -1
- data/README.md +816 -181
- data/Rakefile +29 -1
- data/UPGRADING.md +18 -0
- data/hashie.gemspec +8 -7
- data/lib/hashie/array.rb +15 -12
- data/lib/hashie/clash.rb +59 -4
- data/lib/hashie/dash.rb +144 -16
- data/lib/hashie/extensions/active_support/core_ext/hash.rb +38 -0
- data/lib/hashie/extensions/array/pretty_inspect.rb +20 -0
- data/lib/hashie/extensions/block_access.rb +71 -0
- data/lib/hashie/extensions/coercion.rb +180 -19
- data/lib/hashie/extensions/dash/coercion.rb +34 -3
- data/lib/hashie/extensions/dash/indifferent_access.rb +83 -5
- data/lib/hashie/extensions/dash/lazy.rb +170 -0
- data/lib/hashie/extensions/dash/predefined_values.rb +69 -9
- data/lib/hashie/extensions/dash/property_translation.rb +134 -16
- data/lib/hashie/extensions/deep_fetch.rb +21 -9
- data/lib/hashie/extensions/deep_find.rb +20 -0
- data/lib/hashie/extensions/deep_grep.rb +69 -0
- data/lib/hashie/extensions/deep_locate.rb +15 -28
- data/lib/hashie/extensions/deep_merge.rb +16 -0
- data/lib/hashie/extensions/deep_merge_initializer.rb +42 -0
- data/lib/hashie/extensions/ignore_undeclared.rb +21 -3
- data/lib/hashie/extensions/indifferent_access.rb +100 -14
- data/lib/hashie/extensions/kernel_coercion.rb +58 -0
- data/lib/hashie/extensions/key_conflict_warning.rb +39 -4
- data/lib/hashie/extensions/key_conversion.rb +9 -0
- data/lib/hashie/extensions/mash/define_accessors.rb +71 -8
- data/lib/hashie/extensions/mash/keep_original_keys.rb +13 -9
- data/lib/hashie/extensions/mash/permissive_respond_to.rb +2 -0
- data/lib/hashie/extensions/mash/required_keys.rb +111 -0
- data/lib/hashie/extensions/mash/safe_assignment.rb +22 -4
- data/lib/hashie/extensions/mash/strict_key_access.rb +65 -0
- data/lib/hashie/extensions/mash/symbolize_keys.rb +6 -2
- data/lib/hashie/extensions/mash/transform_keys.rb +86 -0
- data/lib/hashie/extensions/mash/underscore_keys.rb +32 -0
- data/lib/hashie/extensions/merge_initializer.rb +9 -0
- data/lib/hashie/extensions/method_access.rb +93 -7
- data/lib/hashie/extensions/parsers/yaml_erb_parser.rb +28 -35
- data/lib/hashie/extensions/parsers/yaml_parser.rb +81 -0
- data/lib/hashie/extensions/persistable.rb +137 -0
- data/lib/hashie/extensions/pretty_inspect.rb +14 -0
- data/lib/hashie/extensions/ruby_version.rb +18 -1
- data/lib/hashie/extensions/ruby_version_check.rb +17 -0
- data/lib/hashie/extensions/strict_key_access.rb +59 -5
- data/lib/hashie/extensions/stringify_keys.rb +72 -17
- data/lib/hashie/extensions/symbolize_keys.rb +72 -16
- data/lib/hashie/hash.rb +16 -0
- data/lib/hashie/logger.rb +18 -1
- data/lib/hashie/mash.rb +293 -62
- data/lib/hashie/railtie.rb +27 -1
- data/lib/hashie/rash.rb +64 -4
- data/lib/hashie/trash.rb +8 -0
- data/lib/hashie/utils.rb +17 -6
- data/lib/hashie/version.rb +3 -1
- data/lib/hashie.rb +45 -0
- metadata +15 -17
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Hashie
|
|
2
4
|
module Extensions
|
|
3
5
|
# SRP: This extension will fail an error whenever a key is accessed
|
|
@@ -19,11 +21,21 @@ module Hashie
|
|
|
19
21
|
# NOTE: For googlers coming from Python to Ruby, this extension makes a Hash
|
|
20
22
|
# behave more like a "Dictionary".
|
|
21
23
|
#
|
|
24
|
+
# @example Raise on missing keys
|
|
25
|
+
# hash = { name: 'Ada' }.extend(Hashie::Extensions::StrictKeyAccess)
|
|
26
|
+
# hash[:name] # => 'Ada'
|
|
27
|
+
# expect { hash[:missing] }.to raise_error(KeyError)
|
|
22
28
|
module StrictKeyAccess
|
|
29
|
+
# @example Explain why defaults are unsupported
|
|
30
|
+
# error = Hashie::Extensions::StrictKeyAccess::DefaultError.new
|
|
31
|
+
# error.message # => 'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
|
23
32
|
class DefaultError < StandardError
|
|
33
|
+
# @example Construct a default-access error
|
|
34
|
+
# error = Hashie::Extensions::StrictKeyAccess::DefaultError.new
|
|
35
|
+
# error.message # => 'Setting or using a default with Hashie::Extensions::StrictKeyAccess does not make sense'
|
|
24
36
|
def initialize
|
|
25
|
-
super('Setting or using a default with Hashie::Extensions::StrictKeyAccess'\
|
|
26
|
-
'
|
|
37
|
+
super('Setting or using a default with Hashie::Extensions::StrictKeyAccess ' \
|
|
38
|
+
'does not make sense'
|
|
27
39
|
)
|
|
28
40
|
end
|
|
29
41
|
end
|
|
@@ -45,31 +57,73 @@ module Hashie
|
|
|
45
57
|
# >> a["noes"]
|
|
46
58
|
# KeyError: key not found: "noes"
|
|
47
59
|
#
|
|
60
|
+
# @example Fetch an existing value without a default fallback
|
|
61
|
+
# hash = { name: 'Ada' }.extend(Hashie::Extensions::StrictKeyAccess)
|
|
62
|
+
# hash[:name] # => 'Ada'
|
|
63
|
+
# expect { hash[:missing] }.to raise_error(KeyError)
|
|
48
64
|
def [](key)
|
|
49
65
|
fetch(key)
|
|
50
66
|
end
|
|
51
67
|
|
|
68
|
+
# @example Reject reading the default value
|
|
69
|
+
# hash = {}.extend(Hashie::Extensions::StrictKeyAccess)
|
|
70
|
+
# error_class = begin
|
|
71
|
+
# hash.default
|
|
72
|
+
# rescue Hashie::Extensions::StrictKeyAccess::DefaultError => error
|
|
73
|
+
# error.class
|
|
74
|
+
# end
|
|
75
|
+
# error_class # => Hashie::Extensions::StrictKeyAccess::DefaultError
|
|
52
76
|
def default(_ = nil)
|
|
53
77
|
raise DefaultError
|
|
54
78
|
end
|
|
55
79
|
|
|
80
|
+
# @example Reject assigning a default value
|
|
81
|
+
# hash = {}.extend(Hashie::Extensions::StrictKeyAccess)
|
|
82
|
+
# rejected = begin
|
|
83
|
+
# hash.default = 'unknown'
|
|
84
|
+
# false
|
|
85
|
+
# rescue Hashie::Extensions::StrictKeyAccess::DefaultError
|
|
86
|
+
# true
|
|
87
|
+
# end
|
|
88
|
+
# rejected # => true
|
|
56
89
|
def default=(_)
|
|
57
90
|
raise DefaultError
|
|
58
91
|
end
|
|
59
92
|
|
|
93
|
+
# @example Reject reading a default proc
|
|
94
|
+
# hash = {}.extend(Hashie::Extensions::StrictKeyAccess)
|
|
95
|
+
# rejected = begin
|
|
96
|
+
# hash.default_proc
|
|
97
|
+
# false
|
|
98
|
+
# rescue Hashie::Extensions::StrictKeyAccess::DefaultError
|
|
99
|
+
# true
|
|
100
|
+
# end
|
|
101
|
+
# rejected # => true
|
|
60
102
|
def default_proc
|
|
61
103
|
raise DefaultError
|
|
62
104
|
end
|
|
63
105
|
|
|
106
|
+
# @example Reject assigning a default proc
|
|
107
|
+
# hash = {}.extend(Hashie::Extensions::StrictKeyAccess)
|
|
108
|
+
# rejected = begin
|
|
109
|
+
# hash.default_proc = ->(_hash, _key) { 'unknown' }
|
|
110
|
+
# false
|
|
111
|
+
# rescue Hashie::Extensions::StrictKeyAccess::DefaultError
|
|
112
|
+
# true
|
|
113
|
+
# end
|
|
114
|
+
# rejected # => true
|
|
64
115
|
def default_proc=(_)
|
|
65
116
|
raise DefaultError
|
|
66
117
|
end
|
|
67
118
|
|
|
119
|
+
# @example Find an existing key and reject missing values
|
|
120
|
+
# hash = { name: 'Ada', nil => false }.extend(Hashie::Extensions::StrictKeyAccess)
|
|
121
|
+
# hash.key('Ada') # => :name
|
|
122
|
+
# hash.key(false) # => nil
|
|
123
|
+
# expect { hash.key('Grace') }.to raise_error(KeyError)
|
|
68
124
|
def key(value)
|
|
69
125
|
super.tap do |result|
|
|
70
|
-
if result.nil? && (!key?(result) || self[result] != value)
|
|
71
|
-
raise KeyError, "key not found with value of #{value.inspect}"
|
|
72
|
-
end
|
|
126
|
+
raise KeyError, "no key found for value `#{value.inspect}`" if result.nil? && (!key?(result) || self[result] != value)
|
|
73
127
|
end
|
|
74
128
|
end
|
|
75
129
|
end
|
|
@@ -1,31 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Hashie
|
|
2
4
|
module Extensions
|
|
5
|
+
# Extends a Hash with the ability to convert its keys to strings.
|
|
6
|
+
#
|
|
7
|
+
# @example Extend a pre-existing Hash object
|
|
8
|
+
# hash = { test: 'value' }
|
|
9
|
+
# hash.extend(Hashie::Extensions::StringifyKeys)
|
|
10
|
+
# hash.stringify_keys!
|
|
11
|
+
# hash # => { 'test' => 'value' }
|
|
12
|
+
#
|
|
13
|
+
# @example Create a Hash class with this capability
|
|
14
|
+
# class StringifyingHash < Hash
|
|
15
|
+
# include Hashie::Extensions::StringifyKeys
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# hash = StringifyingHash.new
|
|
19
|
+
# hash[:test] = 'value'
|
|
20
|
+
# hash.stringify_keys!
|
|
21
|
+
# hash # => { 'test' => 'value' }
|
|
22
|
+
#
|
|
23
|
+
# @example Use the module function to stringify keys in a hash
|
|
24
|
+
# hash = { test: 'value' }
|
|
25
|
+
# Hashie::Extensions::StringifyKeys.stringify_keys!(hash)
|
|
26
|
+
# hash # => { 'test' => 'value' }
|
|
3
27
|
module StringifyKeys
|
|
4
|
-
#
|
|
28
|
+
# Converts all keys in the hash and nested hashes and arrays to strings.
|
|
5
29
|
#
|
|
6
|
-
# @example
|
|
7
|
-
# test = {:
|
|
30
|
+
# @example Convert keys in place
|
|
31
|
+
# test = { abc: [{ def: 'value' }] }
|
|
32
|
+
# test.extend(Hashie::Extensions::StringifyKeys)
|
|
8
33
|
# test.stringify_keys!
|
|
9
|
-
# test # => {'abc' => 'def'}
|
|
34
|
+
# test # => { 'abc' => [{ 'def' => 'value' }] }
|
|
35
|
+
#
|
|
36
|
+
# @api public
|
|
37
|
+
# @return [Hash] the receiver with its keys converted to strings
|
|
10
38
|
def stringify_keys!
|
|
11
39
|
StringifyKeys.stringify_keys!(self)
|
|
12
40
|
self
|
|
13
41
|
end
|
|
14
42
|
|
|
15
|
-
#
|
|
16
|
-
#
|
|
43
|
+
# Returns a shallow copy with all keys recursively converted to strings.
|
|
44
|
+
# Nested hashes and arrays are shared with the original and are modified.
|
|
45
|
+
#
|
|
46
|
+
# @example Copy a flat hash without modifying the original
|
|
47
|
+
# test = { abc: 'def' }
|
|
48
|
+
# test.extend(Hashie::Extensions::StringifyKeys)
|
|
49
|
+
# test.stringify_keys # => { 'abc' => 'def' }
|
|
50
|
+
# test # => { abc: 'def' }
|
|
51
|
+
#
|
|
52
|
+
# @example Nested values are shared, not deep copied
|
|
53
|
+
# test = { abc: [{ def: 'value' }] }
|
|
54
|
+
# test.extend(Hashie::Extensions::StringifyKeys)
|
|
55
|
+
# test.stringify_keys # => { 'abc' => [{ 'def' => 'value' }] }
|
|
56
|
+
# test # => { abc: [{ 'def' => 'value' }] }
|
|
57
|
+
#
|
|
58
|
+
# @api public
|
|
59
|
+
# @return [Hash] a shallow copy with stringified keys
|
|
17
60
|
def stringify_keys
|
|
18
61
|
StringifyKeys.stringify_keys(self)
|
|
19
62
|
end
|
|
20
63
|
|
|
64
|
+
# @example Add recursive conversion functions to an object
|
|
65
|
+
# converter = Object.new.extend(Hashie::Extensions::StringifyKeys::ClassMethods)
|
|
66
|
+
# converter.stringify_keys(user: { name: 'Ada' }) # => { 'user' => { 'name' => 'Ada' } }
|
|
21
67
|
module ClassMethods
|
|
22
68
|
# Stringify all keys recursively within nested
|
|
23
69
|
# hashes and arrays.
|
|
24
70
|
# @api private
|
|
25
71
|
def stringify_keys_recursively!(object)
|
|
26
72
|
case object
|
|
27
|
-
when self.class
|
|
28
|
-
stringify_keys!(object)
|
|
29
73
|
when ::Array
|
|
30
74
|
object.each do |i|
|
|
31
75
|
stringify_keys_recursively!(i)
|
|
@@ -35,13 +79,16 @@ module Hashie
|
|
|
35
79
|
end
|
|
36
80
|
end
|
|
37
81
|
|
|
38
|
-
#
|
|
82
|
+
# Converts all keys in a hash recursively to strings, in place.
|
|
83
|
+
#
|
|
84
|
+
# @example Convert keys through Hashie's module function
|
|
85
|
+
# test = { abc: 'def' }
|
|
86
|
+
# Hashie.stringify_keys!(test)
|
|
87
|
+
# test # => { 'abc' => 'def' }
|
|
39
88
|
#
|
|
40
|
-
# @
|
|
41
|
-
# @
|
|
42
|
-
#
|
|
43
|
-
# test.stringify_keys!
|
|
44
|
-
# test # => {'abc' => 'def'}
|
|
89
|
+
# @api public
|
|
90
|
+
# @param [Hash] hash
|
|
91
|
+
# @return [Hash] the passed hash with stringified keys
|
|
45
92
|
def stringify_keys!(hash)
|
|
46
93
|
hash.extend(Hashie::Extensions::StringifyKeys) unless hash.respond_to?(:stringify_keys!)
|
|
47
94
|
hash.keys.each do |k| # rubocop:disable Performance/HashEachMethods
|
|
@@ -51,9 +98,17 @@ module Hashie
|
|
|
51
98
|
hash
|
|
52
99
|
end
|
|
53
100
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
101
|
+
# Returns a shallow copy of a hash with recursively stringified keys.
|
|
102
|
+
# Nested hashes and arrays are shared with the original and are modified.
|
|
103
|
+
#
|
|
104
|
+
# @example Copy keys through Hashie's module function
|
|
105
|
+
# test = { abc: 'def' }
|
|
106
|
+
# Hashie.stringify_keys(test) # => { 'abc' => 'def' }
|
|
107
|
+
# test # => { abc: 'def' }
|
|
108
|
+
#
|
|
109
|
+
# @api public
|
|
110
|
+
# @param [Hash] hash
|
|
111
|
+
# @return [Hash] a shallow copy with stringified keys
|
|
57
112
|
def stringify_keys(hash)
|
|
58
113
|
copy = hash.dup
|
|
59
114
|
copy.extend(Hashie::Extensions::StringifyKeys) unless copy.respond_to?(:stringify_keys!)
|
|
@@ -1,31 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Hashie
|
|
2
4
|
module Extensions
|
|
5
|
+
# Extends a Hash with the ability to convert its keys to symbols.
|
|
6
|
+
# Keys that do not respond to #to_sym are preserved.
|
|
7
|
+
#
|
|
8
|
+
# @example Extend a pre-existing Hash object
|
|
9
|
+
# hash = { 'test' => 'value' }
|
|
10
|
+
# hash.extend(Hashie::Extensions::SymbolizeKeys)
|
|
11
|
+
# hash.symbolize_keys!
|
|
12
|
+
# hash # => { test: 'value' }
|
|
13
|
+
#
|
|
14
|
+
# @example Create a Hash class with this capability
|
|
15
|
+
# class SymbolizableHash < Hash
|
|
16
|
+
# include Hashie::Extensions::SymbolizeKeys
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# hash = SymbolizableHash.new
|
|
20
|
+
# hash['test'] = 'value'
|
|
21
|
+
# hash.symbolize_keys!
|
|
22
|
+
# hash # => { test: 'value' }
|
|
23
|
+
#
|
|
24
|
+
# @example Use the module function to symbolize keys in a hash
|
|
25
|
+
# hash = { 'test' => 'value', 123 => 'number' }
|
|
26
|
+
# Hashie::Extensions::SymbolizeKeys.symbolize_keys!(hash)
|
|
27
|
+
# hash # => { test: 'value', 123 => 'number' }
|
|
3
28
|
module SymbolizeKeys
|
|
4
|
-
#
|
|
29
|
+
# Converts keys in the hash and nested hashes and arrays to symbols.
|
|
5
30
|
#
|
|
6
|
-
# @example
|
|
7
|
-
# test = {'abc' => 'def'}
|
|
31
|
+
# @example Convert keys in place
|
|
32
|
+
# test = { 'abc' => [{ 'def' => 'value' }] }
|
|
33
|
+
# test.extend(Hashie::Extensions::SymbolizeKeys)
|
|
8
34
|
# test.symbolize_keys!
|
|
9
|
-
# test # => {:
|
|
35
|
+
# test # => { abc: [{ def: 'value' }] }
|
|
36
|
+
#
|
|
37
|
+
# @api public
|
|
38
|
+
# @return [Hash] the receiver with its keys symbolized where possible
|
|
10
39
|
def symbolize_keys!
|
|
11
40
|
SymbolizeKeys.symbolize_keys!(self)
|
|
12
41
|
self
|
|
13
42
|
end
|
|
14
43
|
|
|
15
|
-
#
|
|
16
|
-
#
|
|
44
|
+
# Returns a shallow copy with keys recursively converted to symbols.
|
|
45
|
+
# Nested hashes and arrays are shared with the original and are modified.
|
|
46
|
+
#
|
|
47
|
+
# @example Copy a flat hash without modifying the original
|
|
48
|
+
# test = { 'abc' => 'def' }
|
|
49
|
+
# test.extend(Hashie::Extensions::SymbolizeKeys)
|
|
50
|
+
# test.symbolize_keys # => { abc: 'def' }
|
|
51
|
+
# test # => { 'abc' => 'def' }
|
|
52
|
+
#
|
|
53
|
+
# @example Nested values are shared, not deep copied
|
|
54
|
+
# test = { 'abc' => [{ 'def' => 'value' }] }
|
|
55
|
+
# test.extend(Hashie::Extensions::SymbolizeKeys)
|
|
56
|
+
# test.symbolize_keys # => { abc: [{ def: 'value' }] }
|
|
57
|
+
# test # => { 'abc' => [{ def: 'value' }] }
|
|
58
|
+
#
|
|
59
|
+
# @api public
|
|
60
|
+
# @return [Hash] a shallow copy with symbolized keys
|
|
17
61
|
def symbolize_keys
|
|
18
62
|
SymbolizeKeys.symbolize_keys(self)
|
|
19
63
|
end
|
|
20
64
|
|
|
65
|
+
# @example Add recursive conversion functions to an object
|
|
66
|
+
# converter = Object.new.extend(Hashie::Extensions::SymbolizeKeys::ClassMethods)
|
|
67
|
+
# converter.symbolize_keys('user' => { 'name' => 'Ada' }) # => { user: { name: 'Ada' } }
|
|
21
68
|
module ClassMethods
|
|
22
69
|
# Symbolize all keys recursively within nested
|
|
23
70
|
# hashes and arrays.
|
|
24
71
|
# @api private
|
|
25
72
|
def symbolize_keys_recursively!(object)
|
|
26
73
|
case object
|
|
27
|
-
when self.class
|
|
28
|
-
symbolize_keys!(object)
|
|
29
74
|
when ::Array
|
|
30
75
|
object.each do |i|
|
|
31
76
|
symbolize_keys_recursively!(i)
|
|
@@ -35,13 +80,16 @@ module Hashie
|
|
|
35
80
|
end
|
|
36
81
|
end
|
|
37
82
|
|
|
38
|
-
#
|
|
83
|
+
# Converts keys in a hash recursively to symbols, in place.
|
|
84
|
+
#
|
|
85
|
+
# @example Convert keys through Hashie's module function
|
|
86
|
+
# test = { 'abc' => 'def' }
|
|
87
|
+
# Hashie.symbolize_keys!(test)
|
|
88
|
+
# test # => { abc: 'def' }
|
|
39
89
|
#
|
|
90
|
+
# @api public
|
|
40
91
|
# @param [Hash] hash
|
|
41
|
-
# @
|
|
42
|
-
# test = {'abc' => 'def'}
|
|
43
|
-
# Hashie.symbolize_keys! test
|
|
44
|
-
# test # => {:abc => 'def'}
|
|
92
|
+
# @return [Hash] the passed hash with symbolized keys
|
|
45
93
|
def symbolize_keys!(hash)
|
|
46
94
|
hash.extend(Hashie::Extensions::SymbolizeKeys) unless hash.respond_to?(:symbolize_keys!)
|
|
47
95
|
hash.keys.each do |k| # rubocop:disable Performance/HashEachMethods
|
|
@@ -51,9 +99,17 @@ module Hashie
|
|
|
51
99
|
hash
|
|
52
100
|
end
|
|
53
101
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
102
|
+
# Returns a shallow copy of a hash with recursively symbolized keys.
|
|
103
|
+
# Nested hashes and arrays are shared with the original and are modified.
|
|
104
|
+
#
|
|
105
|
+
# @example Copy keys through Hashie's module function
|
|
106
|
+
# test = { 'abc' => 'def' }
|
|
107
|
+
# Hashie.symbolize_keys(test) # => { abc: 'def' }
|
|
108
|
+
# test # => { 'abc' => 'def' }
|
|
109
|
+
#
|
|
110
|
+
# @api public
|
|
111
|
+
# @param [Hash] hash
|
|
112
|
+
# @return [Hash] a shallow copy with symbolized keys
|
|
57
113
|
def symbolize_keys(hash)
|
|
58
114
|
copy = hash.dup
|
|
59
115
|
copy.extend(Hashie::Extensions::SymbolizeKeys) unless copy.respond_to?(:symbolize_keys!)
|
data/lib/hashie/hash.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'hashie/extensions/stringify_keys'
|
|
2
4
|
require 'hashie/extensions/pretty_inspect'
|
|
3
5
|
|
|
@@ -5,16 +7,26 @@ module Hashie
|
|
|
5
7
|
# A Hashie Hash is simply a Hash that has convenience
|
|
6
8
|
# functions baked in such as stringify_keys that may
|
|
7
9
|
# not be available in all libraries.
|
|
10
|
+
#
|
|
11
|
+
# @example Convert keys using the built-in extensions
|
|
12
|
+
# Hashie::Hash[name: 'Ada'].stringify_keys # => { 'name' => 'Ada' }
|
|
8
13
|
class Hash < ::Hash
|
|
9
14
|
include Hashie::Extensions::PrettyInspect
|
|
10
15
|
include Hashie::Extensions::StringifyKeys
|
|
11
16
|
|
|
12
17
|
# Convert this hash into a Mash
|
|
18
|
+
#
|
|
19
|
+
# @example Read converted data through methods
|
|
20
|
+
# Hashie::Hash[name: 'Ada'].to_mash.name # => 'Ada'
|
|
13
21
|
def to_mash
|
|
14
22
|
::Hashie::Mash.new(self)
|
|
15
23
|
end
|
|
16
24
|
|
|
17
25
|
# Converts a mash back to a hash (with stringified or symbolized keys)
|
|
26
|
+
#
|
|
27
|
+
# @example Recursively convert nested hashes and their keys
|
|
28
|
+
# hash = Hashie::Hash[user: Hashie::Hash[name: 'Ada']]
|
|
29
|
+
# hash.to_hash(stringify_keys: true) # => { 'user' => { 'name' => 'Ada' } }
|
|
18
30
|
def to_hash(options = {})
|
|
19
31
|
out = {}
|
|
20
32
|
each_key do |k|
|
|
@@ -39,6 +51,10 @@ module Hashie
|
|
|
39
51
|
end
|
|
40
52
|
|
|
41
53
|
# The C generator for the json gem doesn't like mashies
|
|
54
|
+
#
|
|
55
|
+
# @example Serialize as an ordinary JSON object
|
|
56
|
+
# require 'json'
|
|
57
|
+
# JSON.parse(Hashie::Hash[name: 'Ada'].to_json) # => { 'name' => 'Ada' }
|
|
42
58
|
def to_json(*args)
|
|
43
59
|
to_hash.to_json(*args)
|
|
44
60
|
end
|
data/lib/hashie/logger.rb
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'logger'
|
|
2
4
|
|
|
3
5
|
module Hashie
|
|
4
6
|
# The logger that Hashie uses for reporting errors.
|
|
5
7
|
#
|
|
6
8
|
# @return [Logger]
|
|
9
|
+
#
|
|
10
|
+
# @example Obtain the logger used for warnings
|
|
11
|
+
# Hashie.logger.respond_to?(:warn) # => true
|
|
7
12
|
def self.logger
|
|
8
|
-
@logger ||= Logger.new(
|
|
13
|
+
@logger ||= Logger.new($stdout)
|
|
9
14
|
end
|
|
10
15
|
|
|
11
16
|
# Sets the logger that Hashie uses for reporting errors.
|
|
12
17
|
#
|
|
13
18
|
# @param logger [Logger] The logger to set as Hashie's logger.
|
|
14
19
|
# @return [void]
|
|
20
|
+
#
|
|
21
|
+
# @example Temporarily capture warnings
|
|
22
|
+
# require 'stringio'
|
|
23
|
+
# original = Hashie.logger
|
|
24
|
+
# begin
|
|
25
|
+
# output = StringIO.new
|
|
26
|
+
# Hashie.logger = Logger.new(output)
|
|
27
|
+
# Hashie.logger.warn('example warning')
|
|
28
|
+
# output.string.include?('example warning') # => true
|
|
29
|
+
# ensure
|
|
30
|
+
# Hashie.logger = original
|
|
31
|
+
# end
|
|
15
32
|
def self.logger=(logger)
|
|
16
33
|
@logger = logger
|
|
17
34
|
end
|