gorillib 0.5.0 → 0.5.2
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/.gitignore +3 -0
- data/.gitmodules +3 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -16
- data/Rakefile +2 -74
- data/away/aliasing_spec.rb +180 -0
- data/away/confidence.rb +17 -0
- data/away/stub_module.rb +33 -0
- data/gorillib.gemspec +31 -246
- data/lib/gorillib/collection/model_collection.rb +1 -0
- data/lib/gorillib/data_munging.rb +0 -1
- data/lib/gorillib/hashlike/slice.rb +2 -0
- data/lib/gorillib/model/field.rb +2 -2
- data/lib/gorillib/model/serialization.rb +9 -4
- data/lib/gorillib/model/serialization/csv.rb +1 -0
- data/lib/gorillib/model/serialization/lines.rb +2 -0
- data/lib/gorillib/model/serialization/tsv.rb +1 -0
- data/lib/gorillib/pathname.rb +1 -1
- data/lib/gorillib/pathname/utils.rb +6 -0
- data/lib/gorillib/string/inflector.rb +1 -1
- data/lib/gorillib/system.rb +1 -0
- data/lib/gorillib/system/runner.rb +36 -0
- data/lib/gorillib/type/ip_address.rb +2 -2
- data/lib/gorillib/version.rb +3 -0
- data/old/lib/gorillib/hash/indifferent_access.rb +207 -0
- data/old/lib/gorillib/hash/tree_merge.rb +4 -0
- data/old/lib/gorillib/hashlike/tree_merge.rb +49 -0
- data/old/lib/gorillib/metaprogramming/cattr_accessor.rb +79 -0
- data/old/lib/gorillib/metaprogramming/mattr_accessor.rb +61 -0
- data/old/lib/gorillib/receiver.rb +402 -0
- data/old/lib/gorillib/receiver/active_model_shim.rb +32 -0
- data/old/lib/gorillib/receiver/acts_as_hash.rb +195 -0
- data/old/lib/gorillib/receiver/acts_as_loadable.rb +42 -0
- data/old/lib/gorillib/receiver/locale/en.yml +27 -0
- data/old/lib/gorillib/receiver/tree_diff.rb +74 -0
- data/old/lib/gorillib/receiver/validations.rb +30 -0
- data/old/lib/gorillib/receiver_model.rb +21 -0
- data/old/lib/gorillib/struct/acts_as_hash.rb +108 -0
- data/old/lib/gorillib/struct/hashlike_iteration.rb +0 -0
- data/old/spec/gorillib/hash/indifferent_access_spec.rb +391 -0
- data/old/spec/gorillib/metaprogramming/cattr_accessor_spec.rb +43 -0
- data/old/spec/gorillib/metaprogramming/mattr_accessor_spec.rb +45 -0
- data/old/spec/gorillib/receiver/receiver/acts_as_hash_spec.rb +295 -0
- data/old/spec/gorillib/receiver_spec.rb +551 -0
- data/old/spec/gorillib/struct/acts_as_hash_fuzz_spec.rb +71 -0
- data/old/spec/gorillib/struct/acts_as_hash_spec.rb +422 -0
- data/spec/gorillib/array/compact_blank_spec.rb +2 -2
- data/spec/gorillib/collection_spec.rb +6 -6
- data/spec/gorillib/factories_spec.rb +2 -2
- data/spec/gorillib/hashlike_spec.rb +2 -1
- data/spec/gorillib/model/defaults_spec.rb +3 -3
- data/spec/gorillib/model/serialization/csv_spec.rb +35 -0
- data/spec/gorillib/model/serialization/tsv_spec.rb +20 -4
- data/spec/gorillib/model/serialization_spec.rb +3 -3
- data/spec/spec_helper.rb +6 -1
- data/spec/support/factory_test_helpers.rb +2 -2
- data/spec/support/gorillib_test_helpers.rb +4 -4
- data/spec/support/hashlike_fuzzing_helper.rb +1 -15
- data/spec/support/hashlike_helper.rb +5 -1
- data/spec/support/model_test_helpers.rb +12 -1
- metadata +192 -168
- data/notes/HOWTO.md +0 -22
- data/notes/bucket.md +0 -155
- data/notes/builder.md +0 -170
- data/notes/collection.md +0 -81
- data/notes/factories.md +0 -86
- data/notes/model-overlay.md +0 -209
- data/notes/model.md +0 -135
- data/notes/structured-data-classes.md +0 -127
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
require 'gorillib/hashlike'
|
3
|
+
require 'gorillib/struct/acts_as_hash'
|
4
|
+
require 'gorillib/hash/indifferent_access'
|
5
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_fuzzing_helper')
|
6
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_helper')
|
7
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_struct_helper')
|
8
|
+
|
9
|
+
#
|
10
|
+
# Don't test the built-in Struct methods.
|
11
|
+
#
|
12
|
+
# Also, all the enumerable methods behave differently -- they build off each
|
13
|
+
# (which iterates like an array), not each_pair (which iterates like a hash)
|
14
|
+
#
|
15
|
+
STRUCT_HASHLIKE_METHODS_TO_SKIP = [:each, :flatten, :clear, :values_at] +
|
16
|
+
Enumerable.public_instance_methods.map(&:to_sym) +
|
17
|
+
HashlikeHelper::HASH_METHODS_MISSING_FROM_VERSION
|
18
|
+
|
19
|
+
describe Gorillib::Struct::ActsAsHash do
|
20
|
+
if ENV['FULL_SPECS']
|
21
|
+
include HashlikeFuzzingHelper
|
22
|
+
|
23
|
+
describe "vs Hash" do
|
24
|
+
before do
|
25
|
+
@total = 0
|
26
|
+
@hsh = HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT.dup
|
27
|
+
@hshlike = StructUsingHashlike.new.merge(HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT)
|
28
|
+
end
|
29
|
+
|
30
|
+
( HashlikeHelper::METHODS_TO_TEST - STRUCT_HASHLIKE_METHODS_TO_SKIP ).each do |method_to_test|
|
31
|
+
describe "##{method_to_test}" do
|
32
|
+
|
33
|
+
(HashlikeFuzzingHelper::INPUTS_FOR_ALL_HASHLIKES).each do |input|
|
34
|
+
next if HashlikeFuzzingHelper::SPECIAL_CASES_FOR_HASHLIKE_STRUCT[method_to_test].include?(input)
|
35
|
+
|
36
|
+
it "on #{input.inspect}" do
|
37
|
+
behaves_the_same(@hsh, @hshlike, method_to_test, input)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "vs Gorillib::HashWithIndifferentSymbolKeys" do
|
45
|
+
before do
|
46
|
+
@total = 0
|
47
|
+
@hsh = Gorillib::HashWithIndifferentSymbolKeys.new_from_hash_copying_default(
|
48
|
+
HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT)
|
49
|
+
@hshlike = StructUsingHashlike.new.merge(
|
50
|
+
HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT)
|
51
|
+
end
|
52
|
+
|
53
|
+
( HashlikeHelper::METHODS_TO_TEST - STRUCT_HASHLIKE_METHODS_TO_SKIP
|
54
|
+
).each do |method_to_test|
|
55
|
+
describe "##{method_to_test}" do
|
56
|
+
|
57
|
+
( HashlikeFuzzingHelper::INPUTS_WHEN_INDIFFERENT_ACCESS +
|
58
|
+
HashlikeFuzzingHelper::INPUTS_FOR_ALL_HASHLIKES
|
59
|
+
).each do |input|
|
60
|
+
next if HashlikeFuzzingHelper::SPECIAL_CASES_FOR_HASHLIKE_STRUCT[method_to_test].include?(input)
|
61
|
+
|
62
|
+
it "on #{input.inspect}" do
|
63
|
+
behaves_the_same(@hsh, @hshlike, method_to_test, input)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,422 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
require 'gorillib/hashlike'
|
3
|
+
require 'gorillib/struct/acts_as_hash'
|
4
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_via_delegation')
|
5
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_helper')
|
6
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_fuzzing_helper')
|
7
|
+
require GORILLIB_ROOT_DIR('spec/support/hashlike_struct_helper')
|
8
|
+
require GORILLIB_ROOT_DIR('spec/hashlike/hashlike_behavior_spec')
|
9
|
+
|
10
|
+
describe Gorillib::Struct::ActsAsHash do
|
11
|
+
|
12
|
+
before do
|
13
|
+
@hshlike = StructUsingHashlike.new.merge(HashlikeHelper::BASE_HSH.dup)
|
14
|
+
@empty_hshlike = StructUsingHashlike.new
|
15
|
+
@hshlike_with_array_vals = StructUsingHashlike.new.merge(HashlikeHelper::BASE_HSH_WITH_ARRAY_VALS.dup)
|
16
|
+
#
|
17
|
+
@hshlike_subklass = Class.new(StructUsingHashlike)
|
18
|
+
@hshlike_subklass_inst = @hshlike_subklass.new.merge(HashlikeHelper::BASE_HSH.dup)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# ===========================================================================
|
23
|
+
#
|
24
|
+
# Fundamental behavior
|
25
|
+
|
26
|
+
describe '#[] and #[]= and #store' do
|
27
|
+
it_should_behave_like :hashlike_store_and_retrieve
|
28
|
+
it_should_behave_like :references_string_and_symbol_keys_equivalently, ArgumentError
|
29
|
+
it 'reject unknown keys' do
|
30
|
+
lambda{ @hshlike[:fnord] = 69 }.should raise_error NameError, /no member 'fnord' in struct/
|
31
|
+
lambda{ @hshlike[:fnord] }.should raise_error NameError, /no member 'fnord' in struct/
|
32
|
+
@hshlike.delete(:fnord).should be_nil
|
33
|
+
end
|
34
|
+
it 'accepts defined but unset keys' do
|
35
|
+
@hshlike[:new_key].should be_nil
|
36
|
+
@hshlike[:new_key] = 69
|
37
|
+
@hshlike[:new_key].should == 69
|
38
|
+
end
|
39
|
+
it 'does not allow nil, Object, and other non-stringy keys' do
|
40
|
+
lambda{ @hshlike[300] = :i_haz_num }.should raise_error(IndexError, /offset 300 too large for struct/)
|
41
|
+
lambda{ @hshlike[nil] = :i_haz_nil }.should raise_error(TypeError, "no implicit conversion from nil to integer")
|
42
|
+
obj = Object.new
|
43
|
+
lambda{ @hshlike[obj] = :i_haz_obj }.should raise_error(TypeError, "can't convert Object into Integer")
|
44
|
+
def obj.to_sym() :c ; end
|
45
|
+
lambda{ @hshlike[obj] = :i_haz_obj }.should raise_error(TypeError, "can't convert Object into Integer")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#delete' do
|
50
|
+
it 'removes the key/value association and returns the value' do
|
51
|
+
@hshlike.delete(:a).should == 100
|
52
|
+
@hshlike.delete(:is_missing).should be_nil
|
53
|
+
@hshlike.delete(:false_val).should == false
|
54
|
+
@hshlike.should be_hash_eql({ :b => 200, :c => 300, :nil_val => nil })
|
55
|
+
end
|
56
|
+
describe 'with optional code block' do
|
57
|
+
it 'returns the value of executing the block (passing in the key)' do
|
58
|
+
set_in_block = nil
|
59
|
+
ret_val = @hshlike.delete(:is_missing){|k| set_in_block = "got: #{k}" ; "hello!" }
|
60
|
+
set_in_block.should == "got: is_missing"
|
61
|
+
ret_val.should == "hello!"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
it 'will have a nil value but will still include? key after deleting' do
|
65
|
+
@hshlike.should include(:a)
|
66
|
+
@hshlike.delete(:a)
|
67
|
+
@hshlike.should include(:a)
|
68
|
+
@hshlike[:a].should be_nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#keys' do
|
73
|
+
it 'lists keys, even where values are nil' do
|
74
|
+
@hshlike.keys.should be_array_eql([:a, :b, :c, :nil_val, :false_val, :new_key])
|
75
|
+
@hshlike[:nil_val].should be_nil
|
76
|
+
end
|
77
|
+
it 'is the full list of members, even when nothing has been set' do
|
78
|
+
@empty_hshlike.keys.should be_array_eql([:a, :b, :c, :nil_val, :false_val, :new_key])
|
79
|
+
end
|
80
|
+
it 'is the symbolized members list' do
|
81
|
+
@empty_hshlike.keys.map(&:to_s).should == @empty_hshlike.members.map(&:to_s)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# ===========================================================================
|
86
|
+
#
|
87
|
+
# Iteration
|
88
|
+
|
89
|
+
describe '#each_pair' do
|
90
|
+
describe 'with block' do
|
91
|
+
it_should_behave_like :each_pair_on_stringlike_fixed_keys, :each_pair
|
92
|
+
end
|
93
|
+
it_should_behave_like :with_no_block_returns_enumerator, :each_pair
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#each' do
|
97
|
+
describe 'with block' do
|
98
|
+
it 'calls block once for each *val* in hsh !like array not hash!' do
|
99
|
+
seen_arg1 = []
|
100
|
+
seen_arg2 = []
|
101
|
+
@hshlike.each{|arg1,arg2| seen_arg1 << arg1 ; seen_arg2 << arg2 }
|
102
|
+
seen_arg1.should be_array_eql([100, 200, 300, nil, false, nil])
|
103
|
+
seen_arg2.should be_array_eql([nil, nil, nil, nil, nil, nil])
|
104
|
+
end
|
105
|
+
it 'with arity 1, returns keys only' do
|
106
|
+
seen_args = []
|
107
|
+
@hshlike.each{|arg| seen_args << arg }
|
108
|
+
seen_args.should be_array_eql([100, 200, 300, nil, false, nil])
|
109
|
+
end
|
110
|
+
it 'handles array keys' do
|
111
|
+
seen_args = []
|
112
|
+
@hshlike_with_array_vals.each{|arg1, arg2, arg3| seen_args << [arg1, arg2, arg3] }
|
113
|
+
seen_args.should be_array_eql([[100, 111, nil], [200, nil, nil], [1, [2, 3, [4, 5, 6]], nil], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil]])
|
114
|
+
seen_args = []
|
115
|
+
@hshlike_with_array_vals.each{|(arg1, arg2), arg3| seen_args << [arg1, arg2, arg3] }
|
116
|
+
seen_args.should be_array_eql([[100, nil, 111], [200, nil, nil], [1, nil, [2, 3, [4, 5, 6]]], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil]])
|
117
|
+
end
|
118
|
+
it 'returns self' do
|
119
|
+
ret_val = @hshlike.each{|k,v| 3 }
|
120
|
+
ret_val.should equal(@hshlike)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
it_should_behave_like :with_no_block_returns_enumerator, :each
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#each_key' do
|
127
|
+
describe 'with block' do
|
128
|
+
it_should_behave_like :each_key_on_stringlike_fixed_keys
|
129
|
+
end
|
130
|
+
it_should_behave_like :with_no_block_returns_enumerator, :each_key
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#each_value' do
|
134
|
+
describe 'with block' do
|
135
|
+
it_should_behave_like :each_value_on_stringlike_fixed_keys
|
136
|
+
end
|
137
|
+
it_should_behave_like :with_no_block_returns_enumerator, :each_value
|
138
|
+
end
|
139
|
+
|
140
|
+
# ===========================================================================
|
141
|
+
#
|
142
|
+
# Retrieval and Membership
|
143
|
+
|
144
|
+
describe '#values' do
|
145
|
+
it 'returns a new array populated with the values from hsh even when they were never set' do
|
146
|
+
@hshlike.values.should be_array_eql([100, 200, 300, nil, false, nil])
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#values_at' do
|
151
|
+
it 'takes positional, not symbol args' do
|
152
|
+
@hshlike.values_at(1, 0, 3, 5).should == [200, 100, nil, nil]
|
153
|
+
@hshlike.values_at(1, 1, 5, 3, 2, 5).should == [200, 200, nil, nil, 300, nil]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#values_of' do
|
158
|
+
it_should_behave_like :hashlike_values_at_or_of, :values_of
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#length' do
|
162
|
+
it 'returns the number of key/value pairs in the hashlike' do
|
163
|
+
@hshlike.length.should == 6
|
164
|
+
@hshlike.length.should == @hshlike.members.length
|
165
|
+
@hshlike.delete(:a)
|
166
|
+
@hshlike.delete(:b)
|
167
|
+
@hshlike.length.should == 6
|
168
|
+
end
|
169
|
+
it 'is always the length of #members, regardless of contents' do
|
170
|
+
@empty_hshlike.length.should == 6
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '#size' do
|
175
|
+
it 'returns the number of key/value pairs in the hashlike' do
|
176
|
+
@hshlike.size.should == 6
|
177
|
+
@hshlike.size.should == @hshlike.members.size
|
178
|
+
@hshlike.delete(:a)
|
179
|
+
@hshlike.delete(:b)
|
180
|
+
@hshlike.size.should == 6
|
181
|
+
end
|
182
|
+
it 'is always the length of #members, regardless of contents' do
|
183
|
+
@empty_hshlike.size.should == 6
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '#has_key?' do
|
188
|
+
it_should_behave_like :hashlike_has_key_predefined_always_present, :has_key?
|
189
|
+
it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :has_key?
|
190
|
+
end
|
191
|
+
|
192
|
+
describe '#include?' do
|
193
|
+
it_should_behave_like :hashlike_has_key_predefined_always_present, :include?
|
194
|
+
it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :include?
|
195
|
+
end
|
196
|
+
|
197
|
+
describe '#key?' do
|
198
|
+
it_should_behave_like :hashlike_has_key_predefined_always_present, :key?
|
199
|
+
it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :key?
|
200
|
+
end
|
201
|
+
|
202
|
+
describe '#member?' do
|
203
|
+
it_should_behave_like :hashlike_has_key_predefined_always_present, :member?
|
204
|
+
it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :member?
|
205
|
+
end
|
206
|
+
|
207
|
+
describe '#has_value?' do
|
208
|
+
it_should_behave_like :hashlike_has_value?, :has_value?
|
209
|
+
end
|
210
|
+
|
211
|
+
describe '#value?' do
|
212
|
+
it_should_behave_like :hashlike_has_value?, :value?
|
213
|
+
end
|
214
|
+
|
215
|
+
describe '#fetch' do
|
216
|
+
it 'returns a value from the hashlike for the given key' do
|
217
|
+
@hshlike.fetch(:a).should == 100
|
218
|
+
@hshlike.fetch(:c).should == 300
|
219
|
+
@hshlike.fetch(:nil_val).should == nil
|
220
|
+
end
|
221
|
+
describe 'on a missing key' do
|
222
|
+
it 'with no other arguments, raises a +KeyError+ exception' do
|
223
|
+
lambda{ @hshlike.fetch(:is_missing) }.should raise_error(KeyError, 'key not found: :is_missing')
|
224
|
+
end
|
225
|
+
it 'if block given, runs the block with the given key and returns its value' do
|
226
|
+
set_in_block = nil
|
227
|
+
ret_val = @hshlike.fetch(:is_missing){|k| set_in_block = "got: #{k}" ; "hello!" }
|
228
|
+
ret_val.should == "hello!"
|
229
|
+
set_in_block.should == "got: is_missing"
|
230
|
+
end
|
231
|
+
it 'if default given, returns the default arg' do
|
232
|
+
ret_val = @hshlike.fetch(:is_missing, :returned_as_default)
|
233
|
+
ret_val.should == :returned_as_default
|
234
|
+
end
|
235
|
+
it 'if block and default are both given, issues a warning and runs the block' do
|
236
|
+
set_in_block = nil
|
237
|
+
ret_val = @hshlike.fetch(:is_missing, :spurious_default){|k| set_in_block = "got: #{k}" ; "hello!" }
|
238
|
+
ret_val.should == "hello!"
|
239
|
+
set_in_block.should == "got: is_missing"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
it 'something something convert_key' unless ENV['QUIET_RSPEC']
|
243
|
+
end
|
244
|
+
|
245
|
+
describe '#key' do
|
246
|
+
it_should_behave_like :hashlike_key
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '#assoc' do
|
250
|
+
it_should_behave_like :hashlike_assoc
|
251
|
+
end
|
252
|
+
|
253
|
+
describe '#rassoc' do
|
254
|
+
it_should_behave_like :hashlike_rassoc
|
255
|
+
end
|
256
|
+
|
257
|
+
describe '#empty?' do
|
258
|
+
it 'returns true if the hashlike contains only nil values, false otherwise' do
|
259
|
+
@hshlike.empty?.should == false
|
260
|
+
@empty_hshlike.empty?.should == true
|
261
|
+
@empty_hshlike[:a] = false
|
262
|
+
@empty_hshlike.empty?.should == false
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# ===========================================================================
|
267
|
+
#
|
268
|
+
# Update, merge!, merge
|
269
|
+
#
|
270
|
+
|
271
|
+
describe 'update' do
|
272
|
+
it_should_behave_like :merging_method, :update
|
273
|
+
it_should_behave_like :merging_method_with_struct_keys, :update
|
274
|
+
it_should_behave_like :merging_method_inplace, :update
|
275
|
+
end
|
276
|
+
|
277
|
+
describe '#merge!' do
|
278
|
+
it_should_behave_like :merging_method, :merge!
|
279
|
+
it_should_behave_like :merging_method_with_struct_keys, :merge!
|
280
|
+
it_should_behave_like :merging_method_inplace, :merge!
|
281
|
+
end
|
282
|
+
|
283
|
+
describe '#merge' do
|
284
|
+
it_should_behave_like :merging_method, :merge
|
285
|
+
it_should_behave_like :merging_method_with_struct_keys, :merge
|
286
|
+
it_should_behave_like :merging_method_returning_new, :merge
|
287
|
+
end
|
288
|
+
|
289
|
+
# ===========================================================================
|
290
|
+
#
|
291
|
+
# Filters
|
292
|
+
|
293
|
+
shared_examples_for :hashlike_filter_fixed_keys do |method_to_test|
|
294
|
+
it 'passes every key-value pair to block' do
|
295
|
+
seen_args = []
|
296
|
+
ret_val = @hshlike.send(method_to_test){|key,val| seen_args << [key, val] ; val && (val.to_i > 150) }
|
297
|
+
#
|
298
|
+
seen_args.should be_array_eql([[:a, 100], [:b, 200], [:c, 300], [:nil_val, nil], [:false_val, false], [:new_key, nil]])
|
299
|
+
end
|
300
|
+
it 'adapts to the arity of the block' do
|
301
|
+
seen_args = []
|
302
|
+
ret_val = @hshlike.send(method_to_test){|arg| seen_args << [arg] ; @hshlike[arg] && (@hshlike[arg].to_i > 150) }
|
303
|
+
#
|
304
|
+
seen_args.should be_array_eql([[:a], [:b], [:c], [:nil_val], [:false_val], [:new_key]])
|
305
|
+
end
|
306
|
+
describe 'with no block' do
|
307
|
+
it('returns an enumerator'){ @hshlike.send(method_to_test).should enumerate_method(@hshlike, method_to_test) }
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe '#reject!' do
|
312
|
+
it_should_behave_like :hashlike_filter_fixed_keys, :reject!
|
313
|
+
it_should_behave_like :rejection_filter, :reject!
|
314
|
+
it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :reject!, false
|
315
|
+
end
|
316
|
+
|
317
|
+
describe '#select!' do
|
318
|
+
it_should_behave_like :hashlike_filter_fixed_keys, :select!
|
319
|
+
it_should_behave_like :selection_filter, :select!
|
320
|
+
it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :select!, true
|
321
|
+
end
|
322
|
+
|
323
|
+
describe '#delete_if' do
|
324
|
+
it_should_behave_like :hashlike_filter_fixed_keys, :delete_if
|
325
|
+
it_should_behave_like :rejection_filter, :delete_if
|
326
|
+
it_should_behave_like :filter_modifies_self_returns_self, :delete_if, false
|
327
|
+
end
|
328
|
+
|
329
|
+
describe '#keep_if' do
|
330
|
+
it_should_behave_like :hashlike_filter_fixed_keys, :keep_if
|
331
|
+
it_should_behave_like :selection_filter, :keep_if
|
332
|
+
it_should_behave_like :filter_modifies_self_returns_self, :keep_if, true
|
333
|
+
end
|
334
|
+
|
335
|
+
# describe '#reject' do
|
336
|
+
# it_should_behave_like :hashlike_filter_fixed_keys, :select
|
337
|
+
# it_should_behave_like :selection_filter, :select
|
338
|
+
# it_should_behave_like :filter_does_not_modify_self_returns_same_class, :reject, false
|
339
|
+
# end
|
340
|
+
#
|
341
|
+
# describe '#select' do
|
342
|
+
# it_should_behave_like :hashlike_filter_fixed_keys, :select
|
343
|
+
# it_should_behave_like :selection_filter, :select
|
344
|
+
# it_should_behave_like :filter_does_not_modify_self_returns_same_class, :select, true
|
345
|
+
# end
|
346
|
+
|
347
|
+
describe '#clear' do
|
348
|
+
it_should_behave_like :hashlike_clear
|
349
|
+
end
|
350
|
+
|
351
|
+
# ===========================================================================
|
352
|
+
#
|
353
|
+
# Conversion
|
354
|
+
|
355
|
+
describe '#to_hash' do
|
356
|
+
it 'returns a new Hash with each key set to its associated value' do
|
357
|
+
ret_val = @hshlike.to_hash
|
358
|
+
ret_val.should be_an_instance_of(Hash)
|
359
|
+
ret_val.should == {:a=>100, :b=>200, :c=>300, :nil_val=>nil, :false_val=>false, :new_key=>nil}
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
if (RUBY_VERSION >= '1.9')
|
364
|
+
describe '#invert' do
|
365
|
+
it 'returns a new Hash using the values as keys, and the keys as values' do
|
366
|
+
ret_val = @hshlike.invert
|
367
|
+
ret_val.should == { 100 => :a, 200 => :b, 300 => :c, nil => :new_key, false => :false_val }
|
368
|
+
end
|
369
|
+
it 'with duplicate values, the result will contain only one of them as a key' do
|
370
|
+
@hshlike[:a] = 999
|
371
|
+
@hshlike[:new_key] = 999
|
372
|
+
@hshlike.invert.should == { 999 => :new_key, 200 => :b, 300 => :c, nil => :nil_val, false => :false_val }
|
373
|
+
end
|
374
|
+
it 'returns a Hash, not a self.class' do
|
375
|
+
ret_val = @hshlike.invert
|
376
|
+
ret_val.should be_an_instance_of(Hash)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
describe '#flatten' do
|
381
|
+
it 'with no arg returns a one-dimensional flattening' do
|
382
|
+
ret_val = @hshlike_with_array_vals.flatten
|
383
|
+
ret_val.should == [ :a, [100, 111], :b, 200, :c, [1, [2, 3, [4, 5, 6]]], :nil_val, nil, :false_val, nil, :new_key, nil ]
|
384
|
+
end
|
385
|
+
it 'with no arg is same as level = 1' do
|
386
|
+
@hshlike_with_array_vals.flatten(1).should == @hshlike_with_array_vals.flatten
|
387
|
+
end
|
388
|
+
it 'with level == nil, returns a complete flattening' do
|
389
|
+
ret_val = @hshlike_with_array_vals.flatten(nil)
|
390
|
+
ret_val.should == [ :a, 100, 111, :b, 200, :c, 1, 2, 3, 4, 5, 6, :nil_val, nil, :false_val, nil, :new_key, nil ]
|
391
|
+
end
|
392
|
+
it 'with an arg, flattens to that level (0)' do
|
393
|
+
ret_val = @hshlike_with_array_vals.flatten(0)
|
394
|
+
ret_val.should == [ [:a, [100, 111]], [:b, 200], [:c, [1, [2, 3, [4, 5, 6]]]], [:nil_val, nil], [:false_val, nil], [:new_key, nil]]
|
395
|
+
end
|
396
|
+
it 'with an arg, flattens to that level (3)' do
|
397
|
+
ret_val = @hshlike_with_array_vals.flatten(3)
|
398
|
+
ret_val.should == [ :a, 100, 111, :b, 200, :c, 1, 2, 3, [4, 5, 6], :nil_val, nil, :false_val, nil, :new_key, nil ]
|
399
|
+
end
|
400
|
+
it 'with an arg, flattens to that level (4)' do
|
401
|
+
ret_val = @hshlike_with_array_vals.flatten(4)
|
402
|
+
ret_val.should == [ :a, 100, 111, :b, 200, :c, 1, 2, 3, 4, 5, 6, :nil_val, nil, :false_val, nil, :new_key, nil ]
|
403
|
+
ret_val.should == @hshlike_with_array_vals.flatten(999)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
# ===========================================================================
|
409
|
+
#
|
410
|
+
# Sanity check
|
411
|
+
|
412
|
+
it 'built test objects correctly' do
|
413
|
+
@hshlike_subklass .should < @hshlike.class
|
414
|
+
@hshlike_subklass .should_not == @hshlike.class
|
415
|
+
@hshlike_subklass_inst .should be_a(StructUsingHashlike)
|
416
|
+
@hshlike_subklass_inst .should be_a(@hshlike_subklass)
|
417
|
+
@hshlike_subklass_inst .should_not be_an_instance_of(StructUsingHashlike)
|
418
|
+
@hshlike .should_not be_a(@hshlike_subklass)
|
419
|
+
@hshlike .should be_an_instance_of(StructUsingHashlike)
|
420
|
+
end
|
421
|
+
|
422
|
+
end
|