hashie 2.0.5 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +36 -0
- data/.travis.yml +13 -6
- data/CHANGELOG.md +40 -21
- data/CONTRIBUTING.md +110 -19
- data/Gemfile +9 -0
- data/LICENSE +1 -1
- data/README.md +347 -0
- data/Rakefile +4 -2
- data/hashie.gemspec +4 -7
- data/lib/hashie.rb +3 -0
- data/lib/hashie/clash.rb +19 -19
- data/lib/hashie/dash.rb +47 -39
- data/lib/hashie/extensions/coercion.rb +10 -6
- data/lib/hashie/extensions/deep_fetch.rb +29 -0
- data/lib/hashie/extensions/deep_merge.rb +15 -6
- data/lib/hashie/extensions/ignore_undeclared.rb +41 -0
- data/lib/hashie/extensions/indifferent_access.rb +37 -10
- data/lib/hashie/extensions/key_conversion.rb +3 -3
- data/lib/hashie/extensions/method_access.rb +9 -9
- data/lib/hashie/hash.rb +7 -7
- data/lib/hashie/hash_extensions.rb +5 -7
- data/lib/hashie/mash.rb +38 -31
- data/lib/hashie/rash.rb +119 -0
- data/lib/hashie/trash.rb +31 -22
- data/lib/hashie/version.rb +1 -1
- data/spec/hashie/clash_spec.rb +43 -45
- data/spec/hashie/dash_spec.rb +115 -53
- data/spec/hashie/extensions/coercion_spec.rb +42 -37
- data/spec/hashie/extensions/deep_fetch_spec.rb +70 -0
- data/spec/hashie/extensions/deep_merge_spec.rb +11 -9
- data/spec/hashie/extensions/ignore_undeclared_spec.rb +23 -0
- data/spec/hashie/extensions/indifferent_access_spec.rb +117 -64
- data/spec/hashie/extensions/key_conversion_spec.rb +28 -27
- data/spec/hashie/extensions/merge_initializer_spec.rb +13 -10
- data/spec/hashie/extensions/method_access_spec.rb +49 -40
- data/spec/hashie/hash_spec.rb +25 -13
- data/spec/hashie/mash_spec.rb +243 -187
- data/spec/hashie/rash_spec.rb +44 -0
- data/spec/hashie/trash_spec.rb +81 -43
- data/spec/hashie/version_spec.rb +7 -0
- data/spec/spec_helper.rb +0 -4
- metadata +27 -78
- data/.document +0 -5
- data/README.markdown +0 -236
- data/lib/hashie/extensions/structure.rb +0 -47
data/Rakefile
CHANGED
@@ -6,8 +6,10 @@ Bundler::GemHelper.install_tasks
|
|
6
6
|
|
7
7
|
require 'rspec/core/rake_task'
|
8
8
|
RSpec::Core::RakeTask.new do |spec|
|
9
|
-
# spec.libs << 'lib' << 'spec'
|
10
9
|
spec.pattern = 'spec/**/*_spec.rb'
|
11
10
|
end
|
12
11
|
|
13
|
-
|
12
|
+
require 'rubocop/rake_task'
|
13
|
+
Rubocop::RakeTask.new(:rubocop)
|
14
|
+
|
15
|
+
task default: [:rubocop, :spec]
|
data/hashie.gemspec
CHANGED
@@ -3,8 +3,8 @@ require File.expand_path('../lib/hashie/version', __FILE__)
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.authors = ["Michael Bleigh", "Jerry Cheung"]
|
5
5
|
gem.email = ["michael@intridea.com", "jollyjerry@gmail.com"]
|
6
|
-
gem.description = %q{Hashie is a
|
7
|
-
gem.summary = %q{Your friendly neighborhood hash
|
6
|
+
gem.description = %q{Hashie is a collection of classes and mixins that make hashes more powerful.}
|
7
|
+
gem.summary = %q{Your friendly neighborhood hash library.}
|
8
8
|
gem.homepage = 'https://github.com/intridea/hashie'
|
9
9
|
|
10
10
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
@@ -15,9 +15,6 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.version = Hashie::VERSION
|
16
16
|
gem.license = "MIT"
|
17
17
|
|
18
|
-
gem.add_development_dependency 'rake'
|
19
|
-
gem.add_development_dependency 'rspec'
|
20
|
-
gem.add_development_dependency 'guard'
|
21
|
-
gem.add_development_dependency 'guard-rspec'
|
22
|
-
gem.add_development_dependency 'growl'
|
18
|
+
gem.add_development_dependency 'rake'
|
19
|
+
gem.add_development_dependency 'rspec'
|
23
20
|
end
|
data/lib/hashie.rb
CHANGED
@@ -6,11 +6,13 @@ module Hashie
|
|
6
6
|
autoload :Mash, 'hashie/mash'
|
7
7
|
autoload :PrettyInspect, 'hashie/hash_extensions'
|
8
8
|
autoload :Trash, 'hashie/trash'
|
9
|
+
autoload :Rash, 'hashie/rash'
|
9
10
|
|
10
11
|
module Extensions
|
11
12
|
autoload :Coercion, 'hashie/extensions/coercion'
|
12
13
|
autoload :DeepMerge, 'hashie/extensions/deep_merge'
|
13
14
|
autoload :KeyConversion, 'hashie/extensions/key_conversion'
|
15
|
+
autoload :IgnoreUndeclared, 'hashie/extensions/ignore_undeclared'
|
14
16
|
autoload :IndifferentAccess, 'hashie/extensions/indifferent_access'
|
15
17
|
autoload :MergeInitializer, 'hashie/extensions/merge_initializer'
|
16
18
|
autoload :MethodAccess, 'hashie/extensions/method_access'
|
@@ -19,5 +21,6 @@ module Hashie
|
|
19
21
|
autoload :MethodWriter, 'hashie/extensions/method_access'
|
20
22
|
autoload :StringifyKeys, 'hashie/extensions/key_conversion'
|
21
23
|
autoload :SymbolizeKeys, 'hashie/extensions/key_conversion'
|
24
|
+
autoload :DeepFetch, 'hashie/extensions/deep_fetch'
|
22
25
|
end
|
23
26
|
end
|
data/lib/hashie/clash.rb
CHANGED
@@ -3,10 +3,10 @@ require 'hashie/hash'
|
|
3
3
|
module Hashie
|
4
4
|
#
|
5
5
|
# A Clash is a "Chainable Lazy Hash". Inspired by libraries such as Arel,
|
6
|
-
# a Clash allows you to chain together method arguments to build a
|
6
|
+
# a Clash allows you to chain together method arguments to build a
|
7
7
|
# hash, something that's especially useful if you're doing something
|
8
8
|
# like constructing a complex options hash. Here's a basic example:
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# c = Hashie::Clash.new.conditions(:foo => 'bar').order(:created_at)
|
11
11
|
# c # => {:conditions => {:foo => 'bar'}, :order => :created_at}
|
12
12
|
#
|
@@ -15,7 +15,7 @@ module Hashie
|
|
15
15
|
# back out again with the _end! method. Example:
|
16
16
|
#
|
17
17
|
# c = Hashie::Clash.new.conditions!.foo('bar').baz(123)._end!.order(:created_at)
|
18
|
-
# c # => {:
|
18
|
+
# c # => { conditions: { foo: 'bar', baz: 123 }, order: :created_at}
|
19
19
|
#
|
20
20
|
# Because the primary functionality of Clash is to build options objects,
|
21
21
|
# all keys are converted to symbols since many libraries expect symbols explicitly
|
@@ -25,7 +25,7 @@ module Hashie
|
|
25
25
|
class ChainError < ::StandardError; end
|
26
26
|
# The parent Clash if this Clash was created via chaining.
|
27
27
|
attr_reader :_parent
|
28
|
-
|
28
|
+
|
29
29
|
# Initialize a new clash by passing in a Hash to
|
30
30
|
# convert and, optionally, the parent to which this
|
31
31
|
# Clash is chained.
|
@@ -35,7 +35,7 @@ module Hashie
|
|
35
35
|
self[k.to_sym] = v
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Jump back up a level if you are using bang method
|
40
40
|
# chaining. For example:
|
41
41
|
#
|
@@ -43,44 +43,44 @@ module Hashie
|
|
43
43
|
# c.baz!.foo(123) # => c[:baz]
|
44
44
|
# c.baz!._end! # => c
|
45
45
|
def _end!
|
46
|
-
|
46
|
+
_parent
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def id(*args) #:nodoc:
|
50
50
|
method_missing(:id, *args)
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def merge_store(key, *args) #:nodoc:
|
54
54
|
case args.length
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
when 1
|
56
|
+
val = args.first
|
57
|
+
val = self[key].merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
|
58
|
+
else
|
59
|
+
val = args
|
60
60
|
end
|
61
61
|
|
62
62
|
self[key.to_sym] = val
|
63
63
|
self
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def method_missing(name, *args) #:nodoc:
|
67
67
|
name = name.to_s
|
68
68
|
if name.match(/!$/) && args.empty?
|
69
69
|
key = name[0...-1].to_sym
|
70
|
-
|
70
|
+
|
71
71
|
if self[key].nil?
|
72
72
|
self[key] = Clash.new({}, self)
|
73
73
|
elsif self[key].is_a?(::Hash) && !self[key].is_a?(Clash)
|
74
74
|
self[key] = Clash.new(self[key], self)
|
75
75
|
else
|
76
|
-
|
76
|
+
fail ChainError, 'Tried to chain into a non-hash key.'
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
self[key]
|
80
80
|
elsif args.any?
|
81
81
|
key = name.to_sym
|
82
|
-
|
82
|
+
merge_store(key, *args)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
|
-
end
|
86
|
+
end
|
data/lib/hashie/dash.rb
CHANGED
@@ -30,24 +30,18 @@ module Hashie
|
|
30
30
|
def self.property(property_name, options = {})
|
31
31
|
property_name = property_name.to_sym
|
32
32
|
|
33
|
-
|
33
|
+
properties << property_name
|
34
34
|
|
35
|
-
if options.
|
36
|
-
|
37
|
-
elsif
|
38
|
-
|
35
|
+
if options.key?(:default)
|
36
|
+
defaults[property_name] = options[:default]
|
37
|
+
elsif defaults.key?(property_name)
|
38
|
+
defaults.delete property_name
|
39
39
|
end
|
40
40
|
|
41
41
|
unless instance_methods.map { |m| m.to_s }.include?("#{property_name}=")
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def #{property_name}=(value)
|
48
|
-
self.[]=(#{property_name.to_s.inspect}, value)
|
49
|
-
end
|
50
|
-
ACCESSORS
|
42
|
+
define_method(property_name) { |&block| self.[](property_name.to_s, &block) }
|
43
|
+
property_assignment = property_name.to_s.concat('=').to_sym
|
44
|
+
define_method(property_assignment) { |value| self.[]=(property_name.to_s, value) }
|
51
45
|
end
|
52
46
|
|
53
47
|
if defined? @subclasses
|
@@ -67,9 +61,9 @@ module Hashie
|
|
67
61
|
def self.inherited(klass)
|
68
62
|
super
|
69
63
|
(@subclasses ||= Set.new) << klass
|
70
|
-
klass.instance_variable_set('@properties',
|
71
|
-
klass.instance_variable_set('@defaults',
|
72
|
-
klass.instance_variable_set('@required_properties',
|
64
|
+
klass.instance_variable_set('@properties', properties.dup)
|
65
|
+
klass.instance_variable_set('@defaults', defaults.dup)
|
66
|
+
klass.instance_variable_set('@required_properties', required_properties.dup)
|
73
67
|
end
|
74
68
|
|
75
69
|
# Check to see if the specified property has already been
|
@@ -127,6 +121,21 @@ module Hashie
|
|
127
121
|
super(property.to_s, value)
|
128
122
|
end
|
129
123
|
|
124
|
+
def merge(other_hash)
|
125
|
+
new_dash = dup
|
126
|
+
other_hash.each do |k, v|
|
127
|
+
new_dash[k] = block_given? ? yield(k, self[k], v) : v
|
128
|
+
end
|
129
|
+
new_dash
|
130
|
+
end
|
131
|
+
|
132
|
+
def merge!(other_hash)
|
133
|
+
other_hash.each do |k, v|
|
134
|
+
self[k] = block_given? ? yield(k, self[k], v) : v
|
135
|
+
end
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
130
139
|
def replace(other_hash)
|
131
140
|
other_hash = self.class.defaults.merge(other_hash)
|
132
141
|
(keys - other_hash.keys).each { |key| delete(key) }
|
@@ -136,35 +145,34 @@ module Hashie
|
|
136
145
|
|
137
146
|
private
|
138
147
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
148
|
+
def initialize_attributes(attributes)
|
149
|
+
attributes.each_pair do |att, value|
|
150
|
+
self[att] = value
|
151
|
+
end if attributes
|
152
|
+
end
|
144
153
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end
|
154
|
+
def assert_property_exists!(property)
|
155
|
+
unless self.class.property?(property)
|
156
|
+
fail NoMethodError, "The property '#{property}' is not defined for this Dash."
|
149
157
|
end
|
158
|
+
end
|
150
159
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
end
|
160
|
+
def assert_required_properties_set!
|
161
|
+
self.class.required_properties.each do |required_property|
|
162
|
+
assert_property_set!(required_property)
|
155
163
|
end
|
164
|
+
end
|
156
165
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
166
|
+
def assert_property_set!(property)
|
167
|
+
if send(property).nil?
|
168
|
+
fail ArgumentError, "The property '#{property}' is required for this Dash."
|
161
169
|
end
|
170
|
+
end
|
162
171
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
172
|
+
def assert_property_required!(property, value)
|
173
|
+
if self.class.required?(property) && value.nil?
|
174
|
+
fail ArgumentError, "The property '#{property}' is required for this Dash."
|
167
175
|
end
|
168
|
-
|
176
|
+
end
|
169
177
|
end
|
170
178
|
end
|
@@ -2,7 +2,7 @@ module Hashie
|
|
2
2
|
module Extensions
|
3
3
|
module Coercion
|
4
4
|
def self.included(base)
|
5
|
-
base.
|
5
|
+
base.extend ClassMethods
|
6
6
|
base.send :include, InstanceMethods
|
7
7
|
end
|
8
8
|
|
@@ -21,7 +21,7 @@ module Hashie
|
|
21
21
|
super(key, value)
|
22
22
|
end
|
23
23
|
|
24
|
-
def custom_writer(key, value)
|
24
|
+
def custom_writer(key, value, convert = true)
|
25
25
|
self[key] = value
|
26
26
|
end
|
27
27
|
|
@@ -53,7 +53,7 @@ module Hashie
|
|
53
53
|
attrs.each { |key| @key_coercions[key] = into }
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
alias_method :coerce_keys, :coerce_key
|
57
57
|
|
58
58
|
# Returns a hash of any existing key coercions.
|
59
59
|
def key_coercions
|
@@ -87,7 +87,7 @@ module Hashie
|
|
87
87
|
# end
|
88
88
|
# end
|
89
89
|
def coerce_value(from, into, options = {})
|
90
|
-
options = {:
|
90
|
+
options = { strict: true }.merge(options)
|
91
91
|
|
92
92
|
if options[:strict]
|
93
93
|
(@strict_value_coercions ||= {})[from] = into
|
@@ -100,9 +100,13 @@ module Hashie
|
|
100
100
|
end
|
101
101
|
|
102
102
|
# Return all value coercions that have the :strict rule as true.
|
103
|
-
def strict_value_coercions
|
103
|
+
def strict_value_coercions
|
104
|
+
@strict_value_coercions || {}
|
105
|
+
end
|
104
106
|
# Return all value coercions that have the :strict rule as false.
|
105
|
-
def lenient_value_coercions
|
107
|
+
def lenient_value_coercions
|
108
|
+
@value_coercions || {}
|
109
|
+
end
|
106
110
|
|
107
111
|
# Fetch the value coercion, if any, for the specified object.
|
108
112
|
def value_coercion(value)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Hashie
|
2
|
+
module Extensions
|
3
|
+
# Searches a deeply nested datastructure for a key path, and returns the associated value.
|
4
|
+
#
|
5
|
+
# options = { user: { location: { address: '123 Street' } } }
|
6
|
+
# options.deep_fetch :user, :location, :address #=> '123 Street'
|
7
|
+
#
|
8
|
+
# If a block is provided its value will be returned if the key does not exist.
|
9
|
+
#
|
10
|
+
# options.deep_fetch(:user, :non_existent_key) { 'a value' } #=> 'a value'
|
11
|
+
#
|
12
|
+
# This is particularly useful for fetching values from deeply nested api responses or params hashes.
|
13
|
+
module DeepFetch
|
14
|
+
class UndefinedPathError < StandardError; end
|
15
|
+
|
16
|
+
def deep_fetch(*args, &block)
|
17
|
+
args.reduce(self) do |obj, arg|
|
18
|
+
begin
|
19
|
+
arg = Integer(arg) if obj.kind_of? Array
|
20
|
+
obj.fetch(arg)
|
21
|
+
rescue ArgumentError, IndexError => e
|
22
|
+
break block.call(arg) if block
|
23
|
+
raise UndefinedPathError, "Could not fetch path (#{args.join(' > ')}) at #{arg}", e.backtrace
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,19 +3,28 @@ module Hashie
|
|
3
3
|
module DeepMerge
|
4
4
|
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
5
5
|
def deep_merge(other_hash)
|
6
|
-
(
|
7
|
-
h.deep_merge!(other_hash)
|
6
|
+
dup.deep_merge!(other_hash)
|
8
7
|
end
|
9
8
|
|
10
9
|
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
11
10
|
# Modifies the receiver in place.
|
12
11
|
def deep_merge!(other_hash)
|
13
|
-
other_hash
|
14
|
-
(class << (tv = self[k]); self; end).send :include, Hashie::Extensions::DeepMerge
|
15
|
-
self[k] = tv.is_a?(::Hash) && v.is_a?(::Hash) ? tv.deep_merge(v) : v
|
16
|
-
end
|
12
|
+
_recursive_merge(self, other_hash)
|
17
13
|
self
|
18
14
|
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def _recursive_merge(hash, other_hash)
|
19
|
+
if other_hash.is_a?(::Hash) && hash.is_a?(::Hash)
|
20
|
+
other_hash.each do |k, v|
|
21
|
+
hash[k] = hash.key?(k) ? _recursive_merge(hash[k], v) : v
|
22
|
+
end
|
23
|
+
hash
|
24
|
+
else
|
25
|
+
other_hash
|
26
|
+
end
|
27
|
+
end
|
19
28
|
end
|
20
29
|
end
|
21
30
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Hashie
|
2
|
+
module Extensions
|
3
|
+
# IgnoreUndeclared is a simple mixin that silently ignores
|
4
|
+
# undeclared properties on initialization instead of
|
5
|
+
# raising an error. This is useful when using a Trash to
|
6
|
+
# capture a subset of a larger hash.
|
7
|
+
#
|
8
|
+
# Note that attempting to retrieve an undeclared property
|
9
|
+
# will still raise a NoMethodError, even if a value for
|
10
|
+
# that property was provided at initialization.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# class Person < Trash
|
14
|
+
# include Hashie::Extensions::IgnoreUndeclared
|
15
|
+
#
|
16
|
+
# property :first_name
|
17
|
+
# property :last_name
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# user_data = {
|
21
|
+
# :first_name => 'Freddy',
|
22
|
+
# :last_name => 'Nostrils',
|
23
|
+
# :email => 'freddy@example.com'
|
24
|
+
# }
|
25
|
+
#
|
26
|
+
# p = Person.new(user_data) # 'email' is silently ignored
|
27
|
+
#
|
28
|
+
# p.first_name # => 'Freddy'
|
29
|
+
# p.last_name # => 'Nostrils'
|
30
|
+
# p.email # => NoMethodError
|
31
|
+
module IgnoreUndeclared
|
32
|
+
def initialize_attributes(attributes)
|
33
|
+
attributes.each_pair do |att, value|
|
34
|
+
if self.class.property?(att) || (self.class.respond_to?(:translations) && self.class.translations.include?(att.to_sym))
|
35
|
+
self[att] = value
|
36
|
+
end
|
37
|
+
end if attributes
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -27,6 +27,7 @@ module Hashie
|
|
27
27
|
base.class_eval do
|
28
28
|
alias_method :regular_writer, :[]=
|
29
29
|
alias_method :[]=, :indifferent_writer
|
30
|
+
alias_method :store, :indifferent_writer
|
30
31
|
%w(default update replace fetch delete key? values_at).each do |m|
|
31
32
|
alias_method "regular_#{m}", m
|
32
33
|
alias_method m, "indifferent_#{m}"
|
@@ -35,6 +36,16 @@ module Hashie
|
|
35
36
|
%w(include? member? has_key?).each do |key_alias|
|
36
37
|
alias_method key_alias, :indifferent_key?
|
37
38
|
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
def [](*)
|
42
|
+
super.convert!
|
43
|
+
end
|
44
|
+
|
45
|
+
def try_convert(*)
|
46
|
+
(hash = super) && self[hash]
|
47
|
+
end
|
48
|
+
end
|
38
49
|
end
|
39
50
|
end
|
40
51
|
|
@@ -61,7 +72,7 @@ module Hashie
|
|
61
72
|
# is injecting itself into member hashes.
|
62
73
|
def convert!
|
63
74
|
keys.each do |k|
|
64
|
-
regular_writer convert_key(k), convert_value(
|
75
|
+
regular_writer convert_key(k), convert_value(regular_delete(k))
|
65
76
|
end
|
66
77
|
self
|
67
78
|
end
|
@@ -75,7 +86,7 @@ module Hashie
|
|
75
86
|
value
|
76
87
|
end
|
77
88
|
end
|
78
|
-
|
89
|
+
|
79
90
|
def indifferent_default(key = nil)
|
80
91
|
return self[convert_key(key)] if key?(key)
|
81
92
|
regular_default(key)
|
@@ -83,18 +94,34 @@ module Hashie
|
|
83
94
|
|
84
95
|
def indifferent_update(other_hash)
|
85
96
|
return regular_update(other_hash) if hash_with_indifference?(other_hash)
|
86
|
-
other_hash.each_pair do |k,v|
|
97
|
+
other_hash.each_pair do |k, v|
|
87
98
|
self[k] = v
|
88
99
|
end
|
89
100
|
end
|
90
|
-
|
91
|
-
def indifferent_writer(key, value); regular_writer convert_key(key), convert_value(value) end
|
92
|
-
def indifferent_fetch(key, *args); regular_fetch convert_key(key), *args end
|
93
|
-
def indifferent_delete(key); regular_delete convert_key(key) end
|
94
|
-
def indifferent_key?(key); regular_key? convert_key(key) end
|
95
|
-
def indifferent_values_at(*indices); indices.map{|i| self[i] } end
|
96
101
|
|
97
|
-
def
|
102
|
+
def indifferent_writer(key, value)
|
103
|
+
regular_writer convert_key(key), convert_value(value)
|
104
|
+
end
|
105
|
+
|
106
|
+
def indifferent_fetch(key, *args)
|
107
|
+
regular_fetch convert_key(key), *args
|
108
|
+
end
|
109
|
+
|
110
|
+
def indifferent_delete(key)
|
111
|
+
regular_delete convert_key(key)
|
112
|
+
end
|
113
|
+
|
114
|
+
def indifferent_key?(key)
|
115
|
+
regular_key? convert_key(key)
|
116
|
+
end
|
117
|
+
|
118
|
+
def indifferent_values_at(*indices)
|
119
|
+
indices.map { |i| self[i] }
|
120
|
+
end
|
121
|
+
|
122
|
+
def indifferent_access?
|
123
|
+
true
|
124
|
+
end
|
98
125
|
|
99
126
|
def indifferent_replace(other_hash)
|
100
127
|
(keys - other_hash.keys).each { |key| delete(key) }
|