array-hooked 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+
2
+ class ::Array::Hooked < ::Array
3
+ end
4
+
5
+ class ::HookedArray < ::Array::Hooked
6
+ end
@@ -0,0 +1,27 @@
1
+
2
+ basepath = 'hooked'
3
+
4
+ files = [
5
+
6
+ 'array_interface'
7
+
8
+ ]
9
+
10
+ second_basepath = '../hooked_array'
11
+
12
+ second_files = [
13
+
14
+ 'array_interface'
15
+
16
+ ]
17
+
18
+
19
+ files.each do |this_file|
20
+ require_relative( File.join( basepath, this_file ) + '.rb' )
21
+ end
22
+ second_files.each do |this_file|
23
+ require_relative( File.join( second_basepath, this_file ) + '.rb' )
24
+ end
25
+
26
+ require_relative( basepath + '.rb' )
27
+ require_relative( second_basepath + '.rb' )
@@ -0,0 +1,2 @@
1
+
2
+ require_relative '../array-hooked.rb'
@@ -0,0 +1,6 @@
1
+
2
+ class ::HookedArray < ::Array::Hooked
3
+
4
+ include ::HookedArray::Interface
5
+
6
+ end
@@ -0,0 +1,29 @@
1
+
2
+ module ::HookedArray::Interface
3
+
4
+ instances_identify_as!( ::HookedArray )
5
+
6
+ ################
7
+ # initialize #
8
+ ################
9
+
10
+ # Initialize with reference a configuration instance.
11
+ # @param [Object] object Object that HookedArray instance is attached to, primarily useful for
12
+ # reference from hooks.
13
+ # @param [Array<Object>] args Parameters passed through super to Array#initialize.
14
+ # @return [true,false] Whether receiver identifies as object.
15
+ def initialize( configuration_instance = nil, *args )
16
+
17
+ @configuration_instance = configuration_instance
18
+
19
+ super( *args )
20
+
21
+ end
22
+
23
+ ############################
24
+ # configuration_instance #
25
+ ############################
26
+
27
+ attr_accessor :configuration_instance
28
+
29
+ end
@@ -0,0 +1,758 @@
1
+
2
+ require_relative '../../lib/array-hooked.rb'
3
+
4
+ describe ::Array::Hooked do
5
+
6
+ ################
7
+ # initialize #
8
+ ################
9
+
10
+ it 'can add initialize with an ancestor, inheriting its values and linking to it as a child' do
11
+
12
+ hooked_array = ::Array::Hooked.new
13
+
14
+ hooked_array.instance_variable_get( :@parent_composite_object ).should == nil
15
+ hooked_array.should == [ ]
16
+ hooked_array.push( :A, :B, :C, :D )
17
+
18
+ end
19
+
20
+ #########
21
+ # []= #
22
+ #########
23
+
24
+ it 'can add elements' do
25
+
26
+ hooked_array = ::Array::Hooked.new
27
+
28
+ hooked_array[ 0 ] = :A
29
+ hooked_array.should == [ :A ]
30
+
31
+ hooked_array[ 1 ] = :B
32
+ hooked_array.should == [ :A, :B ]
33
+
34
+ hooked_array[ 0 ] = :D
35
+ hooked_array.should == [ :D, :B ]
36
+
37
+ end
38
+
39
+ ############
40
+ # insert #
41
+ ############
42
+
43
+ it 'can insert elements' do
44
+
45
+ hooked_array = ::Array::Hooked.new
46
+
47
+ hooked_array.insert( 3, :D )
48
+ hooked_array.should == [ nil, nil, nil, :D ]
49
+
50
+ hooked_array.insert( 1, :B )
51
+ hooked_array.should == [ nil, :B, nil, nil, :D ]
52
+
53
+ hooked_array.insert( 2, :C )
54
+ hooked_array.should == [ nil, :B, :C, nil, nil, :D ]
55
+
56
+ end
57
+
58
+ ##########
59
+ # push #
60
+ # << #
61
+ ##########
62
+
63
+ it 'can add elements' do
64
+
65
+ hooked_array = ::Array::Hooked.new
66
+
67
+ hooked_array << :A
68
+ hooked_array.should == [ :A ]
69
+
70
+ hooked_array << :B
71
+ hooked_array.should == [ :A, :B ]
72
+
73
+ end
74
+
75
+ ############
76
+ # concat #
77
+ # + #
78
+ ############
79
+
80
+ it 'can add elements' do
81
+
82
+ # NOTE: this breaks + by causing it to modify the array like +=
83
+ # The alternative was worse.
84
+
85
+ hooked_array = ::Array::Hooked.new
86
+
87
+ hooked_array.concat( [ :A ] )
88
+ hooked_array.should == [ :A ]
89
+
90
+ hooked_array += [ :B ]
91
+ hooked_array.should == [ :A, :B ]
92
+
93
+ end
94
+
95
+ ####################
96
+ # delete_objects #
97
+ ####################
98
+
99
+ it 'can delete multiple elements' do
100
+
101
+ hooked_array = ::Array::Hooked.new
102
+
103
+ hooked_array += [ :A, :B ]
104
+ hooked_array.should == [ :A, :B ]
105
+
106
+ hooked_array.delete_objects( :A, :B )
107
+ hooked_array.should == [ ]
108
+
109
+ end
110
+
111
+ #######
112
+ # - #
113
+ #######
114
+
115
+ it 'can exclude elements' do
116
+
117
+ hooked_array = ::Array::Hooked.new
118
+
119
+ hooked_array.push( :A )
120
+ hooked_array.should == [ :A ]
121
+
122
+ hooked_array -= [ :A ]
123
+ hooked_array.should == [ ]
124
+
125
+ hooked_array.push( :B )
126
+ hooked_array.should == [ :B ]
127
+
128
+ end
129
+
130
+ ############
131
+ # delete #
132
+ ############
133
+
134
+ it 'can delete elements' do
135
+
136
+ hooked_array = ::Array::Hooked.new
137
+
138
+ hooked_array.push( :A )
139
+ hooked_array.should == [ :A ]
140
+
141
+ hooked_array.delete( :A )
142
+ hooked_array.should == [ ]
143
+
144
+ hooked_array.push( :B )
145
+ hooked_array.should == [ :B ]
146
+
147
+ end
148
+
149
+ ###############
150
+ # delete_at #
151
+ ###############
152
+
153
+ it 'can delete by indexes' do
154
+
155
+ hooked_array = ::Array::Hooked.new
156
+
157
+ hooked_array.push( :A )
158
+ hooked_array.should == [ :A ]
159
+
160
+ hooked_array.delete_at( 0 )
161
+ hooked_array.should == [ ]
162
+
163
+ hooked_array.push( :B )
164
+ hooked_array.should == [ :B ]
165
+
166
+ end
167
+
168
+ #######################
169
+ # delete_at_indexes #
170
+ #######################
171
+
172
+ it 'can delete by indexes' do
173
+
174
+ hooked_array = ::Array::Hooked.new
175
+
176
+ hooked_array.push( :A, :B, :C )
177
+ hooked_array.should == [ :A, :B, :C ]
178
+
179
+ hooked_array.delete_at_indexes( 0, 1 )
180
+ hooked_array.should == [ :C ]
181
+
182
+ end
183
+
184
+ ###############
185
+ # delete_if #
186
+ ###############
187
+
188
+ it 'can delete by block' do
189
+
190
+ hooked_array = ::Array::Hooked.new
191
+
192
+ hooked_array.push( :A, :B, :C )
193
+ hooked_array.should == [ :A, :B, :C ]
194
+ hooked_array.delete_if do |object|
195
+ object != :C
196
+ end
197
+ hooked_array.should == [ :C ]
198
+
199
+ hooked_array.delete_if.is_a?( Enumerator ).should == true
200
+
201
+ end
202
+
203
+ #############
204
+ # keep_if #
205
+ #############
206
+
207
+ it 'can keep by block' do
208
+
209
+ hooked_array = ::Array::Hooked.new
210
+
211
+ hooked_array.push( :A, :B, :C )
212
+ hooked_array.should == [ :A, :B, :C ]
213
+ hooked_array.keep_if do |object|
214
+ object == :C
215
+ end
216
+ hooked_array.should == [ :C ]
217
+
218
+ end
219
+
220
+ ##############
221
+ # compact! #
222
+ ##############
223
+
224
+ it 'can compact' do
225
+
226
+ hooked_array = ::Array::Hooked.new
227
+
228
+ hooked_array.push( :A, nil, :B, nil, :C, nil )
229
+ hooked_array.should == [ :A, nil, :B, nil, :C, nil ]
230
+ hooked_array.compact!
231
+ hooked_array.should == [ :A, :B, :C ]
232
+
233
+ end
234
+
235
+ ##############
236
+ # flatten! #
237
+ ##############
238
+
239
+ it 'can flatten' do
240
+
241
+ hooked_array = ::Array::Hooked.new
242
+
243
+ hooked_array.push( :A, [ :F_A, :F_B ], :B, [ :F_C ], :C, [ :F_D ], [ :F_E ] )
244
+ hooked_array.should == [ :A, [ :F_A, :F_B ], :B, [ :F_C ], :C, [ :F_D ], [ :F_E ] ]
245
+ hooked_array.flatten!
246
+ hooked_array.should == [ :A, :F_A, :F_B, :B, :F_C, :C, :F_D, :F_E ]
247
+
248
+ end
249
+
250
+ #############
251
+ # reject! #
252
+ #############
253
+
254
+ it 'can reject' do
255
+
256
+ hooked_array = ::Array::Hooked.new
257
+
258
+ hooked_array.push( :A, :B, :C )
259
+ hooked_array.should == [ :A, :B, :C ]
260
+ hooked_array.reject! do |object|
261
+ object != :C
262
+ end
263
+ hooked_array.should == [ :C ]
264
+
265
+ end
266
+
267
+ #############
268
+ # replace #
269
+ #############
270
+
271
+ it 'can replace self' do
272
+
273
+ hooked_array = ::Array::Hooked.new
274
+
275
+ hooked_array.push( :A, :B, :C )
276
+ hooked_array.should == [ :A, :B, :C ]
277
+ hooked_array.replace( [ :D, :E, :F ] )
278
+ hooked_array.should == [ :D, :E, :F ]
279
+
280
+ end
281
+
282
+ ##############
283
+ # reverse! #
284
+ ##############
285
+
286
+ it 'can reverse self' do
287
+
288
+ hooked_array = ::Array::Hooked.new
289
+
290
+ hooked_array.push( :A, :B, :C )
291
+ hooked_array.should == [ :A, :B, :C ]
292
+ hooked_array.reverse!
293
+ hooked_array.should == [ :C, :B, :A ]
294
+
295
+ end
296
+
297
+ #############
298
+ # rotate! #
299
+ #############
300
+
301
+ it 'can rotate self' do
302
+
303
+ hooked_array = ::Array::Hooked.new
304
+
305
+ hooked_array.push( :A, :B, :C )
306
+ hooked_array.should == [ :A, :B, :C ]
307
+
308
+ hooked_array.rotate!
309
+ hooked_array.should == [ :B, :C, :A ]
310
+
311
+ hooked_array.rotate!( -1 )
312
+ hooked_array.should == [ :A, :B, :C ]
313
+
314
+ end
315
+
316
+ #############
317
+ # select! #
318
+ #############
319
+
320
+ it 'can keep by select' do
321
+
322
+ hooked_array = ::Array::Hooked.new
323
+
324
+ hooked_array.push( :A, :B, :C )
325
+ hooked_array.should == [ :A, :B, :C ]
326
+ hooked_array.select! do |object|
327
+ object == :C
328
+ end
329
+ hooked_array.should == [ :C ]
330
+
331
+ hooked_array.select!.is_a?( Enumerator ).should == true
332
+
333
+ end
334
+
335
+ ##############
336
+ # shuffle! #
337
+ ##############
338
+
339
+ it 'can shuffle self' do
340
+
341
+ hooked_array = ::Array::Hooked.new
342
+
343
+ hooked_array.push( :A, :B, :C )
344
+ hooked_array.should == [ :A, :B, :C ]
345
+
346
+ prior_version = hooked_array.dup
347
+ attempts = [ ]
348
+ 50.times do
349
+ hooked_array.shuffle!
350
+ attempts.push( hooked_array == prior_version )
351
+ prior_version = hooked_array.dup
352
+ end
353
+ attempts_correct = attempts.select { |member| member == false }.count
354
+ ( attempts_correct >= 10 ).should == true
355
+ first_shuffle_version = hooked_array
356
+
357
+ end
358
+
359
+ ##############
360
+ # collect! #
361
+ # map! #
362
+ ##############
363
+
364
+ it 'can replace by collect/map' do
365
+
366
+ hooked_array = ::Array::Hooked.new
367
+
368
+ hooked_array.push( :A, :B, :C )
369
+ hooked_array.should == [ :A, :B, :C ]
370
+ hooked_array.collect! do |object|
371
+ :C
372
+ end
373
+ hooked_array.should == [ :C, :C, :C ]
374
+
375
+ hooked_array.collect!.is_a?( Enumerator ).should == true
376
+
377
+ end
378
+
379
+ ###########
380
+ # sort! #
381
+ ###########
382
+
383
+ it 'can replace by collect/map' do
384
+
385
+ hooked_array = ::Array::Hooked.new
386
+
387
+ hooked_array.push( :A, :B, :C )
388
+ hooked_array.should == [ :A, :B, :C ]
389
+ hooked_array.sort! do |a, b|
390
+ if a < b
391
+ 1
392
+ elsif a > b
393
+ -1
394
+ elsif a == b
395
+ 0
396
+ end
397
+ end
398
+ hooked_array.should == [ :C, :B, :A ]
399
+
400
+ hooked_array.sort!
401
+ hooked_array.should == [ :A, :B, :C ]
402
+
403
+ end
404
+
405
+ ##############
406
+ # sort_by! #
407
+ ##############
408
+
409
+ it 'can replace by collect/map' do
410
+
411
+ hooked_array = ::Array::Hooked.new
412
+
413
+ hooked_array.push( :A, :B, :C )
414
+ hooked_array.should == [ :A, :B, :C ]
415
+ hooked_array.sort_by! do |object|
416
+ case object
417
+ when :A
418
+ :B
419
+ when :B
420
+ :A
421
+ when :C
422
+ :C
423
+ end
424
+ end
425
+ hooked_array.should == [ :B, :A, :C ]
426
+
427
+ hooked_array.sort_by!.is_a?( Enumerator ).should == true
428
+
429
+ end
430
+
431
+ ###########
432
+ # uniq! #
433
+ ###########
434
+
435
+ it 'can remove non-unique elements' do
436
+
437
+ hooked_array = ::Array::Hooked.new
438
+
439
+ hooked_array.push( :A, :B, :C, :C, :C, :B, :A )
440
+ hooked_array.should == [ :A, :B, :C, :C, :C, :B, :A ]
441
+ hooked_array.uniq!
442
+ hooked_array.should == [ :A, :B, :C ]
443
+
444
+ end
445
+
446
+ #############
447
+ # unshift #
448
+ #############
449
+
450
+ it 'can unshift onto the first element' do
451
+
452
+ hooked_array = ::Array::Hooked.new
453
+
454
+ hooked_array += :A
455
+ hooked_array.should == [ :A ]
456
+
457
+ hooked_array.unshift( :B )
458
+ hooked_array.should == [ :B, :A ]
459
+
460
+ end
461
+
462
+ #########
463
+ # pop #
464
+ #########
465
+
466
+ it 'can pop the final element' do
467
+
468
+ hooked_array = ::Array::Hooked.new
469
+
470
+ hooked_array += :A
471
+ hooked_array.should == [ :A ]
472
+
473
+ hooked_array.pop.should == :A
474
+ hooked_array.should == [ ]
475
+
476
+ hooked_array += :B
477
+ hooked_array.should == [ :B ]
478
+
479
+ end
480
+
481
+ ###########
482
+ # shift #
483
+ ###########
484
+
485
+ it 'can shift the first element' do
486
+
487
+ hooked_array = ::Array::Hooked.new
488
+
489
+ hooked_array += :A
490
+ hooked_array.should == [ :A ]
491
+
492
+ hooked_array.shift.should == :A
493
+ hooked_array.should == [ ]
494
+
495
+ hooked_array += :B
496
+ hooked_array.should == [ :B ]
497
+
498
+ end
499
+
500
+ ############
501
+ # slice! #
502
+ ############
503
+
504
+ it 'can slice elements' do
505
+
506
+ hooked_array = ::Array::Hooked.new
507
+
508
+ hooked_array += :A
509
+ hooked_array.should == [ :A ]
510
+
511
+ hooked_array.slice!( 0, 1 ).should == [ :A ]
512
+ hooked_array.should == [ ]
513
+
514
+ hooked_array += :B
515
+ hooked_array.should == [ :B ]
516
+
517
+ end
518
+
519
+ ###########
520
+ # clear #
521
+ ###########
522
+
523
+ it 'can clear, causing present elements to be excluded' do
524
+
525
+ hooked_array = ::Array::Hooked.new
526
+
527
+ hooked_array += :A
528
+ hooked_array.should == [ :A ]
529
+
530
+ hooked_array.clear
531
+ hooked_array.should == [ ]
532
+
533
+ hooked_array += :B
534
+ hooked_array.should == [ :B ]
535
+
536
+ end
537
+
538
+ ##################
539
+ # pre_set_hook #
540
+ ##################
541
+
542
+ it 'has a hook that is called before setting a value; return value is used in place of object' do
543
+
544
+ class ::Array::Hooked::SubMockPreSet < ::Array::Hooked
545
+
546
+ def pre_set_hook( index, object, is_insert = false )
547
+ return :some_other_value
548
+ end
549
+
550
+ end
551
+
552
+ hooked_array = ::Array::Hooked::SubMockPreSet.new
553
+
554
+ hooked_array.push( :some_value )
555
+
556
+ hooked_array.should == [ :some_other_value ]
557
+
558
+ end
559
+
560
+ ###################
561
+ # post_set_hook #
562
+ ###################
563
+
564
+ it 'has a hook that is called after setting a value' do
565
+
566
+ class ::Array::Hooked::SubMockPostSet < ::Array::Hooked
567
+
568
+ def post_set_hook( index, object, is_insert = false )
569
+ return :some_other_value
570
+ end
571
+
572
+ end
573
+
574
+ hooked_array = ::Array::Hooked::SubMockPostSet.new
575
+
576
+ hooked_array.push( :some_value ).should == [ :some_other_value ]
577
+
578
+ hooked_array.should == [ :some_value ]
579
+
580
+ end
581
+
582
+ ##################
583
+ # pre_get_hook #
584
+ ##################
585
+
586
+ it 'has a hook that is called before getting a value; if return value is false, get does not occur' do
587
+
588
+ class ::Array::Hooked::SubMockPreGet < ::Array::Hooked
589
+
590
+ def pre_get_hook( index )
591
+ return false
592
+ end
593
+
594
+ end
595
+
596
+ hooked_array = ::Array::Hooked::SubMockPreGet.new
597
+
598
+ hooked_array.push( :some_value )
599
+ hooked_array[ 0 ].should == nil
600
+
601
+ hooked_array.should == [ :some_value ]
602
+
603
+ end
604
+
605
+ ###################
606
+ # post_get_hook #
607
+ ###################
608
+
609
+ it 'has a hook that is called after getting a value' do
610
+
611
+ class ::Array::Hooked::SubMockPostGet < ::Array::Hooked
612
+
613
+ def post_get_hook( index, object )
614
+ return :some_other_value
615
+ end
616
+
617
+ end
618
+
619
+ hooked_array = ::Array::Hooked::SubMockPostGet.new
620
+
621
+ hooked_array.push( :some_value )
622
+ hooked_array[ 0 ].should == :some_other_value
623
+
624
+ hooked_array.should == [ :some_value ]
625
+
626
+ end
627
+
628
+ #####################
629
+ # pre_delete_hook #
630
+ #####################
631
+
632
+ it 'has a hook that is called before deleting an index; if return value is false, delete does not occur' do
633
+
634
+ class ::Array::Hooked::SubMockPreDelete < ::Array::Hooked
635
+
636
+ def pre_delete_hook( index )
637
+ return false
638
+ end
639
+
640
+ end
641
+
642
+ hooked_array = ::Array::Hooked::SubMockPreDelete.new
643
+
644
+ hooked_array.push( :some_value )
645
+ hooked_array.delete_at( 0 )
646
+
647
+ hooked_array.should == [ :some_value ]
648
+
649
+ end
650
+
651
+ ######################
652
+ # post_delete_hook #
653
+ ######################
654
+
655
+ it 'has a hook that is called after deleting an index' do
656
+
657
+ class ::Array::Hooked::SubMockPostDelete < ::Array::Hooked
658
+
659
+ def post_delete_hook( index, object )
660
+ return :some_other_value
661
+ end
662
+
663
+ end
664
+
665
+ hooked_array = ::Array::Hooked::SubMockPostDelete.new
666
+
667
+ hooked_array.push( :some_value )
668
+ hooked_array.delete_at( 0 ).should == :some_other_value
669
+
670
+ hooked_array.should == [ ]
671
+
672
+ end
673
+
674
+ ########################
675
+ # child_pre_set_hook #
676
+ ########################
677
+
678
+ it 'has a hook that is called before setting a value that has been passed by a parent; return value is used in place of object' do
679
+
680
+ class ::Array::Hooked::SubMockChildPreSet < ::Array::Hooked
681
+
682
+ def child_pre_set_hook( index, object, is_insert = false )
683
+ return :some_other_value
684
+ end
685
+
686
+ end
687
+
688
+ hooked_array = ::Array::Hooked::SubMockChildPreSet.new
689
+ hooked_array.push( :some_value )
690
+
691
+ end
692
+
693
+ #########################
694
+ # child_post_set_hook #
695
+ #########################
696
+
697
+ it 'has a hook that is called after setting a value passed by a parent' do
698
+
699
+ class ::Array::Hooked::SubMockChildPostSet < ::Array::Hooked
700
+
701
+ def child_post_set_hook( index, object, is_insert = false )
702
+ push( :some_other_value )
703
+ end
704
+
705
+ end
706
+
707
+ hooked_array = ::Array::Hooked::SubMockChildPostSet.new
708
+ hooked_array.push( :some_value )
709
+
710
+ hooked_array.should == [ :some_value ]
711
+
712
+ end
713
+
714
+ ###########################
715
+ # child_pre_delete_hook #
716
+ ###########################
717
+
718
+ it 'has a hook that is called before deleting an index that has been passed by a parent; if return value is false, delete does not occur' do
719
+
720
+ class ::Array::Hooked::SubMockChildPreDelete < ::Array::Hooked
721
+
722
+ def child_pre_delete_hook( index )
723
+ false
724
+ end
725
+
726
+ end
727
+
728
+ hooked_array = ::Array::Hooked::SubMockChildPreDelete.new
729
+ hooked_array.push( :some_value )
730
+ hooked_array.delete( :some_value )
731
+
732
+ hooked_array.should == [ ]
733
+
734
+ end
735
+
736
+ ############################
737
+ # child_post_delete_hook #
738
+ ############################
739
+
740
+ it 'has a hook that is called after deleting an index passed by a parent' do
741
+
742
+ class ::Array::Hooked::SubMockChildPostDelete < ::Array::Hooked
743
+
744
+ def child_post_delete_hook( index, object )
745
+ delete( :some_other_value )
746
+ end
747
+
748
+ end
749
+
750
+ hooked_array = ::Array::Hooked::SubMockChildPostDelete.new
751
+ hooked_array.push( :some_value )
752
+ hooked_array.delete( :some_value )
753
+
754
+ hooked_array.should == [ ]
755
+
756
+ end
757
+
758
+ end