hashmodel 0.1.1

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.
@@ -0,0 +1,14 @@
1
+ module MikBe
2
+ class HashModel
3
+ module VERSION # :nodoc:
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ TINY = 1
7
+ PRE = nil
8
+
9
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
10
+
11
+ SUMMARY = "HashModel #{STRING}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,774 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module MikBe
4
+
5
+ # RSpec's change just does not work with arrays in tests because of how Ruby changes the data arrays point to
6
+ # So we have to manually check before and after
7
+
8
+ describe "HashModel" do
9
+
10
+ before(:each) do
11
+ @records = [
12
+ {:switch => ["-x", "--xtended"], :parameter => {:type => String, :require => true}, :description => "Xish stuff"},
13
+ {:switch => ["-y", "--why"], :description => "lucky what?"},
14
+ {:switch => "-z", :parameter => {:type => String}, :description => "zee svitch zu moost calz"},
15
+ ]
16
+ @hm = HashModel.new(:raw_data=>@records)
17
+
18
+ @records2 = [
19
+ {:switch => ["-p", "--pea"], :parameter => {:type => Hash, :require => false}, :description => "Pea soup"},
20
+ {:switch => ["-q", "--quit"], :description => "exit the game"},
21
+ {:switch => "-r", :parameter => {:type => Fixnum}, :description => "Arrrrrrrrrrgh!"},
22
+ ]
23
+ @hm2 = HashModel.new(:raw_data=>@records2)
24
+
25
+ @flat_records = [
26
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
27
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
28
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1}, {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1},
29
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2}
30
+ ]
31
+
32
+ @flat_records2 =[
33
+ {:switch=>"-p", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>0, :hm_group_id=>0},
34
+ {:switch=>"--pea", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>1, :hm_group_id=>0},
35
+ {:switch=>"-q", :description=>"exit the game", :hm_id=>2, :hm_group_id=>1},
36
+ {:switch=>"--quit", :description=>"exit the game", :hm_id=>3, :hm_group_id=>1},
37
+ {:switch=>"-r", :parameter=>{:type=>Fixnum}, :description=>"Arrrrrrrrrrgh!", :hm_id=>4, :hm_group_id=>2}
38
+ ]
39
+
40
+ @flat_records_all = [
41
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
42
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
43
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
44
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1},
45
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2},
46
+ {:switch=>"-p", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>5, :hm_group_id=>3},
47
+ {:switch=>"--pea", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>6, :hm_group_id=>3},
48
+ {:switch=>"-q", :description=>"exit the game", :hm_id=>7, :hm_group_id=>4},
49
+ {:switch=>"--quit", :description=>"exit the game", :hm_id=>8, :hm_group_id=>4},
50
+ {:switch=>"-r", :parameter=>{:type=>Fixnum}, :description=>"Arrrrrrrrrrgh!", :hm_id=>9, :hm_group_id=>5}
51
+ ]
52
+
53
+ end
54
+
55
+ describe "general properties" do
56
+
57
+ describe "raw data" do
58
+
59
+ it "should always allow access to the raw, unflattened records" do
60
+ @hm.should respond_to(:raw_data)
61
+ end
62
+
63
+ it "should have raw data equal to the data that is input" do
64
+ @hm.raw_data.should == @records
65
+ end
66
+
67
+ it "should clear the raw data when clear is called" do
68
+ @hm = HashModel.new
69
+ @hm << @records[0]
70
+ proc{@hm.clear}.should change(@hm, :raw_data)
71
+ .from([{:switch => ["-x", "--xtended"], :parameter => {:type => String, :require => true}, :description => "Xish stuff"}])
72
+ .to([])
73
+ end
74
+
75
+ it "should only allow arrays to be set as the raw data" do
76
+ proc {@hm.raw_data = "string"}.should raise_error
77
+ end
78
+
79
+ it "should allow arrays to be set as the raw data" do
80
+ proc {@hm.raw_data = [ { :switch => ["-x", "--xtended"] } ] }.should_not raise_error
81
+ end
82
+
83
+ it "should allow nil to be set as the raw data" do
84
+ proc {@hm.raw_data = nil }.should_not raise_error
85
+ end
86
+
87
+ end # "raw data"
88
+
89
+ end # "general properties"
90
+
91
+ describe "adding records" do
92
+
93
+ it "should allow a hash of values to be added" do
94
+ proc { @hm << {:switch => ["-x", "--xtended"], :description => "Xish stuff"} }.should_not raise_error
95
+ end
96
+
97
+ it "should allow a hash of values to be added using the keyword 'add'" do
98
+ proc { @hm.add(:switch => ["-x", "--xtended"], :description => "Xish stuff") }.should_not raise_error
99
+ end
100
+
101
+ it "should allow an array of hashes to be added as if they were multiple records" do
102
+ proc { @hm << @records }.should_not raise_error
103
+ end
104
+
105
+ it "should allow another HashModel to be added" do
106
+ @hm.add(@hm2).should == @flat_records_all
107
+ end
108
+
109
+ it "should allow an array of HashModels to be added" do
110
+ @hm.add([@hm, @hm2])
111
+ @hm.should == [
112
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
113
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
114
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
115
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1},
116
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2},
117
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>5, :hm_group_id=>3},
118
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>6, :hm_group_id=>3},
119
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>7, :hm_group_id=>4},
120
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>8, :hm_group_id=>4},
121
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>9, :hm_group_id=>5},
122
+ {:switch=>"-p", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>10, :hm_group_id=>6},
123
+ {:switch=>"--pea", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>11, :hm_group_id=>6},
124
+ {:switch=>"-q", :description=>"exit the game", :hm_id=>12, :hm_group_id=>7},
125
+ {:switch=>"--quit", :description=>"exit the game", :hm_id=>13, :hm_group_id=>7},
126
+ {:switch=>"-r", :parameter=>{:type=>Fixnum}, :description=>"Arrrrrrrrrrgh!", :hm_id=>14, :hm_group_id=>8}
127
+ ]
128
+ end
129
+
130
+ it "should raise an error if something other than a hash, an array of hashes, or another HashModel (or an array of them) is added" do
131
+ proc { @hm << ["-x", "--xtended", "Xish stuff"] }.should raise_error
132
+ end
133
+
134
+ context "reserved field names" do
135
+
136
+ it "should raise an error if a protected field name is used" do
137
+ proc { @hm << {:hm_id => 1} }.should raise_error(MikBe::ReservedNameError)
138
+ proc { @hm << {:hm_group_id => 1} }.should raise_error(MikBe::ReservedNameError)
139
+ end
140
+
141
+ it "should raise an error if a reserved field name is used deep within the raw data" do
142
+ proc { @hm.raw_data = [{:switch => "--potato", :should_error=>[:hm_group_id => 1, :another => 2] }] }
143
+ .should raise_error(MikBe::ReservedNameError)
144
+ end
145
+
146
+ it "should raise an error if a reserved field name is used deep within the raw data" do
147
+ proc { @hm = HashModel.new(:raw_data=>[{:switch => "--potato", :should_error=>[:hm_group_id => 1, :another => 2] }] ) }
148
+ .should raise_error(MikBe::ReservedNameError)
149
+ end
150
+
151
+ end
152
+
153
+ it "should allow an array of hashes to be specified when creating the HashModel" do
154
+ proc { HashModel.new(:raw_data=>@records) }.should_not raise_error
155
+ end
156
+
157
+ it "should retain the raw data used when creating the HashModel" do
158
+ @hm.raw_data.should == @records
159
+ end
160
+
161
+ it "should return a HashModel object when adding records using <<" do
162
+ (@hm << @records[0]).class.should == HashModel
163
+ end
164
+
165
+ it "should return the same HashModel instance when adding records using <<" do
166
+ (@hm << @records[0]).object_id.should == @hm.object_id
167
+ end
168
+
169
+ it "should allow chaining of record adds using <<" do
170
+ proc {@hm << @records[0] << @records[1] << @records[2]}.should_not raise_error
171
+ end
172
+
173
+ it "should contain all of the records when chaining record adds" do
174
+ @hm << @records[0] << @records[1] << @records[2]
175
+ @hm.raw_data.should == @records
176
+ end
177
+
178
+ context "using the + sign" do
179
+
180
+ it "should return a HashModel class when adding an Array" do
181
+ (@hm + @records2).class.should == HashModel
182
+ end
183
+
184
+ it "should return a HashModel class when adding a HashModel" do
185
+ (@hm + @hm2).class.should == HashModel
186
+ end
187
+
188
+ it "should return a different HashModel instance" do
189
+ (@hm + @records2).object_id.should_not == @hm.object_id
190
+ end
191
+
192
+ it "should contain the records of both recordsets when adding an Array" do
193
+ (@hm + @records2).raw_data.should == (@records + @records2)
194
+ end
195
+
196
+ it "should contain the records of both recordsets when adding a HashModel" do
197
+ (@hm + @hm2).raw_data.should == (@records + @records2)
198
+ end
199
+
200
+ it "should use the flatten index of the receiver HashModel" do
201
+ hm2 = HashModel.new
202
+ hm2 << {:potato=>7}
203
+ (@hm + hm2).flatten_index.should == :switch
204
+ (hm2 + @hm).flatten_index.should == :potato
205
+ end
206
+
207
+ end # "when using the plus sign"
208
+
209
+ context "using the += sign" do
210
+
211
+ it "should return a HashModel class" do
212
+ (@hm += @records2).class.should == HashModel
213
+ end
214
+
215
+ it "should return the same HashModel instance when using += to add an array" do
216
+ (@hm += @records2).object_id.should == @hm.object_id
217
+ end
218
+
219
+ it "should contain the records of both recordsets when adding an Array" do
220
+ @hm += @records2
221
+ @hm.raw_data.should == (@records + @records2)
222
+ end
223
+
224
+ it "should contain the records of both recordsets when adding a HashModel" do
225
+ @hm += @hm2
226
+ @hm.raw_data.should == (@records + @records2)
227
+ end
228
+
229
+ it "should not alter the added HashModel" do
230
+ proc{@hm += @hm2}.should_not change(@hm2, :raw_data)
231
+ end
232
+
233
+ end # "when using the += sign"
234
+
235
+ context "using the * sign" do
236
+
237
+ it "should return a HashRecord" do
238
+ (@hm * 2).class.should == HashModel
239
+ end
240
+
241
+ it "should return a different HashRecord" do
242
+ (@hm * 2).object_id.should_not == @hm.object_id
243
+ end
244
+
245
+ it "should return a HashModel with twice the amount of raw data if * 2'd" do
246
+ (@hm * 2).raw_data.should == [
247
+ {:switch=>["-x", "--xtended"], :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff"},
248
+ {:switch=>["-y", "--why"], :description=>"lucky what?"},
249
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz"},
250
+ {:switch=>["-x", "--xtended"], :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff"},
251
+ {:switch=>["-y", "--why"], :description=>"lucky what?"},
252
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz"}
253
+ ]
254
+ end
255
+
256
+ end
257
+
258
+ context "using the *= sign" do
259
+
260
+ it "should return the same HashModel" do
261
+ (@hm *= 2).object_id.should == @hm.object_id
262
+ end
263
+
264
+ it "should change current raw to twice its old raw data if *= 2'd" do
265
+ @hm *= 2
266
+ @hm.should == [
267
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
268
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
269
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
270
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1},
271
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2},
272
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>5, :hm_group_id=>3},
273
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>6, :hm_group_id=>3},
274
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>7, :hm_group_id=>4},
275
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>8, :hm_group_id=>4},
276
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>9, :hm_group_id=>5}
277
+ ]
278
+ end
279
+
280
+ end
281
+
282
+ context "using concat" do
283
+
284
+ it "should concatinate using a single Hash" do
285
+ @hm.concat(@records2[0]).should == [
286
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
287
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
288
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
289
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1},
290
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2},
291
+ {:switch=>"-p", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>5, :hm_group_id=>3},
292
+ {:switch=>"--pea", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>6, :hm_group_id=>3}
293
+ ]
294
+ end
295
+
296
+ it "should concatinate using an array" do
297
+ @hm.concat(@records2).should == @flat_records_all
298
+ end
299
+
300
+ it "should concatinate using a HashModel" do
301
+ @hm.concat(@hm2).should == @flat_records_all
302
+ end
303
+
304
+ end
305
+
306
+ context "using push" do
307
+
308
+ it "should add a single Hash" do
309
+ @hm.push(@records2[0]).should == [
310
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
311
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
312
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
313
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1},
314
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2},
315
+ {:switch=>"-p", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>5, :hm_group_id=>3},
316
+ {:switch=>"--pea", :parameter=>{:type=>Hash, :require=>false}, :description=>"Pea soup", :hm_id=>6, :hm_group_id=>3}
317
+ ]
318
+ end
319
+
320
+ it "should add an array" do
321
+ @hm.push(@records2).should == @flat_records_all
322
+ end
323
+
324
+ it "should add a HashModel" do
325
+ @hm.push(@hm2).should == @flat_records_all
326
+ end
327
+
328
+ end
329
+
330
+ end # adding records
331
+
332
+ describe "using the [] sign" do
333
+
334
+ it "should return flat records" do
335
+ @hm.each_with_index do |record, index|
336
+ record.should == @flat_records[index]
337
+ end
338
+ end
339
+
340
+ end
341
+
342
+ describe "flattening behavior" do
343
+
344
+ it "should set the first field given as the default flatten index" do
345
+ @hm << {:switch => ["-x", "--xtended"], :description => "Xish stuff"}
346
+ @hm.add(:description => "blah,blah,blah")
347
+ @hm.flatten_index.should == :switch
348
+ end
349
+
350
+ it "should set the flatten index properly if specified using parameter :flatten_index" do
351
+ @hm = HashModel.new(:raw_data=>@records, :flatten_index=>:parameter)
352
+ @hm.should == [
353
+ {:parameter=>{:type=>String}, :switch=>["-x", "--xtended"], :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
354
+ {:parameter=>{:require=>true}, :switch=>["-x", "--xtended"], :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
355
+ {:parameter=>nil, :switch=>["-y", "--why"], :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
356
+ {:parameter=>{:type=>String}, :switch=>"-z", :description=>"zee svitch zu moost calz", :hm_id=>3, :hm_group_id=>2}
357
+ ]
358
+
359
+ end
360
+
361
+ it "should allow you to change the flatten index" do
362
+ @hm << {:switch => ["-x", "--xtended"], :description => "Xish stuff"}
363
+ proc do
364
+ @hm.flatten_index = :description
365
+ end.should change(@hm, :flatten_index).from(:switch).to(:description)
366
+ end
367
+
368
+ it "should set the flatten index when adding to an empty HashModel" do
369
+ @hm.flatten_index.should == :switch
370
+ end
371
+
372
+ it "should assign the flattened data to self correctly when adding records using <<" do
373
+ @hm = HashModel.new
374
+ @hm << @records[0]
375
+ @hm << @records[1]
376
+ @hm << @records[2]
377
+ @hm.should == @flat_records
378
+ end
379
+
380
+ it "should assign the flattened data to self correctly when adding with :raw_data=>records" do
381
+ @hm.should == @flat_records
382
+ end
383
+
384
+ it "should add a nil value for the field index for records that don't have a field with the field index" do
385
+ @hm = HashModel.new
386
+ @hm << @records[0]
387
+ @hm << {:foo=>"bar"}
388
+ @hm.last.should == {:switch=>nil, :foo=>"bar", :hm_id=>2, :hm_group_id=>1}
389
+ end
390
+
391
+ it "should change the flattened data when changing the flatten index" do
392
+ @hm = HashModel.new(:raw_data=>@records)
393
+ @hm.flatten_index = :parameter_type
394
+ @hm.should == [
395
+ {:parameter_type=>String, :switch=>["-x", "--xtended"], :parameter_require=>true, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
396
+ {:parameter_type=>nil, :switch=>["-y", "--why"], :description=>"lucky what?", :hm_id=>1, :hm_group_id=>1},
397
+ {:parameter_type=>String, :switch=>"-z", :description=>"zee svitch zu moost calz", :hm_id=>2, :hm_group_id=>2}
398
+ ]
399
+ end
400
+
401
+ it "should update the flattened data if the raw data is changed" do
402
+ @hm.raw_data = @records2.clone
403
+ @hm.should == @flat_records2
404
+ end
405
+
406
+ end # flattening behvior
407
+
408
+ describe "comparisons" do
409
+
410
+ it "should allow arrays to be compared to the HashModel" do
411
+ @hm.should == @flat_records
412
+ end
413
+
414
+ it "should allow HashModels to be compared to the HashModel" do
415
+ hm2 = HashModel.new(:raw_data=>@records)
416
+ @hm.should == hm2
417
+ end
418
+
419
+ it "should compare using the raw data if sent an array without group_id's or id's" do
420
+ @hm.should == @records
421
+ end
422
+
423
+ it "should return false if compared to something other than an Array or a HashModel" do
424
+ @hm.should_not == "potato"
425
+ end
426
+
427
+ it "should allow arrays to be compared to the HashModel using eql?" do
428
+ @hm.eql?(@hm).should == true
429
+ end
430
+
431
+ it "should return false if compared to an array of something other than hashes" do
432
+ @hm.should_not == ["potato"]
433
+ end
434
+
435
+ it "should use flattened records if <=>'d with an array with a group_id" do
436
+ (@hm <=> @flat_records).should == 0
437
+ end
438
+
439
+ it "should use flattened records if <=>'d with an array without a group_id" do
440
+ (@hm <=> @records).should == 0
441
+ end
442
+
443
+ it "should use flattened data if <=>'d with another HashModel" do
444
+ hm2 = @hm.clone
445
+ (@hm <=> hm2).should == 0
446
+ end
447
+
448
+ it "should return nil if <=>'d with something other than an Array or a HashModel" do
449
+ (@hm <=> "potato").should == nil
450
+ end
451
+
452
+ end # comparisons
453
+
454
+ describe "searching and selecting records" do
455
+
456
+ context "in place" do
457
+
458
+ it "should accept a parameter as input" do
459
+ proc{@hm.where!("-x")}.should_not raise_error
460
+ end
461
+
462
+ it "should raise an error if a block and a parameter are given" do
463
+ proc{@hm.where!("-x"){@switch == "-x"}}.should raise_error
464
+ end
465
+
466
+ it "should return a HashModel when searching" do
467
+ @hm.where!("-x").class.should == HashModel
468
+ end
469
+
470
+ it "should return the same hash model when calling where" do
471
+ @hm.where!("-x").object_id.should == @hm.object_id
472
+ end
473
+
474
+ it "should filter the recordset" do
475
+ @hm.where!("-x")
476
+ @hm.should == [@flat_records[0]]
477
+ end
478
+
479
+ it "should tell you if it is filtering records" do
480
+ @hm.where!("-x")
481
+ @hm.filtered?.should == true
482
+ end
483
+
484
+ it "should let you clear the filter" do
485
+ @hm.where!("-x")
486
+ proc {@hm.clear_filter}.should change(@hm, :filtered?).from(true).to(false)
487
+ end
488
+
489
+ it "should show all the records when the filter is cleared" do
490
+ @hm.where!("-x")
491
+ @hm.clear_filter
492
+ @hm.should == @flat_records
493
+ end
494
+
495
+ it "should clear the filter if nothing is sent" do
496
+ @hm.where!("-x")
497
+ proc {@hm.where!}.should change(@hm, :filtered?).from(true).to(false)
498
+ end
499
+
500
+ it "should return the entire flattened recordset if nothing is sent" do
501
+ @hm.where!("-x")
502
+ @hm.should == [@flat_records[0]]
503
+ @hm.where!
504
+ @hm.should == @flat_records
505
+ end
506
+
507
+ end # in place
508
+
509
+ context "not in place" do
510
+
511
+ it "should return a HashModel object" do
512
+ @hm = HashModel.new(:raw_data=>@records)
513
+ @hm.where("-x").class.should == HashModel
514
+ end
515
+
516
+ it "should return a new HashModel" do
517
+ @hm.where("-x").object_id.should_not == @hm.object_id
518
+ end
519
+
520
+ it "should search the flatten index if given a parameter" do
521
+ @hm = HashModel.new(:raw_data=>@records)
522
+ @hm.where("-x").should == [@flat_records[0]]
523
+ end
524
+
525
+ it "should search the flatten index if given a block" do
526
+ @hm = HashModel.new(:raw_data=>@records)
527
+ @hm.where{@parameter_type == String}.should == [
528
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
529
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
530
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2}
531
+ ]
532
+ end
533
+
534
+ end # not in place
535
+
536
+ it "should return false if tested for inclusion of anything other than a hash" do
537
+ @hm.include?([:switch=>"-x"]).should == false
538
+ end
539
+
540
+ it "should match flat data if search criteria includes an hm_group_id field" do
541
+ @hm.include?(@flat_records[2]).should == true
542
+ end
543
+
544
+ it "should search raw data if search criteria includes an hm_group_id field" do
545
+ @hm.include?(@records[2]).should == true
546
+ end
547
+
548
+ it "should return the flattened record index using the index method" do
549
+ @hm.index(@flat_records[3]).should == 3
550
+ end
551
+
552
+ context "when using take" do
553
+ it "should return the first n flat records" do
554
+ @hm.take(2).should == @flat_records.take(2)
555
+ end
556
+
557
+ it "should return the first n flat records while block is true" do
558
+ @hm.take_while {|record| record[:hm_id] < 4}.should == @flat_records[0..3]
559
+ end
560
+
561
+ end
562
+
563
+ it "should return values at x,y,z" do
564
+ @hm.values_at(1,3,5).should == @flat_records.values_at(1,3,5)
565
+ end
566
+
567
+ it "should zip things" do
568
+ hm2 = HashModel.new(:raw_data=>@records2)
569
+ @hm.zip(hm2).should == @flat_records.zip(@flat_records2)
570
+ end
571
+
572
+ end # searching records
573
+
574
+ describe "grouping" do
575
+
576
+ context "not in place" do
577
+
578
+ it "should return a HashModel object" do
579
+ @hm.group("-x").class.should == HashModel
580
+ end
581
+
582
+ it "should return a different HashModel object" do
583
+ @hm.group("-x").object_id.should_not == @hm.object_id
584
+ end
585
+
586
+ it "should return the records in the same raw data record when using a parameter" do
587
+ @hm.group("-x").should == [@flat_records[0], @flat_records[1]]
588
+ end
589
+
590
+ it "should be chainable on a filtered HashModel" do
591
+ @hm.where("-x").group.should == [@flat_records[0],@flat_records[1]]
592
+ end
593
+
594
+ it "should return the records in the same raw data record when using a block" do
595
+ @hm.group{@switch == "-y"}.should == [@flat_records[2], @flat_records[3]]
596
+ end
597
+
598
+ it "should work across group_id's if searching for something that returns records from multiple groups" do
599
+ @hm.group{@parameter_type == String}.should == [
600
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
601
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
602
+ {:switch => "-z", :parameter => {:type => String}, :description => "zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2}
603
+ ]
604
+ end
605
+
606
+ end # not in place
607
+
608
+ context "in place" do
609
+
610
+ it "should return the same HashModel object" do
611
+ @hm.group!("-x").object_id.should == @hm.object_id
612
+ end
613
+
614
+ it "should return the records in the same raw data record when using a parameter" do
615
+ @hm.group!("-x").should == [@flat_records[0],@flat_records[1]]
616
+ end
617
+
618
+ it "should be chainable on a filtered HashModel" do
619
+ @hm.where("-x").group!.should == [@flat_records[0],@flat_records[1]]
620
+ end
621
+
622
+ it "should be chainable on an in-place filtered HashModel" do
623
+ @hm.where!("-x").group!.should == [@flat_records[0],@flat_records[1]]
624
+ end
625
+
626
+ it "should return the records in the same raw data record when using a block" do
627
+ @hm.group!{@switch == "-y"}.should == [
628
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1},
629
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1}
630
+ ]
631
+ end
632
+
633
+ it "should work across group_id's if searching for something that returns records from multiple groups" do
634
+ @hm.group!{@parameter_type == String}.should == [
635
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0},
636
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0},
637
+ {:switch => "-z", :parameter => {:type => String}, :description => "zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2}
638
+ ]
639
+ end
640
+
641
+ end
642
+
643
+ end # grouping
644
+
645
+ describe "miscellaneous array methods and properties" do
646
+
647
+ it "should return an array when calling to_ary" do
648
+ @hm.to_ary.class.should == Array
649
+ end
650
+
651
+ it "should not return a HashModel when calling to_ary" do
652
+ @hm.to_ary.class.should_not == HashModel
653
+ end
654
+
655
+ it "should return the flat records when calling to_ary" do
656
+ @hm.to_ary.should == @flat_records
657
+ end
658
+
659
+ it "should return an array when calling to_a" do
660
+ @hm.to_a.class.should == Array
661
+ end
662
+
663
+ it "should not return a HashModel when calling to_a" do
664
+ @hm.to_a.class.should_not == HashModel
665
+ end
666
+
667
+ it "should return the flat records when calling to_a" do
668
+ @hm.to_a.should == @flat_records
669
+ end
670
+
671
+ it "should report the length of the flat data" do
672
+ @hm.length.should == @flat_records.length
673
+ end
674
+
675
+ it "should report the size of the flat data" do
676
+ @hm.size.should == @flat_records.size
677
+ end
678
+
679
+ it "should return the correct flat record when using at" do
680
+ @hm.at(0).should == @flat_records[0]
681
+ @hm.at(2).should == @flat_records[2]
682
+ end
683
+
684
+ it "should collect across the flat data" do
685
+ extra = -1
686
+ @hm.collect {|record| record.merge!(:extra=>extra+=1)}.should == [
687
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0, :extra=>0},
688
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0, :extra=>1},
689
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1, :extra=>2},
690
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1, :extra=>3},
691
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2, :extra=>4}
692
+ ]
693
+ end
694
+
695
+ it "should map across the flat data" do
696
+ extra = -1
697
+ @hm.map {|record| record.merge!(:extra=>extra+=1)}.should == [
698
+ {:switch=>"-x", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>0, :hm_group_id=>0, :extra=>0},
699
+ {:switch=>"--xtended", :parameter=>{:type=>String, :require=>true}, :description=>"Xish stuff", :hm_id=>1, :hm_group_id=>0, :extra=>1},
700
+ {:switch=>"-y", :description=>"lucky what?", :hm_id=>2, :hm_group_id=>1, :extra=>2},
701
+ {:switch=>"--why", :description=>"lucky what?", :hm_id=>3, :hm_group_id=>1, :extra=>3},
702
+ {:switch=>"-z", :parameter=>{:type=>String}, :description=>"zee svitch zu moost calz", :hm_id=>4, :hm_group_id=>2, :extra=>4}
703
+ ]
704
+ end
705
+
706
+ it "should combination'ize the flat data" do
707
+ hm_combo = []
708
+ flat_combo = []
709
+ @hm.combination(2).each { |record| hm_combo << record }
710
+ @flat_records.combination(2) { |record| flat_combo << record }
711
+ hm_combo.should == flat_combo
712
+ end
713
+
714
+ it "should count the flat data" do
715
+ @hm.count.should == @flat_records.count
716
+ end
717
+
718
+ it "should cycle over the flat data" do
719
+ cycle = cycle2 = []
720
+ @hm.cycle(2) {|record| cycle << record}
721
+ @flat_records.cycle(2) {|record| cycle2 << record}
722
+ cycle.should == cycle2
723
+ end
724
+
725
+ it "should iterate with an index" do
726
+ collect = []
727
+ @hm.each_index {|index| collect << @hm[index][:switch]}
728
+ collect.should == ["-x", "--xtended", "-y", "--why", "-z"]
729
+ end
730
+
731
+ it "should say if it's empty" do
732
+ @hm = HashModel.new
733
+ @hm.empty?.should == true
734
+ @hm << @records[0]
735
+ @hm.empty?.should == false
736
+ end
737
+
738
+ it "should fetch records given an index" do
739
+ @hm.fetch(2).should == @flat_records[2]
740
+ end
741
+
742
+ it "should return the default value if fetch index is out of bounds" do
743
+ @hm.fetch(10, "potato").should == "potato"
744
+ end
745
+
746
+ it "should run a block if fetch index is out of bounds" do
747
+ (@hm.fetch(10) {|index| index }).should == 10
748
+ end
749
+
750
+ it "should return the first flattened record" do
751
+ @hm.first.should == @flat_records.first
752
+ end
753
+
754
+ it "should return the last flattened record" do
755
+ @hm.last.should == @flat_records.last
756
+ end
757
+
758
+ it "should freeze the raw records" do
759
+ proc{@hm.freeze}.should change(@hm.raw_data,:frozen?)
760
+ .from(false)
761
+ .to(true)
762
+ end
763
+
764
+ it "should permutate over the flat data" do
765
+ @hm.permutation(2).to_a.should == @flat_records.permutation(2).to_a
766
+ @hm.permutation.to_a.should == @flat_records.permutation.to_a
767
+ @hm.permutation.to_a.should_not == @records.permutation.to_a
768
+ end
769
+
770
+ end
771
+
772
+ end # describe "HashModel"
773
+
774
+ end # MikBe