array-hooked 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,12 @@
1
+
2
+ == 6/14/2012
3
+
4
+ Initial release - split from compositing-array.
5
+
6
+ == 6/15/2012
7
+
8
+ Added missing :get_without_hooks and corresponding hooks.
9
+
10
+ == 6/30/2012
11
+
12
+ Renamed from hooked-array to array-hooked. File schema updated to reflect gem name.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Hooked Array #
2
+
3
+ http://rubygems.org/gems/array-hooked
4
+
5
+ # Description #
6
+
7
+ Provides ::Array::Hooked and ::HookedArray.
8
+
9
+ # Summary #
10
+
11
+ A subclass of Array that offers event hooks for pre-insert/pre-set/pre-delete, insert/set/delete. ::HookedArray offers implicit reference to a configuration instance.
12
+
13
+ # Install #
14
+
15
+ * sudo gem install array-hooked
16
+
17
+ # Usage #
18
+
19
+ Provides methods that can be overridden that will be called during every corresponding event:
20
+
21
+ * pre_set_hook
22
+ * post_set_hook
23
+ * pre_get_hook
24
+ * post_get_hook
25
+ * pre_delete_hook
26
+ * post_delete_hook
27
+
28
+ As a result, several internal perform methods have been created:
29
+
30
+ * perform_set_between_hooks
31
+ * perform_insert_between_hooks
32
+ * perform_delete_between_hooks
33
+
34
+ Also provides methods corresponding to each already-existing method + '_without_hooks', which causes methods to bypass hooks.
35
+
36
+ # License #
37
+
38
+ (The MIT License)
39
+
40
+ Copyright (c) Asher
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,2 @@
1
+
2
+ require_relative 'array/hooked.rb'
@@ -0,0 +1,43 @@
1
+
2
+ require 'identifies_as'
3
+
4
+ # namespaces that have to be declared ahead of time for proper load order
5
+ require_relative './namespaces'
6
+
7
+ # source file requires
8
+ require_relative './requires.rb'
9
+
10
+ class ::Array::Hooked < ::Array
11
+
12
+ ###############################
13
+ # perform_set_between_hooks #
14
+ ###############################
15
+
16
+ # Alias to original :[]= method. Used to perform actual set between hooks.
17
+ # @param [Fixnum] index Index at which set is taking place.
18
+ # @param [Object] object Element being set.
19
+ # @return [Object] Element returned.
20
+ alias_method :perform_set_between_hooks, :[]=
21
+
22
+ ##################################
23
+ # perform_insert_between_hooks #
24
+ ##################################
25
+
26
+ # Alias to original :insert method. Used to perform actual insert between hooks.
27
+ # @param [Fixnum] index Index at which insert is taking place.
28
+ # @param [Array<Object>] objects Elements being inserted.
29
+ # @return [Object] Element returned.
30
+ alias_method :perform_insert_between_hooks, :insert
31
+
32
+ ##################################
33
+ # perform_delete_between_hooks #
34
+ ##################################
35
+
36
+ # Alias to original :delete method. Used to perform actual delete between hooks.
37
+ # @param [Fixnum] index Index at which delete is taking place.
38
+ # @return [Object] Element returned.
39
+ alias_method :perform_delete_between_hooks, :delete_at
40
+
41
+ include ::Array::Hooked::ArrayInterface
42
+
43
+ end
@@ -0,0 +1,1233 @@
1
+
2
+ module ::Array::Hooked::ArrayInterface
3
+
4
+ instances_identify_as!( ::Array::Hooked )
5
+
6
+ ###################################### Subclass Hooks ##########################################
7
+
8
+ ##################
9
+ # pre_set_hook #
10
+ ##################
11
+
12
+ # A hook that is called before setting a value; return value is used in place of object.
13
+ # @param [Fixnum] index Index at which set/insert is taking place.
14
+ # @param [Object] object Element being set/inserted.
15
+ # @param [true,false] is_insert Whether this set is inserting a new index.
16
+ # @return [true,false] Return value is used in place of object.
17
+ def pre_set_hook( index, object, is_insert = false )
18
+
19
+ return object
20
+
21
+ end
22
+
23
+ ###################
24
+ # post_set_hook #
25
+ ###################
26
+
27
+ # A hook that is called after setting a value.
28
+ # @param [Fixnum] index Index at which set/insert is taking place.
29
+ # @param [Object] object Element being set/inserted.
30
+ # @param [true,false] is_insert Whether this set is inserting a new index.
31
+ # @return [Object] Ignored.
32
+ def post_set_hook( index, object, is_insert = false )
33
+
34
+ return object
35
+
36
+ end
37
+
38
+ ##################
39
+ # pre_get_hook #
40
+ ##################
41
+
42
+ # A hook that is called before getting a value; if return value is false, get does not occur.
43
+ # @param [Fixnum] index Index at which set/insert is taking place.
44
+ # @return [true,false] If return value is false, get does not occur.
45
+ def pre_get_hook( index )
46
+
47
+ # false means get does not take place
48
+ return true
49
+
50
+ end
51
+
52
+ ###################
53
+ # post_get_hook #
54
+ ###################
55
+
56
+ # A hook that is called after getting a value.
57
+ # @param [Fixnum] index Index at which get is taking place.
58
+ # @param [Object] object Element being set/inserted.
59
+ # @return [Object] Object returned in place of get result.
60
+ def post_get_hook( index, object )
61
+
62
+ return object
63
+
64
+ end
65
+
66
+ #####################
67
+ # pre_delete_hook #
68
+ #####################
69
+
70
+ # A hook that is called before deleting a value; if return value is false, delete does not occur.
71
+ # @param [Fixnum] index Index at which delete is taking place.
72
+ # @return [true,false] If return value is false, delete does not occur.
73
+ def pre_delete_hook( index )
74
+
75
+ # false means delete does not take place
76
+ return true
77
+
78
+ end
79
+
80
+ ######################
81
+ # post_delete_hook #
82
+ ######################
83
+
84
+ # A hook that is called after deleting a value.
85
+ # @param [Fixnum] index Index at which delete took place.
86
+ # @param [Object] object Element deleted.
87
+ # @return [Object] Object returned in place of delete result.
88
+ def post_delete_hook( index, object )
89
+
90
+ return object
91
+
92
+ end
93
+
94
+ ##################################### Self Management ##########################################
95
+
96
+ ########
97
+ # [] #
98
+ ########
99
+
100
+ def []( index )
101
+
102
+ object = nil
103
+
104
+ should_get = true
105
+
106
+ unless @without_hooks
107
+ should_get = pre_get_hook( index )
108
+ end
109
+
110
+ if should_get
111
+
112
+ object = super( index )
113
+
114
+ unless @without_hooks
115
+ object = post_get_hook( index, object )
116
+ end
117
+
118
+ end
119
+
120
+ return object
121
+
122
+ end
123
+
124
+ #######################
125
+ # get_without_hooks #
126
+ #######################
127
+
128
+ # Alias to :[] that bypasses hooks.
129
+ # @param [Fixnum] index Index at which set is taking place.
130
+ # @return [Object] Element returned.
131
+ def get_without_hooks( index )
132
+
133
+ @without_hooks = true
134
+
135
+ self[ index ] = object
136
+
137
+ @without_hooks = false
138
+
139
+ return object
140
+
141
+ end
142
+
143
+ #########
144
+ # []= #
145
+ #########
146
+
147
+ def []=( index, object )
148
+
149
+ # we are either replacing or adding at the end
150
+ # if we are replacing we are either replacing a parent element or an element in self
151
+ # * if replacing parent element, track and exclude parent changes
152
+
153
+ unless @without_hooks
154
+ object = pre_set_hook( index, object, false )
155
+ end
156
+
157
+ perform_set_between_hooks( index, object )
158
+
159
+ unless @without_hooks
160
+ object = post_set_hook( index, object, false )
161
+ end
162
+
163
+ return object
164
+
165
+ end
166
+
167
+ #######################
168
+ # set_without_hooks #
169
+ #######################
170
+
171
+ # Alias to :[]= that bypasses hooks.
172
+ # @param [Fixnum] index Index at which set is taking place.
173
+ # @param [Object] object Element being set.
174
+ # @return [Object] Element returned.
175
+ def set_without_hooks( index, object )
176
+
177
+ @without_hooks = true
178
+
179
+ self[ index ] = object
180
+
181
+ @without_hooks = false
182
+
183
+ return object
184
+
185
+ end
186
+
187
+ ############
188
+ # insert #
189
+ ############
190
+
191
+ def insert( index, *objects )
192
+
193
+ objects_to_insert = nil
194
+ if @without_hooks
195
+ objects_to_insert = objects
196
+ else
197
+ objects_to_insert = [ ]
198
+ objects.each_with_index do |this_object, this_index|
199
+ this_insert_index = index + this_index
200
+ this_object = pre_set_hook( this_insert_index, this_object, true )
201
+ objects_to_insert.push( this_object )
202
+ end
203
+ end
204
+ objects = objects_to_insert
205
+
206
+ # if we have less elements in self than the index we are inserting at
207
+ # we need to make sure the nils inserted cascade
208
+ if index > count
209
+ nils_created = index - count
210
+ index -= nils_created
211
+ nils = [ ]
212
+ nils_created.times do |this_time|
213
+ nils.push( nil )
214
+ end
215
+ objects = nils.concat( objects )
216
+ end
217
+
218
+ perform_insert_between_hooks( index, *objects )
219
+
220
+ unless @without_hooks
221
+ objects.each_with_index do |this_object, this_index|
222
+ objects[ this_index ] = post_set_hook( index + this_index, this_object, true )
223
+ end
224
+ end
225
+
226
+ return objects
227
+
228
+ end
229
+
230
+ ##########################
231
+ # insert_without_hooks #
232
+ ##########################
233
+
234
+ # Alias to :insert that bypasses hooks.
235
+ # @param [Fixnum] index Index at which set is taking place.
236
+ # @param [Array<Object>] objects Elements being inserted.
237
+ # @return [Object] Element returned.
238
+ def insert_without_hooks( index, *objects )
239
+
240
+ @without_hooks = true
241
+
242
+ super( index, *objects )
243
+
244
+ @without_hooks = false
245
+
246
+ return objects
247
+
248
+ end
249
+
250
+ ##########
251
+ # push #
252
+ ##########
253
+
254
+ def push( *objects )
255
+
256
+ return insert( count, *objects )
257
+
258
+ end
259
+
260
+ alias_method :<<, :push
261
+
262
+ ########################
263
+ # push_without_hooks #
264
+ ########################
265
+
266
+ # Alias to :push that bypasses hooks.
267
+ # @param [Array<Object>] objects Elements being pushed.
268
+ # @return [Object] Element returned.
269
+ def push_without_hooks( *objects )
270
+
271
+ @without_hooks = true
272
+
273
+ push( *objects )
274
+
275
+ @without_hooks = false
276
+
277
+ return objects
278
+
279
+ end
280
+
281
+ ############
282
+ # concat #
283
+ ############
284
+
285
+ def concat( *arrays )
286
+
287
+ arrays.each do |this_array|
288
+ push( *this_array )
289
+ end
290
+
291
+ return self
292
+
293
+ end
294
+
295
+ alias_method :+, :concat
296
+
297
+ ##########################
298
+ # concat_without_hooks #
299
+ ##########################
300
+
301
+ # Alias to :concat that bypasses hooks.
302
+ # @param [Array<Object>] objects Elements being concatenated.
303
+ # @return [Object] Element returned.
304
+ def concat_without_hooks( *arrays )
305
+
306
+ @without_hooks = true
307
+
308
+ concat( *arrays )
309
+
310
+ @without_hooks = false
311
+
312
+ return arrays
313
+
314
+ end
315
+
316
+ ############
317
+ # delete #
318
+ ############
319
+
320
+ def delete( object )
321
+
322
+ return_value = nil
323
+
324
+ if index = index( object )
325
+ return_value = delete_at( index )
326
+ end
327
+
328
+ return return_value
329
+
330
+ end
331
+
332
+ ##########################
333
+ # delete_without_hooks #
334
+ ##########################
335
+
336
+ # Alias to :delete that bypasses hooks.
337
+ # @param [Object] object Element being deleted.
338
+ # @return [Object] Element returned.
339
+ def delete_without_hooks( object )
340
+
341
+ @without_hooks = true
342
+
343
+ return_value = delete( object )
344
+
345
+ @without_hooks = false
346
+
347
+ return return_value
348
+
349
+ end
350
+
351
+ ####################
352
+ # delete_objects #
353
+ ####################
354
+
355
+ def delete_objects( *objects )
356
+
357
+ return_value = nil
358
+
359
+ indexes = [ ]
360
+ objects.each do |this_object|
361
+ this_index = index( this_object )
362
+ if this_index
363
+ indexes.push( this_index )
364
+ end
365
+ end
366
+
367
+ unless indexes.empty?
368
+ return_value = delete_at_indexes( *indexes )
369
+ end
370
+
371
+ return return_value
372
+
373
+ end
374
+
375
+ ##################################
376
+ # delete_objects_without_hooks #
377
+ ##################################
378
+
379
+ # Alias to :delete that bypasses hooks and takes multiple objects.
380
+ # @param [Array<Object>] objects Elements being deleted.
381
+ # @return [Object] Element returned.
382
+ def delete_objects_without_hooks( *objects )
383
+
384
+ @without_hooks = true
385
+
386
+ return_value = delete_objects( *objects )
387
+
388
+ @without_hooks = false
389
+
390
+ return return_value
391
+
392
+ end
393
+
394
+ #######
395
+ # - #
396
+ #######
397
+
398
+ def -( *arrays )
399
+
400
+ arrays.each do |this_array|
401
+ delete_objects( *this_array )
402
+ end
403
+
404
+ return self
405
+
406
+ end
407
+
408
+ ###############
409
+ # delete_at #
410
+ ###############
411
+
412
+ def delete_at( index )
413
+
414
+ deleted_object = nil
415
+
416
+ if @without_hooks
417
+ pre_delete_hook_result = true
418
+ else
419
+ pre_delete_hook_result = pre_delete_hook( index )
420
+ end
421
+
422
+ if pre_delete_hook_result
423
+
424
+ deleted_object = perform_delete_between_hooks( index )
425
+
426
+ unless @without_hooks
427
+ deleted_object = post_delete_hook( index, deleted_object )
428
+ end
429
+
430
+ end
431
+
432
+ return deleted_object
433
+
434
+ end
435
+
436
+ #############################
437
+ # delete_at_without_hooks #
438
+ #############################
439
+
440
+ # Alias to :delete_at that bypasses hooks.
441
+ # @param [Fixnum] index Index to delete.
442
+ # @return [Object] Deleted element.
443
+ def delete_at_without_hooks( index )
444
+
445
+ @without_hooks = true
446
+
447
+ object = delete_at( index )
448
+
449
+ @without_hooks = false
450
+
451
+ return object
452
+
453
+ end
454
+
455
+ #######################
456
+ # delete_at_indexes #
457
+ #######################
458
+
459
+ def delete_at_indexes( *indexes )
460
+
461
+ indexes = indexes.sort.uniq.reverse
462
+
463
+ objects = [ ]
464
+
465
+ indexes.each do |this_index|
466
+ objects.push( delete_at( this_index ) )
467
+ end
468
+
469
+ return objects
470
+
471
+ end
472
+
473
+ #####################################
474
+ # delete_at_indexes_without_hooks #
475
+ #####################################
476
+
477
+ # Alias to :delete_at that bypasses hooks and takes multiple indexes.
478
+ # @param [Array<Fixnum>] index Index to delete.
479
+ # @return [Object] Deleted element.
480
+ def delete_at_indexes_without_hooks( *indexes )
481
+
482
+ @without_hooks = true
483
+
484
+ objects = delete_at_indexes( *indexes )
485
+
486
+ @without_hooks = false
487
+
488
+ return objects
489
+
490
+ end
491
+
492
+ ###############
493
+ # delete_if #
494
+ ###############
495
+
496
+ def delete_if
497
+
498
+ return to_enum unless block_given?
499
+
500
+ indexes = [ ]
501
+
502
+ self.each_with_index do |this_object, index|
503
+ if yield( this_object )
504
+ indexes.push( index )
505
+ end
506
+ end
507
+
508
+ delete_at_indexes( *indexes )
509
+
510
+ return self
511
+
512
+ end
513
+
514
+ #############################
515
+ # delete_if_without_hooks #
516
+ #############################
517
+
518
+ # Alias to :delete_if that bypasses hooks.
519
+ # @yield Block passed to :delete_if.
520
+ # @return [Object] Deleted element.
521
+ def delete_if_without_hooks( & block )
522
+
523
+ @without_hooks = true
524
+
525
+ delete_if( & block )
526
+
527
+ @without_hooks = false
528
+
529
+ return self
530
+
531
+ end
532
+
533
+ #############
534
+ # keep_if #
535
+ #############
536
+
537
+ def keep_if
538
+
539
+ indexes = [ ]
540
+
541
+ self.each_with_index do |this_object, index|
542
+ unless yield( this_object )
543
+ indexes.push( index )
544
+ end
545
+ end
546
+
547
+ delete_at_indexes( *indexes )
548
+
549
+ return self
550
+
551
+ end
552
+
553
+ ###########################
554
+ # keep_if_without_hooks #
555
+ ###########################
556
+
557
+ # Alias to :keep_if that bypasses hooks.
558
+ # @yield Block passed to :keep_if.
559
+ # @return [Object] Deleted element.
560
+ def keep_if_without_hooks( & block )
561
+
562
+ @without_hooks = true
563
+
564
+ keep_if( & block )
565
+
566
+ @without_hooks = false
567
+
568
+ return self
569
+
570
+ end
571
+
572
+ ##############
573
+ # compact! #
574
+ ##############
575
+
576
+ def compact!
577
+
578
+ return keep_if do |object|
579
+ object != nil
580
+ end
581
+
582
+ end
583
+
584
+ ############################
585
+ # compact_without_hooks! #
586
+ ############################
587
+
588
+ # Alias to :compact that bypasses hooks.
589
+ # @return [Object] Self.
590
+ def compact_without_hooks!
591
+
592
+ @without_hooks = true
593
+
594
+ compact!
595
+
596
+ @without_hooks = false
597
+
598
+ return self
599
+
600
+ end
601
+
602
+ ##############
603
+ # flatten! #
604
+ ##############
605
+
606
+ def flatten!
607
+
608
+ return_value = nil
609
+
610
+ indexes = [ ]
611
+
612
+ self.each_with_index do |this_object, index|
613
+ if this_object.is_a?( Array )
614
+ indexes.push( index )
615
+ end
616
+ end
617
+
618
+ unless indexes.empty?
619
+ indexes.sort!.reverse!
620
+ indexes.each do |this_index|
621
+ this_array = delete_at( this_index )
622
+ insert( this_index, *this_array )
623
+ end
624
+ return_value = self
625
+ end
626
+
627
+ return return_value
628
+
629
+ end
630
+
631
+ ############################
632
+ # flatten_without_hooks! #
633
+ ############################
634
+
635
+ # Alias to :flatten that bypasses hooks.
636
+ # @return [Object] Self.
637
+ def flatten_without_hooks!
638
+
639
+ @without_hooks = true
640
+
641
+ return_value = flatten!
642
+
643
+ @without_hooks = false
644
+
645
+ return return_value
646
+
647
+ end
648
+
649
+ #############
650
+ # reject! #
651
+ #############
652
+
653
+ def reject!
654
+
655
+ return to_enum unless block_given?
656
+
657
+ return_value = nil
658
+
659
+ deleted_objects = 0
660
+
661
+ iteration_dup = dup
662
+ iteration_dup.each_with_index do |this_object, index|
663
+ if yield( this_object )
664
+ delete_at( index - deleted_objects )
665
+ deleted_objects += 1
666
+ end
667
+ end
668
+
669
+ if deleted_objects > 0
670
+ return_value = self
671
+ end
672
+
673
+ return return_value
674
+
675
+ end
676
+
677
+ ###########################
678
+ # reject_without_hooks! #
679
+ ###########################
680
+
681
+ # Alias to :reject that bypasses hooks.
682
+ # @yield Block passed to :keep_if.
683
+ # @return [Object] Self.
684
+ def reject_without_hooks!( & block )
685
+
686
+ @without_hooks = true
687
+
688
+ reject!( & block )
689
+
690
+ @without_hooks = false
691
+
692
+ return return_value
693
+
694
+ end
695
+
696
+ #############
697
+ # replace #
698
+ #############
699
+
700
+ def replace( other_array )
701
+
702
+ clear
703
+
704
+ other_array.each_with_index do |this_object, index|
705
+ unless self[ index ] == this_object
706
+ self[ index ] = this_object
707
+ end
708
+ end
709
+
710
+ return self
711
+
712
+ end
713
+
714
+ ###########################
715
+ # replace_without_hooks #
716
+ ###########################
717
+
718
+ # Alias to :replace that bypasses hooks.
719
+ # @param [Array] other_array Other array to replace self with.
720
+ # @return [Object] Self.
721
+ def replace_without_hooks( other_array )
722
+
723
+ @without_hooks = true
724
+
725
+ replace( other_array )
726
+
727
+ @without_hooks = false
728
+
729
+ return self
730
+
731
+ end
732
+
733
+ ##############
734
+ # reverse! #
735
+ ##############
736
+
737
+ def reverse!
738
+
739
+ reversed_array = reverse
740
+
741
+ clear
742
+
743
+ reversed_array.each_with_index do |this_object, index|
744
+ self[ index ] = this_object
745
+ end
746
+
747
+ return self
748
+
749
+ end
750
+
751
+ ############################
752
+ # reverse_without_hooks! #
753
+ ############################
754
+
755
+ # Alias to :reverse that bypasses hooks.
756
+ # @return [Object] Self.
757
+ def reverse_without_hooks!
758
+
759
+ @without_hooks = true
760
+
761
+ reverse!
762
+
763
+ @without_hooks = false
764
+
765
+ return self
766
+
767
+ end
768
+
769
+ #############
770
+ # rotate! #
771
+ #############
772
+
773
+ def rotate!( rotate_count = 1 )
774
+
775
+ reversed_array = rotate( rotate_count )
776
+
777
+ clear
778
+
779
+ reversed_array.each_with_index do |this_object, index|
780
+ self[ index ] = this_object
781
+ end
782
+
783
+ return self
784
+
785
+ end
786
+
787
+ ###########################
788
+ # rotate_without_hooks! #
789
+ ###########################
790
+
791
+ # Alias to :rotate that bypasses hooks.
792
+ # @param [Fixnum] rotate_count Integer count of how many elements to rotate.
793
+ # @return [Object] Self.
794
+ def rotate_without_hooks!( rotate_count = 1 )
795
+
796
+ @without_hooks = true
797
+
798
+ rotate!( rotate_count )
799
+
800
+ @without_hooks = false
801
+
802
+ return self
803
+
804
+ end
805
+
806
+ #############
807
+ # select! #
808
+ #############
809
+
810
+ def select!
811
+
812
+ return to_enum unless block_given?
813
+
814
+ deleted_objects = 0
815
+
816
+ iteration_dup = dup
817
+ iteration_dup.each_with_index do |this_object, index|
818
+ unless yield( this_object )
819
+ delete_at( index - deleted_objects )
820
+ deleted_objects += 1
821
+ end
822
+ end
823
+
824
+ return self
825
+
826
+ end
827
+
828
+ ###########################
829
+ # select_without_hooks! #
830
+ ###########################
831
+
832
+ # Alias to :select that bypasses hooks.
833
+ # @yield Block passed to :select!.
834
+ # @return [Object] Self.
835
+ def select_without_hooks!( & block )
836
+
837
+ @without_hooks = true
838
+
839
+ select!( & block )
840
+
841
+ @without_hooks = false
842
+
843
+ return self
844
+
845
+ end
846
+
847
+ ##############
848
+ # shuffle! #
849
+ ##############
850
+
851
+ def shuffle!( random_number_generator = nil )
852
+
853
+ shuffled_array = shuffle( random: random_number_generator )
854
+
855
+ clear
856
+
857
+ shuffled_array.each_with_index do |this_object, index|
858
+ self[ index ] = this_object
859
+ end
860
+
861
+ return self
862
+
863
+ end
864
+
865
+ ############################
866
+ # shuffle_without_hooks! #
867
+ ############################
868
+
869
+ # Alias to :shuffle that bypasses hooks.
870
+ # @param [Object] random_number_generator Random number generator passed to :shuffle!.
871
+ # @return [Object] Self.
872
+ def shuffle_without_hooks!( random_number_generator = nil )
873
+
874
+ @without_hooks = true
875
+
876
+ shuffle!( random_number_generator )
877
+
878
+ @without_hooks = false
879
+
880
+ return self
881
+
882
+ end
883
+
884
+ ##############
885
+ # collect! #
886
+ # map! #
887
+ ##############
888
+
889
+ def collect!
890
+
891
+ return to_enum unless block_given?
892
+
893
+ self.each_with_index do |this_object, index|
894
+ replacement_object = yield( this_object )
895
+ self[ index ] = replacement_object
896
+ end
897
+
898
+ return self
899
+
900
+ end
901
+
902
+ alias_method :map!, :collect!
903
+
904
+ ############################
905
+ # collect_without_hooks! #
906
+ # map_without_hooks! #
907
+ ############################
908
+
909
+ # Alias to :select that bypasses hooks.
910
+ # @yield Block passed to :collect!.
911
+ # @return [Object] Self.
912
+ def collect_without_hooks!( & block )
913
+
914
+ @without_hooks = true
915
+
916
+ collect!( & block )
917
+
918
+ @without_hooks = false
919
+
920
+ return self
921
+
922
+ end
923
+
924
+ alias_method :map_without_hooks!, :collect_without_hooks!
925
+
926
+ ###########
927
+ # sort! #
928
+ ###########
929
+
930
+ def sort!( & block )
931
+
932
+ sorted_array = sort( & block )
933
+
934
+ unless sorted_array == self
935
+
936
+ replace( sorted_array )
937
+
938
+ end
939
+
940
+ return self
941
+
942
+ end
943
+
944
+ #########################
945
+ # sort_without_hooks! #
946
+ #########################
947
+
948
+ # Alias to :sort that bypasses hooks.
949
+ # @yield Block passed to :sort!.
950
+ # @return [Object] Self.
951
+ def sort_without_hooks!( & block )
952
+
953
+ @without_hooks = true
954
+
955
+ sort!
956
+
957
+ @without_hooks = false
958
+
959
+ return self
960
+
961
+ end
962
+
963
+ ##############
964
+ # sort_by! #
965
+ ##############
966
+
967
+ def sort_by!( & block )
968
+
969
+ return to_enum unless block_given?
970
+
971
+ sorted_array = sort_by( & block )
972
+
973
+ unless sorted_array == self
974
+
975
+ replace( sorted_array )
976
+
977
+ end
978
+
979
+ return self
980
+
981
+ end
982
+
983
+ ############################
984
+ # sort_by_without_hooks! #
985
+ ############################
986
+
987
+ # Alias to :sort_by! that bypasses hooks.
988
+ # @yield Block passed to :sort_by!.
989
+ # @return [Object] Self.
990
+ def sort_by_without_hooks!( & block )
991
+
992
+ @without_hooks = true
993
+
994
+ sort_by!( & block )
995
+
996
+ @without_hooks = false
997
+
998
+ return self
999
+
1000
+ end
1001
+
1002
+ ###########
1003
+ # uniq! #
1004
+ ###########
1005
+
1006
+ def uniq!
1007
+
1008
+ return_value = nil
1009
+
1010
+ uniq_array = uniq
1011
+
1012
+ unless uniq_array == self
1013
+
1014
+ clear
1015
+
1016
+ replace( uniq_array )
1017
+
1018
+ end
1019
+
1020
+ return return_value
1021
+
1022
+ end
1023
+
1024
+ #########################
1025
+ # uniq_without_hooks! #
1026
+ #########################
1027
+
1028
+ # Alias to :uniq! that bypasses hooks.
1029
+ # @return [Object] Self.
1030
+ def uniq_without_hooks!
1031
+
1032
+ @without_hooks = true
1033
+
1034
+ return_value = uniq!
1035
+
1036
+ @without_hooks = false
1037
+
1038
+ return return_value
1039
+
1040
+ end
1041
+
1042
+ #############
1043
+ # unshift #
1044
+ #############
1045
+
1046
+ def unshift( object )
1047
+
1048
+ insert( 0, object )
1049
+
1050
+ return self
1051
+
1052
+ end
1053
+
1054
+ ###########################
1055
+ # unshift_without_hooks #
1056
+ ###########################
1057
+
1058
+ # Alias to :unshift that bypasses hooks.
1059
+ # @param [Object] object Object to unshift onto self.
1060
+ # @return [Object] Self.
1061
+ def unshift_without_hooks( object )
1062
+
1063
+ @without_hooks = true
1064
+
1065
+ unshift( object )
1066
+
1067
+ @without_hooks = false
1068
+
1069
+ return self
1070
+
1071
+ end
1072
+
1073
+ #########
1074
+ # pop #
1075
+ #########
1076
+
1077
+ def pop
1078
+
1079
+ object = delete_at( count - 1 )
1080
+
1081
+ return object
1082
+
1083
+ end
1084
+
1085
+ #######################
1086
+ # pop_without_hooks #
1087
+ #######################
1088
+
1089
+ # Alias to :pop that bypasses hooks.
1090
+ # @return [Object] Self.
1091
+ def pop_without_hooks
1092
+
1093
+ @without_hooks = true
1094
+
1095
+ object = pop
1096
+
1097
+ @without_hooks = false
1098
+
1099
+ return object
1100
+
1101
+ end
1102
+
1103
+ ###########
1104
+ # shift #
1105
+ ###########
1106
+
1107
+ def shift
1108
+
1109
+ object = delete_at( 0 )
1110
+
1111
+ return object
1112
+
1113
+ end
1114
+
1115
+ #########################
1116
+ # shift_without_hooks #
1117
+ #########################
1118
+
1119
+ # Alias to :shift that bypasses hooks.
1120
+ # @return [Object] Self.
1121
+ def shift_without_hooks
1122
+
1123
+ @without_hooks = true
1124
+
1125
+ object = shift
1126
+
1127
+ @without_hooks = false
1128
+
1129
+ return object
1130
+
1131
+ end
1132
+
1133
+ ############
1134
+ # slice! #
1135
+ ############
1136
+
1137
+ def slice!( index_start_or_range, length = nil )
1138
+
1139
+ slice = nil
1140
+
1141
+ start_index = nil
1142
+ end_index = nil
1143
+
1144
+ if index_start_or_range.is_a?( Range )
1145
+
1146
+ start_index = index_start_or_range.begin
1147
+ end_index = index_start_or_range.end
1148
+
1149
+ elsif length
1150
+
1151
+ start_index = index_start_or_range
1152
+ end_index = index_start_or_range + length
1153
+
1154
+ end
1155
+
1156
+ if end_index
1157
+
1158
+ indexes = [ ]
1159
+
1160
+ ( end_index - start_index ).times do |this_time|
1161
+ indexes.push( end_index - this_time - 1 )
1162
+ end
1163
+
1164
+ slice = delete_at_indexes( *indexes )
1165
+
1166
+ else
1167
+
1168
+ slice = delete_at( start_index )
1169
+
1170
+ end
1171
+
1172
+
1173
+ return slice
1174
+
1175
+ end
1176
+
1177
+ ##########################
1178
+ # slice_without_hooks! #
1179
+ ##########################
1180
+
1181
+ # Alias to :slice! that bypasses hooks.
1182
+ # @param [Fixnum] index_start_or_range Index at which to begin slice.
1183
+ # @param [Fixnum] length Length of slice.
1184
+ # @return [Object] Self.
1185
+ def slice_without_hooks!( index_start_or_range, length = nil )
1186
+
1187
+ @without_hooks = true
1188
+
1189
+ slice = slice!( index_start_or_range, length )
1190
+
1191
+ @without_hooks = false
1192
+
1193
+ return slice
1194
+
1195
+ end
1196
+
1197
+ ###########
1198
+ # clear #
1199
+ ###########
1200
+
1201
+ def clear
1202
+
1203
+ indexes = [ ]
1204
+
1205
+ count.times do |this_time|
1206
+ indexes.push( count - this_time - 1 )
1207
+ end
1208
+
1209
+ delete_at_indexes( *indexes )
1210
+
1211
+ return self
1212
+
1213
+ end
1214
+
1215
+ #########################
1216
+ # clear_without_hooks #
1217
+ #########################
1218
+
1219
+ # Alias to :clear that bypasses hooks.
1220
+ # @return [Object] Self.
1221
+ def clear_without_hooks
1222
+
1223
+ @without_hooks = true
1224
+
1225
+ clear
1226
+
1227
+ @without_hooks = false
1228
+
1229
+ return self
1230
+
1231
+ end
1232
+
1233
+ end