configliere 0.3.4 → 0.4.4
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.
- data/.document +3 -0
- data/.watchr +20 -0
- data/CHANGELOG.textile +99 -3
- data/Gemfile +26 -0
- data/Gemfile.lock +54 -0
- data/README.textile +162 -138
- data/Rakefile +30 -21
- data/VERSION +1 -1
- data/bin/configliere +77 -77
- data/bin/configliere-decrypt +85 -0
- data/bin/configliere-delete +85 -0
- data/bin/configliere-dump +85 -0
- data/bin/configliere-encrypt +85 -0
- data/bin/configliere-list +85 -0
- data/bin/configliere-set +85 -0
- data/configliere.gemspec +53 -23
- data/examples/config_block_script.rb +9 -2
- data/examples/encrypted_script.rb +28 -16
- data/examples/env_var_script.rb +2 -2
- data/examples/help_message_demo.rb +16 -0
- data/examples/independent_config.rb +28 -0
- data/examples/prompt.rb +23 -0
- data/examples/simple_script.rb +28 -15
- data/examples/simple_script.yaml +1 -1
- data/lib/configliere.rb +22 -24
- data/lib/configliere/commandline.rb +135 -116
- data/lib/configliere/commands.rb +38 -54
- data/lib/configliere/config_block.rb +4 -2
- data/lib/configliere/config_file.rb +30 -52
- data/lib/configliere/crypter.rb +8 -5
- data/lib/configliere/deep_hash.rb +368 -0
- data/lib/configliere/define.rb +83 -89
- data/lib/configliere/encrypted.rb +17 -18
- data/lib/configliere/env_var.rb +5 -7
- data/lib/configliere/param.rb +37 -64
- data/lib/configliere/prompt.rb +23 -0
- data/spec/configliere/commandline_spec.rb +156 -57
- data/spec/configliere/commands_spec.rb +75 -30
- data/spec/configliere/config_block_spec.rb +10 -1
- data/spec/configliere/config_file_spec.rb +83 -55
- data/spec/configliere/crypter_spec.rb +3 -2
- data/spec/configliere/deep_hash_spec.rb +401 -0
- data/spec/configliere/define_spec.rb +121 -42
- data/spec/configliere/encrypted_spec.rb +53 -20
- data/spec/configliere/env_var_spec.rb +24 -4
- data/spec/configliere/param_spec.rb +25 -27
- data/spec/configliere/prompt_spec.rb +50 -0
- data/spec/configliere_spec.rb +3 -9
- data/spec/spec_helper.rb +17 -6
- metadata +110 -35
- data/lib/configliere/core_ext.rb +0 -2
- data/lib/configliere/core_ext/blank.rb +0 -93
- data/lib/configliere/core_ext/hash.rb +0 -108
- data/lib/configliere/core_ext/sash.rb +0 -170
- data/spec/configliere/core_ext/hash_spec.rb +0 -78
- data/spec/configliere/core_ext/sash_spec.rb +0 -312
@@ -1,108 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# core_ext/hash.rb -- hash extensions
|
3
|
-
#
|
4
|
-
class Hash
|
5
|
-
|
6
|
-
# lambda for recursive merges
|
7
|
-
::Hash::DEEP_MERGER = proc do |key,v1,v2|
|
8
|
-
(v1.respond_to?(:merge) && v2.respond_to?(:merge)) ? v1.merge(v2.compact, &Hash::DEEP_MERGER) : (v2.nil? ? v1 : v2)
|
9
|
-
end unless defined?(::Hash::DEEP_MERGER)
|
10
|
-
|
11
|
-
#
|
12
|
-
# Merge hashes recursively.
|
13
|
-
# Nothing special happens to array values
|
14
|
-
#
|
15
|
-
# x = { :subhash => { 1 => :val_from_x, 222 => :only_in_x, 333 => :only_in_x }, :scalar => :scalar_from_x}
|
16
|
-
# y = { :subhash => { 1 => :val_from_y, 999 => :only_in_y }, :scalar => :scalar_from_y }
|
17
|
-
# x.deep_merge y
|
18
|
-
# => {:subhash=>{1=>:val_from_y, 222=>:only_in_x, 333=>:only_in_x, 999=>:only_in_y}, :scalar=>:scalar_from_y}
|
19
|
-
# y.deep_merge x
|
20
|
-
# => {:subhash=>{1=>:val_from_x, 222=>:only_in_x, 333=>:only_in_x, 999=>:only_in_y}, :scalar=>:scalar_from_x}
|
21
|
-
#
|
22
|
-
# Nil values always lose.
|
23
|
-
#
|
24
|
-
# x = {:subhash=>{:nil_in_x=>nil, 1=>:val1,}, :nil_in_x=>nil}
|
25
|
-
# y = {:subhash=>{:nil_in_x=>5}, :nil_in_x=>5}
|
26
|
-
# y.deep_merge x
|
27
|
-
# => {:subhash=>{1=>:val1, :nil_in_x=>5}, :nil_in_x=>5}
|
28
|
-
# x.deep_merge y
|
29
|
-
# => {:subhash=>{1=>:val1, :nil_in_x=>5}, :nil_in_x=>5}
|
30
|
-
#
|
31
|
-
def deep_merge hsh2
|
32
|
-
merge hsh2, &Hash::DEEP_MERGER
|
33
|
-
end unless method_defined?(:deep_merge)
|
34
|
-
|
35
|
-
def deep_merge! hsh2
|
36
|
-
update hsh2, &Hash::DEEP_MERGER
|
37
|
-
self
|
38
|
-
end unless method_defined?(:deep_merge!)
|
39
|
-
|
40
|
-
#
|
41
|
-
# Treat hash as tree of hashes:
|
42
|
-
#
|
43
|
-
# x = { 1 => :val, :subhash => { 1 => :val1 } }
|
44
|
-
# x.deep_set(:subhash, :cat, :hat)
|
45
|
-
# # => { 1 => :val, :subhash => { 1 => :val1, :cat => :hat } }
|
46
|
-
# x.deep_set(:subhash, 1, :newval)
|
47
|
-
# # => { 1 => :val, :subhash => { 1 => :newval, :cat => :hat } }
|
48
|
-
#
|
49
|
-
#
|
50
|
-
def deep_set *args
|
51
|
-
val = args.pop
|
52
|
-
last_key = args.pop
|
53
|
-
# dig down to last subtree (building out if necessary)
|
54
|
-
hsh = self
|
55
|
-
args.each{|key| hsh = (hsh[key] ||= self.class.new) }
|
56
|
-
# set leaf value
|
57
|
-
hsh[last_key] = val
|
58
|
-
end unless method_defined?(:deep_set)
|
59
|
-
|
60
|
-
#
|
61
|
-
# Treat hash as tree of hashes:
|
62
|
-
#
|
63
|
-
# x = { 1 => :val, :subhash => { 1 => :val1 } }
|
64
|
-
# x.deep_get(:subhash, 1)
|
65
|
-
# # => :val
|
66
|
-
# x.deep_get(:subhash, 2)
|
67
|
-
# # => nil
|
68
|
-
# x.deep_get(:subhash, 2, 3)
|
69
|
-
# # => nil
|
70
|
-
# x.deep_get(:subhash, 2)
|
71
|
-
# # => nil
|
72
|
-
#
|
73
|
-
def deep_get *args
|
74
|
-
last_key = args.pop
|
75
|
-
# dig down to last subtree (building out if necessary)
|
76
|
-
hsh = args.inject(self){|h, k| h[k] || {} }
|
77
|
-
# get leaf value
|
78
|
-
hsh[last_key]
|
79
|
-
end unless method_defined?(:deep_get)
|
80
|
-
|
81
|
-
#
|
82
|
-
# Treat hash as tree of hashes:
|
83
|
-
#
|
84
|
-
# x = { 1 => :val, :subhash => { 1 => :val1, 2 => :val2 } }
|
85
|
-
# x.deep_delete(:subhash, 1)
|
86
|
-
# #=> :val
|
87
|
-
# x
|
88
|
-
# #=> { 1 => :val, :subhash => { 2 => :val2 } }
|
89
|
-
#
|
90
|
-
def deep_delete *args
|
91
|
-
last_key = args.pop
|
92
|
-
last_hsh = args.empty? ? self : (deep_get(*args)||{})
|
93
|
-
last_hsh.delete(last_key)
|
94
|
-
end unless method_defined?(:deep_delete)
|
95
|
-
|
96
|
-
#
|
97
|
-
# remove all key-value pairs where the value is nil
|
98
|
-
#
|
99
|
-
def compact
|
100
|
-
reject{|key,val| val.nil? }
|
101
|
-
end unless method_defined?(:compact)
|
102
|
-
#
|
103
|
-
# Replace the hash with its compacted self
|
104
|
-
#
|
105
|
-
def compact!
|
106
|
-
replace(compact)
|
107
|
-
end unless method_defined?(:compact!)
|
108
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'configliere/core_ext/hash'
|
2
|
-
|
3
|
-
#
|
4
|
-
# Hash with indifferent access
|
5
|
-
#
|
6
|
-
# Adapted from extlib/lib/mash.rb
|
7
|
-
#
|
8
|
-
class Sash < ::Hash
|
9
|
-
|
10
|
-
# @param constructor<Object>
|
11
|
-
# The default value for the mash. Defaults to an empty hash.
|
12
|
-
#
|
13
|
-
# @details [Alternatives]
|
14
|
-
# If constructor is a Hash, a new mash will be created based on the keys of
|
15
|
-
# the hash and no default value will be set.
|
16
|
-
def initialize(constructor = {})
|
17
|
-
if constructor.is_a?(Hash)
|
18
|
-
super()
|
19
|
-
update(constructor) unless constructor.empty?
|
20
|
-
else
|
21
|
-
super(constructor)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
|
26
|
-
alias_method :regular_update, :update unless method_defined?(:regular_update)
|
27
|
-
|
28
|
-
# @param key<Object> The key to set.
|
29
|
-
# @param value<Object>
|
30
|
-
# The value to set the key to.
|
31
|
-
#
|
32
|
-
# @see Mash#convert_key
|
33
|
-
# @see Mash#convert_value
|
34
|
-
def []=(key, value)
|
35
|
-
regular_writer(convert_key(key), convert_value(value))
|
36
|
-
end
|
37
|
-
|
38
|
-
alias_method :merge!, :update
|
39
|
-
|
40
|
-
# @param key<Object> The key to check for. This will be run through convert_key.
|
41
|
-
#
|
42
|
-
# @return [Boolean] True if the key exists in the mash.
|
43
|
-
def key?(key)
|
44
|
-
super(convert_key(key))
|
45
|
-
end
|
46
|
-
|
47
|
-
# def include? def has_key? def member?
|
48
|
-
alias_method :include?, :key?
|
49
|
-
alias_method :has_key?, :key?
|
50
|
-
alias_method :member?, :key?
|
51
|
-
|
52
|
-
# @param key<Object> The key to fetch. This will be run through convert_key.
|
53
|
-
# @param *extras<Array> Default value.
|
54
|
-
#
|
55
|
-
# @return [Object] The value at key or the default value.
|
56
|
-
def fetch(key, *extras)
|
57
|
-
super(convert_key(key), *extras)
|
58
|
-
end
|
59
|
-
|
60
|
-
# @param *indices<Array>
|
61
|
-
# The keys to retrieve values for. These will be run through +convert_key+.
|
62
|
-
#
|
63
|
-
# @return [Array] The values at each of the provided keys
|
64
|
-
def values_at(*indices)
|
65
|
-
indices.collect{|key| self[convert_key(key)]}
|
66
|
-
end
|
67
|
-
|
68
|
-
# @param hash<Hash> The hash to merge with the mash.
|
69
|
-
#
|
70
|
-
# @return [Mash] A new mash with the hash values merged in.
|
71
|
-
def merge(hash, &block)
|
72
|
-
self.dup.update(hash, &block)
|
73
|
-
end
|
74
|
-
|
75
|
-
# @param key<Object>
|
76
|
-
# The key to delete from the mash.\
|
77
|
-
def delete(key)
|
78
|
-
super(convert_key(key))
|
79
|
-
end
|
80
|
-
|
81
|
-
# @return [Hash] The mash as a Hash with string keys.
|
82
|
-
def to_hash
|
83
|
-
Hash.new(default).merge(self)
|
84
|
-
end
|
85
|
-
|
86
|
-
# @param key<Object> The default value for the mash. Defaults to nil.
|
87
|
-
#
|
88
|
-
# @details [Alternatives]
|
89
|
-
# If key is a Symbol and it is a key in the mash, then the default value will
|
90
|
-
# be set to the value matching the key.
|
91
|
-
def default(key = nil)
|
92
|
-
if key.is_a?(String) && include?(key = key.to_sym)
|
93
|
-
self[key]
|
94
|
-
else
|
95
|
-
super(key)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# @param other_hash<Hash>
|
100
|
-
# A hash to update values in the mash with. The keys and the values will be
|
101
|
-
# converted to Mash format.
|
102
|
-
#
|
103
|
-
# @return [Mash] The updated mash.
|
104
|
-
def update(other_hash, &block)
|
105
|
-
sash = self.class.new
|
106
|
-
other_hash.each_pair do |key, value|
|
107
|
-
val = convert_value(value)
|
108
|
-
sash[convert_key(key)] = val
|
109
|
-
end
|
110
|
-
regular_update(sash, &block)
|
111
|
-
end
|
112
|
-
|
113
|
-
# Used to provide the same interface as Hash.
|
114
|
-
#
|
115
|
-
# @return [Sash] This sash unchanged.
|
116
|
-
def symbolize_keys!; self end
|
117
|
-
|
118
|
-
# @return [Hash] The sash as a Hash with stringified keys.
|
119
|
-
def stringify_keys
|
120
|
-
h = Hash.new(default)
|
121
|
-
each { |key, val| h[key.to_sym] = val }
|
122
|
-
h
|
123
|
-
end
|
124
|
-
|
125
|
-
protected
|
126
|
-
# @param key<Object> The key to convert.
|
127
|
-
#
|
128
|
-
# @param [Object]
|
129
|
-
# The converted key. If the key was a string, it will be converted to a
|
130
|
-
# symbol.
|
131
|
-
#
|
132
|
-
# @api private
|
133
|
-
def convert_key(key)
|
134
|
-
key.is_a?(String) ? key.to_sym : key
|
135
|
-
end
|
136
|
-
|
137
|
-
# @param value<Object> The value to convert.
|
138
|
-
#
|
139
|
-
# @return [Object]
|
140
|
-
# The converted value. A Hash or an Array of hashes, will be converted to
|
141
|
-
# their Mash equivalents.
|
142
|
-
#
|
143
|
-
# @api private
|
144
|
-
def convert_value(value)
|
145
|
-
if value.class == Hash
|
146
|
-
value.to_sash
|
147
|
-
elsif value.is_a?(Array)
|
148
|
-
value.collect { |e| convert_value(e) }
|
149
|
-
else
|
150
|
-
value
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
155
|
-
|
156
|
-
|
157
|
-
class ::Hash
|
158
|
-
|
159
|
-
# Convert to Sash. This class has semantics of ActiveSupport's
|
160
|
-
# HashWithIndifferentAccess and we only have it so that people can write
|
161
|
-
# params[:key] instead of params['key'].
|
162
|
-
#
|
163
|
-
# @return [Mash] This hash as a Mash for string or symbol key access.
|
164
|
-
def to_sash
|
165
|
-
hash = Sash.new(self)
|
166
|
-
hash.default = default
|
167
|
-
hash
|
168
|
-
end
|
169
|
-
|
170
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '../../spec_helper'))
|
2
|
-
|
3
|
-
describe Hash do
|
4
|
-
before(:each) do
|
5
|
-
@hash = { :hsh1a => { :hsh2 => { :key3 => "val3" }, :key2 => "val2" }, :key1b => 'val1b' }
|
6
|
-
end
|
7
|
-
|
8
|
-
describe "#deep_merge!" do
|
9
|
-
it "merges two subhashes when they share a key" do
|
10
|
-
@hash.deep_merge!(:hsh1a => { :hsh2 => { :key3a => "val3a" } })
|
11
|
-
@hash.should == { :hsh1a => { :hsh2 => { :key3a => "val3a", :key3 => "val3" }, :key2 => "val2" }, :key1b => 'val1b' }
|
12
|
-
end
|
13
|
-
it "preserves values in the original" do
|
14
|
-
@hash.deep_merge! :other_key => "other_val"
|
15
|
-
@hash[:hsh1a][:key2].should == "val2"
|
16
|
-
@hash[:other_key].should == "other_val"
|
17
|
-
end
|
18
|
-
it "replaces values from the given Hash" do
|
19
|
-
@hash.deep_merge!(:hsh1a => { :hsh2 => { :key3 => "new_val3" }, :key2 => { "other2" => "other_val2" }})
|
20
|
-
@hash[:hsh1a][:hsh2][:key3].should == 'new_val3'
|
21
|
-
@hash[:hsh1a][:key2].should == { "other2" => "other_val2" }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
describe "#deep_set" do
|
27
|
-
it 'should set a new value (single arg)' do
|
28
|
-
@hash.deep_set :new_key, 'new_val'
|
29
|
-
@hash[:new_key].should == 'new_val'
|
30
|
-
end
|
31
|
-
it 'should set a new value (multiple args)' do
|
32
|
-
@hash.deep_set :hsh1a, :hsh2, :new_key, 'new_val'
|
33
|
-
@hash[:hsh1a][:hsh2][:new_key].should == 'new_val'
|
34
|
-
end
|
35
|
-
it 'should replace an existing value (single arg)' do
|
36
|
-
@hash.deep_set :key1b, 'new_val'
|
37
|
-
@hash[:key1b].should == 'new_val'
|
38
|
-
end
|
39
|
-
it 'should replace an existing value (multiple args)' do
|
40
|
-
@hash.deep_set :hsh1a, :hsh2, 'new_val'
|
41
|
-
@hash[:hsh1a][:hsh2].should == 'new_val'
|
42
|
-
end
|
43
|
-
it 'should auto-vivify intermediate hashes' do
|
44
|
-
@hash.deep_set :one, :two, :three, :four, 'new_val'
|
45
|
-
@hash[:one][:two][:three][:four].should == 'new_val'
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "#deep_delete" do
|
50
|
-
it 'should remove the key from the array (multiple args)' do
|
51
|
-
@hash.deep_delete(:hsh1a)
|
52
|
-
@hash[:hsh1a].should be_nil
|
53
|
-
@hash.should == { :key1b => 'val1b'}
|
54
|
-
end
|
55
|
-
it 'should remove the key from the array (multiple args)' do
|
56
|
-
@hash.deep_delete(:hsh1a, :hsh2, :key3)
|
57
|
-
@hash[:hsh1a][:hsh2][:key3].should be_nil
|
58
|
-
@hash.should == {:key1b=>"val1b", :hsh1a=>{:key2=>"val2", :hsh2=>{}}}
|
59
|
-
end
|
60
|
-
it 'should return the value if present (single args)' do
|
61
|
-
returned_val = @hash.deep_delete(:key1b)
|
62
|
-
returned_val.should == 'val1b'
|
63
|
-
end
|
64
|
-
it 'should return the value if present (multiple args)' do
|
65
|
-
returned_val = @hash.deep_delete(:hsh1a, :hsh2, :key3)
|
66
|
-
returned_val.should == 'val3'
|
67
|
-
end
|
68
|
-
it 'should return nil if the key is absent (single arg)' do
|
69
|
-
returned_val = @hash.deep_delete(:hsh1a, :hsh2, :missing_key)
|
70
|
-
returned_val.should be_nil
|
71
|
-
end
|
72
|
-
it 'should return nil if the key is absent (multiple args)' do
|
73
|
-
returned_val = @hash.deep_delete(:missing_key)
|
74
|
-
returned_val.should be_nil
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
@@ -1,312 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '../../spec_helper'))
|
2
|
-
|
3
|
-
class AwesomeHash < Hash
|
4
|
-
end
|
5
|
-
|
6
|
-
describe Sash do
|
7
|
-
before(:each) do
|
8
|
-
@hash = { "str_key" => "strk_val", :sym_key => "symk_val"}
|
9
|
-
@sub = AwesomeHash.new("str_key" => "strk_val", :sym_key => "symk_val")
|
10
|
-
end
|
11
|
-
|
12
|
-
describe "#deep_merge!" do
|
13
|
-
before do
|
14
|
-
@sash = Sash.new :hsh1 => { :hsh2 => { :key3 => "val3" }, :key2 => "val2" }
|
15
|
-
end
|
16
|
-
it "merges two subhashes when they share a key" do
|
17
|
-
@sash.deep_merge!(:hsh1 => { :hsh2 => { :key3a => "val3a" } })
|
18
|
-
@sash.should == { :hsh1 => { :hsh2 => { :key3a => "val3a", :key3 => "val3" }, :key2 => "val2" } }
|
19
|
-
end
|
20
|
-
it "merges two subhashes when they share a symbolized key" do
|
21
|
-
@sash.deep_merge!(:hsh1 => { "hsh2" => { "key3a" => "val3a" } })
|
22
|
-
@sash.should == { :hsh1 => { :hsh2 => { :key3a => "val3a", :key3 => "val3" }, :key2 => "val2" } }
|
23
|
-
end
|
24
|
-
it "preserves values in the original" do
|
25
|
-
@sash.deep_merge! :other_key => "other_val"
|
26
|
-
@sash[:other_key].should == "other_val"
|
27
|
-
@sash[:hsh1][:key2].should == "val2"
|
28
|
-
end
|
29
|
-
|
30
|
-
it "converts all keys into symbols when param is a Hash" do
|
31
|
-
@sash.deep_merge!(:hsh1 => { "hsh2" => { "key3a" => "val3a" } })
|
32
|
-
@sash.should == { :hsh1 => { :hsh2 => { :key3a => "val3a", :key3 => "val3" }, :key2 => "val2" } }
|
33
|
-
end
|
34
|
-
it "converts all Hash values into Sashes if param is a Hash" do
|
35
|
-
@sash.deep_merge!({:hsh1 => { :hsh2 => { :key3a => "val3a" } }, :other1 => { "other2" => "other_val2" }})
|
36
|
-
@sash[:hsh1].should be_an_instance_of(Sash)
|
37
|
-
@sash[:hsh1][:hsh2].should be_an_instance_of(Sash)
|
38
|
-
@sash[:other1].should be_an_instance_of(Sash)
|
39
|
-
end
|
40
|
-
it "replaces values from the given Hash" do
|
41
|
-
@sash.deep_merge!(:hsh1 => { :hsh2 => { :key3 => "new_val3" }, :key2 => { "other2" => "other_val2" }})
|
42
|
-
@sash[:hsh1][:hsh2][:key3].should == 'new_val3'
|
43
|
-
@sash[:hsh1][:key2].should == { :other2 => "other_val2" }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "#initialize" do
|
48
|
-
it 'converts all keys into symbols when param is a Hash' do
|
49
|
-
sash = Sash.new(@hash)
|
50
|
-
sash.keys.any? { |key| key.is_a?(String) }.should be_false
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'converts all pure Hash values into Sashes if param is a Hash' do
|
54
|
-
sash = Sash.new :sym_key => @hash
|
55
|
-
|
56
|
-
sash[:sym_key].should be_an_instance_of(Sash)
|
57
|
-
# sanity check
|
58
|
-
sash[:sym_key][:sym_key].should == "symk_val"
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'does not convert Hash subclass values into Sashes' do
|
62
|
-
sash = Sash.new :sub => @sub
|
63
|
-
sash[:sub].should be_an_instance_of(AwesomeHash)
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'converts all value items if value is an Array' do
|
67
|
-
sash = Sash.new :arry => { :sym_key => [@hash] }
|
68
|
-
|
69
|
-
sash[:arry].should be_an_instance_of(Sash)
|
70
|
-
# sanity check
|
71
|
-
sash[:arry][:sym_key].first[:sym_key].should == "symk_val"
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'delegates to superclass constructor if param is not a Hash' do
|
76
|
-
sash = Sash.new("dash berlin")
|
77
|
-
|
78
|
-
sash["unexisting key"].should == "dash berlin"
|
79
|
-
end
|
80
|
-
end # describe "#initialize"
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
describe "#update" do
|
85
|
-
it 'converts all keys into symbols when param is a Hash' do
|
86
|
-
sash = Sash.new(@hash)
|
87
|
-
sash.update("starry" => "night")
|
88
|
-
|
89
|
-
sash.keys.any?{|key| key.is_a?(String) }.should be_false
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'converts all Hash values into Sashes if param is a Hash' do
|
93
|
-
sash = Sash.new :hash => @hash
|
94
|
-
sash.update(:hash => { :sym_key => "is buggy in Ruby 1.8.6" })
|
95
|
-
|
96
|
-
sash[:hash].should be_an_instance_of(Sash)
|
97
|
-
end
|
98
|
-
end # describe "#update"
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
describe "#[]=" do
|
103
|
-
it 'converts key into symbol' do
|
104
|
-
sash = Sash.new(@hash)
|
105
|
-
sash["str_key"] = { "starry" => "night" }
|
106
|
-
|
107
|
-
sash.keys.any?{|key| key.is_a?(String) }.should be_false
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'converts all Hash value into Sash' do
|
111
|
-
sash = Sash.new :hash => @hash
|
112
|
-
sash[:hash] = { :sym_key => "is buggy in Ruby 1.8.6" }
|
113
|
-
|
114
|
-
sash[:hash].should be_an_instance_of(Sash)
|
115
|
-
end
|
116
|
-
end # describe "#[]="
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
describe "#key?" do
|
121
|
-
before(:each) do
|
122
|
-
@sash = Sash.new(@hash)
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'converts key before lookup' do
|
126
|
-
@sash.key?("str_key").should be_true
|
127
|
-
@sash.key?(:str_key).should be_true
|
128
|
-
|
129
|
-
@sash.key?("sym_key").should be_true
|
130
|
-
@sash.key?(:sym_key).should be_true
|
131
|
-
|
132
|
-
@sash.key?(:rainclouds).should be_false
|
133
|
-
@sash.key?("rainclouds").should be_false
|
134
|
-
end
|
135
|
-
|
136
|
-
it 'is aliased as include?' do
|
137
|
-
@sash.include?("str_key").should be_true
|
138
|
-
@sash.include?(:str_key).should be_true
|
139
|
-
|
140
|
-
@sash.include?("sym_key").should be_true
|
141
|
-
@sash.include?(:sym_key).should be_true
|
142
|
-
|
143
|
-
@sash.include?(:rainclouds).should be_false
|
144
|
-
@sash.include?("rainclouds").should be_false
|
145
|
-
end
|
146
|
-
|
147
|
-
it 'is aliased as member?' do
|
148
|
-
@sash.member?("str_key").should be_true
|
149
|
-
@sash.member?(:str_key).should be_true
|
150
|
-
|
151
|
-
@sash.member?("sym_key").should be_true
|
152
|
-
@sash.member?(:sym_key).should be_true
|
153
|
-
|
154
|
-
@sash.member?(:rainclouds).should be_false
|
155
|
-
@sash.member?("rainclouds").should be_false
|
156
|
-
end
|
157
|
-
end # describe "#key?"
|
158
|
-
|
159
|
-
def arrays_should_be_equal arr1, arr2
|
160
|
-
arr1.sort_by{|s| s.to_s }.should == arr2.sort_by{|s| s.to_s }
|
161
|
-
end
|
162
|
-
|
163
|
-
describe "#dup" do
|
164
|
-
it 'returns instance of Sash' do
|
165
|
-
Sash.new(@hash).dup.should be_an_instance_of(Sash)
|
166
|
-
end
|
167
|
-
|
168
|
-
it 'preserves keys' do
|
169
|
-
sash = Sash.new(@hash)
|
170
|
-
dup = sash.dup
|
171
|
-
|
172
|
-
arrays_should_be_equal sash.keys, dup.keys
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'preserves value' do
|
176
|
-
sash = Sash.new(@hash)
|
177
|
-
dup = sash.dup
|
178
|
-
|
179
|
-
arrays_should_be_equal sash.values, dup.values
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
describe "#to_hash" do
|
186
|
-
it 'returns instance of Hash' do
|
187
|
-
Sash.new(@hash).to_hash.should be_an_instance_of(Hash)
|
188
|
-
end
|
189
|
-
|
190
|
-
it 'preserves keys' do
|
191
|
-
sash = Sash.new(@hash)
|
192
|
-
converted = sash.to_hash
|
193
|
-
arrays_should_be_equal sash.keys, converted.keys
|
194
|
-
end
|
195
|
-
|
196
|
-
it 'preserves value' do
|
197
|
-
sash = Sash.new(@hash)
|
198
|
-
converted = sash.to_hash
|
199
|
-
arrays_should_be_equal sash.values, converted.values
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
describe "#stringify_keys" do
|
206
|
-
it 'returns instance of Sash' do
|
207
|
-
Sash.new(@hash).stringify_keys.should be_an_instance_of(Hash)
|
208
|
-
end
|
209
|
-
|
210
|
-
it 'converts keys to symbols' do
|
211
|
-
sash = Sash.new(@hash)
|
212
|
-
converted = sash.stringify_keys
|
213
|
-
|
214
|
-
converted_keys = converted.keys.sort{|k1, k2| k1.to_s <=> k2.to_s}
|
215
|
-
orig_keys = sash.keys.map{|k| k.to_sym}.sort{|i1, i2| i1.to_s <=> i2.to_s}
|
216
|
-
|
217
|
-
converted_keys.should == orig_keys
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'preserves value' do
|
221
|
-
sash = Sash.new(@hash)
|
222
|
-
converted = sash.stringify_keys
|
223
|
-
|
224
|
-
arrays_should_be_equal sash.values, converted.values
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
describe "#delete" do
|
231
|
-
it 'converts Symbol key into String before deleting' do
|
232
|
-
sash = Sash.new(@hash)
|
233
|
-
|
234
|
-
sash.delete(:sym_key)
|
235
|
-
sash.key?("hash").should be_false
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'works with String keys as well' do
|
239
|
-
sash = Sash.new(@hash)
|
240
|
-
|
241
|
-
sash.delete("str_key")
|
242
|
-
sash.key?("str_key").should be_false
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
describe "#merge" do
|
249
|
-
before(:each) do
|
250
|
-
@sash = Sash.new(@hash).merge(:no => "in between")
|
251
|
-
end
|
252
|
-
|
253
|
-
it 'returns instance of Sash' do
|
254
|
-
@sash.should be_an_instance_of(Sash)
|
255
|
-
end
|
256
|
-
|
257
|
-
it 'merges in give Hash' do
|
258
|
-
@sash["no"].should == "in between"
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
describe "#fetch" do
|
265
|
-
before(:each) do
|
266
|
-
@sash = Sash.new(@hash).merge(:no => "in between")
|
267
|
-
end
|
268
|
-
|
269
|
-
it 'converts key before fetching' do
|
270
|
-
@sash.fetch("no").should == "in between"
|
271
|
-
end
|
272
|
-
|
273
|
-
it 'returns alternative value if key lookup fails' do
|
274
|
-
@sash.fetch("flying", "screwdriver").should == "screwdriver"
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
|
279
|
-
describe "#default" do
|
280
|
-
before(:each) do
|
281
|
-
@sash = Sash.new(:yet_another_technical_revolution)
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'returns default value unless key exists in sash' do
|
285
|
-
@sash.default("peak oil is now behind, baby").should == :yet_another_technical_revolution
|
286
|
-
end
|
287
|
-
|
288
|
-
it 'returns existing value if key is String and exists in sash' do
|
289
|
-
@sash.update("no" => "in between")
|
290
|
-
@sash.default("no").should == "in between"
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
|
295
|
-
describe "#values_at" do
|
296
|
-
before(:each) do
|
297
|
-
@sash = Sash.new(@hash).merge(:no => "in between")
|
298
|
-
end
|
299
|
-
|
300
|
-
it 'is indifferent to whether keys are strings or symbols' do
|
301
|
-
@sash.values_at("sym_key", :str_key, :no).should == ["symk_val", "strk_val", "in between"]
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
|
306
|
-
describe "#symbolize_keys!" do
|
307
|
-
it 'returns the sash itself' do
|
308
|
-
sash = Sash.new(@hash)
|
309
|
-
sash.symbolize_keys!.object_id.should == sash.object_id
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|