compositing-hash 1.0.15
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/README.md +65 -0
- data/README.rdoc +0 -0
- data/lib/compositing-hash.rb +5 -0
- data/lib/compositing-hash/CompositingHash.rb +374 -0
- data/spec/CompositingHash_spec.rb +648 -0
- metadata +67 -0
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# CompositingHash #
|
2
|
+
|
3
|
+
http://rubygems.org/gems/compositing-hash
|
4
|
+
|
5
|
+
# Description #
|
6
|
+
|
7
|
+
Provides CompositingHash.
|
8
|
+
|
9
|
+
# Summary #
|
10
|
+
|
11
|
+
An implementation of Hash that permits chaining, where children inherit changes to parent and where parent settings can be overridden in children.
|
12
|
+
|
13
|
+
# Install #
|
14
|
+
|
15
|
+
* sudo gem install compositing-hash
|
16
|
+
|
17
|
+
# Usage #
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
compositing_hash = CompositingHash.new
|
21
|
+
sub_compositing_hash = CompositingHash.new( compositing_hash )
|
22
|
+
|
23
|
+
compositing_hash[ :some_key ] = :some_value
|
24
|
+
# compositing_hash
|
25
|
+
# => { :some_key => :some_value }
|
26
|
+
# sub_compositing_hash
|
27
|
+
# => { :some_key => :some_value }
|
28
|
+
|
29
|
+
compositing_hash.delete( :some_key )
|
30
|
+
# compositing_hash
|
31
|
+
# => { }
|
32
|
+
# sub_compositing_hash
|
33
|
+
# => { }
|
34
|
+
|
35
|
+
sub_compositing_hash[ :some_key ] = :some_value
|
36
|
+
# compositing_hash
|
37
|
+
# => { }
|
38
|
+
# sub_compositing_hash
|
39
|
+
# => { :some_key => :some_value }
|
40
|
+
```
|
41
|
+
|
42
|
+
# License #
|
43
|
+
|
44
|
+
(The MIT License)
|
45
|
+
|
46
|
+
Copyright (c) Asher
|
47
|
+
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
49
|
+
a copy of this software and associated documentation files (the
|
50
|
+
'Software'), to deal in the Software without restriction, including
|
51
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
52
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
53
|
+
permit persons to whom the Software is furnished to do so, subject to
|
54
|
+
the following conditions:
|
55
|
+
|
56
|
+
The above copyright notice and this permission notice shall be
|
57
|
+
included in all copies or substantial portions of the Software.
|
58
|
+
|
59
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
60
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
61
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
62
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
63
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
64
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
65
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
File without changes
|
@@ -0,0 +1,374 @@
|
|
1
|
+
|
2
|
+
class ::CompositingHash < ::HookedHash
|
3
|
+
|
4
|
+
################
|
5
|
+
# initialize #
|
6
|
+
################
|
7
|
+
|
8
|
+
def initialize( parent_composite_hash = nil, configuration_instance = nil )
|
9
|
+
|
10
|
+
super( configuration_instance )
|
11
|
+
|
12
|
+
@replaced_parents = { }
|
13
|
+
@parent_key_lookup = { }
|
14
|
+
|
15
|
+
# we may later have our own child composites that register with us
|
16
|
+
@sub_composite_hashes = [ ]
|
17
|
+
|
18
|
+
initialize_for_parent( parent_composite_hash )
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
#############################
|
23
|
+
# parent_composite_object #
|
24
|
+
# parent_composite_hash #
|
25
|
+
#############################
|
26
|
+
|
27
|
+
attr_accessor :parent_composite_object
|
28
|
+
|
29
|
+
alias_method :parent_composite_hash, :parent_composite_object
|
30
|
+
|
31
|
+
################################### Sub-Hash Management #######################################
|
32
|
+
|
33
|
+
###########################
|
34
|
+
# initialize_for_parent #
|
35
|
+
###########################
|
36
|
+
|
37
|
+
def initialize_for_parent( parent_composite_hash )
|
38
|
+
|
39
|
+
if @parent_composite_object = parent_composite_hash
|
40
|
+
|
41
|
+
@parent_composite_object.register_sub_composite_hash( self )
|
42
|
+
|
43
|
+
# @parent_key_lookup tracks keys that we have not yet received from parent
|
44
|
+
@parent_composite_object.each do |this_key, this_object|
|
45
|
+
@parent_key_lookup[ this_key ] = true
|
46
|
+
non_cascading_store( this_key, nil )
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
#################################
|
54
|
+
# register_sub_composite_hash #
|
55
|
+
#################################
|
56
|
+
|
57
|
+
def register_sub_composite_hash( sub_composite_hash )
|
58
|
+
|
59
|
+
@sub_composite_hashes.push( sub_composite_hash )
|
60
|
+
|
61
|
+
return self
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
###################################
|
66
|
+
# unregister_sub_composite_hash #
|
67
|
+
###################################
|
68
|
+
|
69
|
+
def unregister_sub_composite_hash( sub_composite_hash )
|
70
|
+
|
71
|
+
@sub_composite_hashes.delete( sub_composite_hash )
|
72
|
+
|
73
|
+
return self
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
###################################### Subclass Hooks ##########################################
|
78
|
+
|
79
|
+
########################
|
80
|
+
# child_pre_set_hook #
|
81
|
+
########################
|
82
|
+
|
83
|
+
def child_pre_set_hook( key, object )
|
84
|
+
|
85
|
+
return object
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
#########################
|
90
|
+
# child_post_set_hook #
|
91
|
+
#########################
|
92
|
+
|
93
|
+
def child_post_set_hook( key, object )
|
94
|
+
|
95
|
+
return object
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
###########################
|
100
|
+
# child_pre_delete_hook #
|
101
|
+
###########################
|
102
|
+
|
103
|
+
def child_pre_delete_hook( key )
|
104
|
+
|
105
|
+
# false means delete does not take place
|
106
|
+
return true
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
############################
|
111
|
+
# child_post_delete_hook #
|
112
|
+
############################
|
113
|
+
|
114
|
+
def child_post_delete_hook( key, object )
|
115
|
+
|
116
|
+
return object
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
##################################### Self Management ##########################################
|
121
|
+
|
122
|
+
########
|
123
|
+
# == #
|
124
|
+
########
|
125
|
+
|
126
|
+
def ==( object )
|
127
|
+
|
128
|
+
@parent_key_lookup.each do |this_key, true_value|
|
129
|
+
self[ this_key ]
|
130
|
+
end
|
131
|
+
|
132
|
+
super
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
##########
|
137
|
+
# each #
|
138
|
+
##########
|
139
|
+
|
140
|
+
def each( *args, & block )
|
141
|
+
|
142
|
+
@parent_key_lookup.each do |this_key, true_value|
|
143
|
+
self[ this_key ]
|
144
|
+
end
|
145
|
+
|
146
|
+
super
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
##########
|
151
|
+
# to_s #
|
152
|
+
##########
|
153
|
+
|
154
|
+
def to_s
|
155
|
+
|
156
|
+
@parent_key_lookup.each do |this_key, true_value|
|
157
|
+
self[ this_key ]
|
158
|
+
end
|
159
|
+
|
160
|
+
super
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
#############
|
165
|
+
# inspect #
|
166
|
+
#############
|
167
|
+
|
168
|
+
def inspect
|
169
|
+
|
170
|
+
@parent_key_lookup.each do |this_key, true_value|
|
171
|
+
self[ this_key ]
|
172
|
+
end
|
173
|
+
|
174
|
+
super
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
########
|
179
|
+
# [] #
|
180
|
+
########
|
181
|
+
|
182
|
+
def []( key )
|
183
|
+
|
184
|
+
return_value = nil
|
185
|
+
|
186
|
+
if @parent_key_lookup.has_key?( key )
|
187
|
+
return_value = set_parent_element_in_self( key, @parent_composite_object[ key ] )
|
188
|
+
@parent_key_lookup.delete( key )
|
189
|
+
else
|
190
|
+
return_value = super
|
191
|
+
end
|
192
|
+
|
193
|
+
return return_value
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
#########
|
198
|
+
# []= #
|
199
|
+
#########
|
200
|
+
|
201
|
+
private
|
202
|
+
alias_method :non_cascading_store, :store
|
203
|
+
public
|
204
|
+
|
205
|
+
def []=( key, object )
|
206
|
+
|
207
|
+
@replaced_parents[ key ] = true
|
208
|
+
|
209
|
+
@parent_key_lookup.delete( key )
|
210
|
+
|
211
|
+
super
|
212
|
+
|
213
|
+
@sub_composite_hashes.each do |this_sub_hash|
|
214
|
+
this_sub_hash.instance_eval do
|
215
|
+
update_as_sub_hash_for_parent_store( key )
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
return object
|
220
|
+
|
221
|
+
end
|
222
|
+
alias_method :store, :[]=
|
223
|
+
|
224
|
+
############
|
225
|
+
# delete #
|
226
|
+
############
|
227
|
+
|
228
|
+
private
|
229
|
+
alias_method :non_cascading_delete, :delete
|
230
|
+
public
|
231
|
+
|
232
|
+
def delete( key )
|
233
|
+
|
234
|
+
@replaced_parents.delete( key )
|
235
|
+
|
236
|
+
@parent_key_lookup.delete( key )
|
237
|
+
|
238
|
+
object = super
|
239
|
+
|
240
|
+
@sub_composite_hashes.each do |this_sub_hash|
|
241
|
+
this_sub_hash.instance_eval do
|
242
|
+
update_as_sub_hash_for_parent_delete( key, object )
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
return object
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
#############
|
251
|
+
# freeze! #
|
252
|
+
#############
|
253
|
+
|
254
|
+
# freezes configuration and prevents ancestors from changing this configuration in the future
|
255
|
+
def freeze!
|
256
|
+
|
257
|
+
# unregister with parent composite so we don't get future updates from it
|
258
|
+
if @parent_composite_object
|
259
|
+
@parent_composite_object.unregister_sub_composite_hash( self )
|
260
|
+
end
|
261
|
+
|
262
|
+
return self
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
##################################################################################################
|
267
|
+
private ######################################################################################
|
268
|
+
##################################################################################################
|
269
|
+
|
270
|
+
######################### Self-as-Sub Management for Parent Updates ############################
|
271
|
+
|
272
|
+
################################
|
273
|
+
# set_parent_element_in_self #
|
274
|
+
################################
|
275
|
+
|
276
|
+
def set_parent_element_in_self( key, object )
|
277
|
+
|
278
|
+
unless @without_child_hooks
|
279
|
+
object = child_pre_set_hook( key, object )
|
280
|
+
end
|
281
|
+
|
282
|
+
unless @without_hooks
|
283
|
+
object = pre_set_hook( key, object )
|
284
|
+
end
|
285
|
+
|
286
|
+
non_cascading_store( key, object )
|
287
|
+
|
288
|
+
unless @without_hooks
|
289
|
+
object = post_set_hook( key, object )
|
290
|
+
end
|
291
|
+
|
292
|
+
unless @without_child_hooks
|
293
|
+
object = child_post_set_hook( key, object )
|
294
|
+
end
|
295
|
+
|
296
|
+
return object
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
#########################################
|
301
|
+
# update_as_sub_hash_for_parent_store #
|
302
|
+
#########################################
|
303
|
+
|
304
|
+
def update_as_sub_hash_for_parent_store( key )
|
305
|
+
|
306
|
+
unless @replaced_parents[ key ]
|
307
|
+
|
308
|
+
@parent_key_lookup[ key ] = true
|
309
|
+
|
310
|
+
@sub_composite_hashes.each do |this_hash|
|
311
|
+
this_hash.instance_eval do
|
312
|
+
update_as_sub_hash_for_parent_store( key )
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
##########################################
|
321
|
+
# update_as_sub_hash_for_parent_delete #
|
322
|
+
##########################################
|
323
|
+
|
324
|
+
def update_as_sub_hash_for_parent_delete( key, object )
|
325
|
+
|
326
|
+
unless @replaced_parents[ key ]
|
327
|
+
|
328
|
+
if @without_child_hooks
|
329
|
+
child_pre_delete_hook_result = true
|
330
|
+
else
|
331
|
+
child_pre_delete_hook_result = child_pre_delete_hook( key )
|
332
|
+
end
|
333
|
+
|
334
|
+
if @without_hooks
|
335
|
+
pre_delete_hook_result = true
|
336
|
+
else
|
337
|
+
pre_delete_hook_result = pre_delete_hook( key )
|
338
|
+
end
|
339
|
+
|
340
|
+
if child_pre_delete_hook_result and pre_delete_hook_result
|
341
|
+
|
342
|
+
@parent_key_lookup.delete( key )
|
343
|
+
object = non_cascading_delete( key )
|
344
|
+
|
345
|
+
unless @without_hooks
|
346
|
+
post_delete_hook( key, object )
|
347
|
+
end
|
348
|
+
|
349
|
+
unless @without_child_hooks
|
350
|
+
child_post_delete_hook( key, object )
|
351
|
+
end
|
352
|
+
|
353
|
+
else
|
354
|
+
|
355
|
+
# if we were told not to delete in child when parent delete
|
356
|
+
# and the child does not yet have its parent value
|
357
|
+
# then we need to get it now
|
358
|
+
if @parent_key_lookup.delete( key )
|
359
|
+
self[ key ] = object
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
363
|
+
|
364
|
+
@sub_composite_hashes.each do |this_hash|
|
365
|
+
this_hash.instance_eval do
|
366
|
+
update_as_sub_hash_for_parent_delete( key, object )
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
end
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
@@ -0,0 +1,648 @@
|
|
1
|
+
|
2
|
+
require_relative '../lib/compositing-hash.rb'
|
3
|
+
|
4
|
+
describe ::CompositingHash do
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
|
8
|
+
module ::CompositingHash::MockA
|
9
|
+
# needed for ccv ancestor determination
|
10
|
+
def self.some_configuration
|
11
|
+
end
|
12
|
+
end
|
13
|
+
module ::CompositingHash::MockB
|
14
|
+
end
|
15
|
+
|
16
|
+
@configuration_instance = ::CompositingHash::MockA
|
17
|
+
@sub_configuration_instance = ::CompositingHash::MockB
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
################
|
22
|
+
# initialize #
|
23
|
+
################
|
24
|
+
|
25
|
+
it 'can add initialize with an ancestor, inheriting its values and linking to it as a child' do
|
26
|
+
|
27
|
+
cascading_composite_hash = ::CompositingHash.new
|
28
|
+
|
29
|
+
cascading_composite_hash.instance_variable_get( :@parent_composite_object ).should == nil
|
30
|
+
cascading_composite_hash.should == {}
|
31
|
+
cascading_composite_hash[ :A ] = 1
|
32
|
+
cascading_composite_hash[ :B ] = 2
|
33
|
+
cascading_composite_hash[ :C ] = 3
|
34
|
+
cascading_composite_hash[ :D ] = 4
|
35
|
+
cascading_composite_hash.should == { :A => 1,
|
36
|
+
:B => 2,
|
37
|
+
:C => 3,
|
38
|
+
:D => 4 }
|
39
|
+
|
40
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
41
|
+
sub_cascading_composite_hash.instance_variable_get( :@parent_composite_object ).should == cascading_composite_hash
|
42
|
+
sub_cascading_composite_hash.should == { :A => 1,
|
43
|
+
:B => 2,
|
44
|
+
:C => 3,
|
45
|
+
:D => 4 }
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
##################################################################################################
|
50
|
+
# private #####################################################################################
|
51
|
+
##################################################################################################
|
52
|
+
|
53
|
+
#########################################
|
54
|
+
# update_as_sub_hash_for_parent_store #
|
55
|
+
#########################################
|
56
|
+
|
57
|
+
it 'can update for a parent store' do
|
58
|
+
|
59
|
+
cascading_composite_hash = ::CompositingHash.new
|
60
|
+
cascading_composite_hash[ :A ] = 1
|
61
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
62
|
+
|
63
|
+
sub_cascading_composite_hash.instance_eval do
|
64
|
+
update_as_sub_hash_for_parent_store( :A )
|
65
|
+
self.should == { :A => 1 }
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
##########################################
|
71
|
+
# update_as_sub_hash_for_parent_delete #
|
72
|
+
##########################################
|
73
|
+
|
74
|
+
it 'can update for a parent delete' do
|
75
|
+
|
76
|
+
cascading_composite_hash = ::CompositingHash.new
|
77
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
78
|
+
|
79
|
+
cascading_composite_hash[ :A ] = 1
|
80
|
+
cascading_composite_hash.should == { :A => 1 }
|
81
|
+
sub_cascading_composite_hash.should == { :A => 1 }
|
82
|
+
|
83
|
+
sub_cascading_composite_hash.instance_eval do
|
84
|
+
update_as_sub_hash_for_parent_delete( :A, 1 )
|
85
|
+
self.should == { }
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
##################################################################################################
|
91
|
+
# public ######################################################################################
|
92
|
+
##################################################################################################
|
93
|
+
|
94
|
+
#########
|
95
|
+
# []= #
|
96
|
+
#########
|
97
|
+
|
98
|
+
it 'can add elements' do
|
99
|
+
|
100
|
+
cascading_composite_hash = ::CompositingHash.new
|
101
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
102
|
+
|
103
|
+
cascading_composite_hash[ :some_setting ] = :some_value
|
104
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
105
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value }
|
106
|
+
|
107
|
+
cascading_composite_hash[ :other_setting ] = :some_value
|
108
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
109
|
+
:other_setting => :some_value }
|
110
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
111
|
+
:other_setting => :some_value }
|
112
|
+
|
113
|
+
sub_cascading_composite_hash[ :yet_another_setting ] = :some_value
|
114
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
115
|
+
:other_setting => :some_value }
|
116
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
117
|
+
:other_setting => :some_value,
|
118
|
+
:yet_another_setting => :some_value }
|
119
|
+
|
120
|
+
cascading_composite_hash.method( :[]= ).should == cascading_composite_hash.method( :store )
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
############
|
125
|
+
# delete #
|
126
|
+
############
|
127
|
+
|
128
|
+
it 'can delete elements' do
|
129
|
+
|
130
|
+
cascading_composite_hash = ::CompositingHash.new
|
131
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
132
|
+
|
133
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
134
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
135
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value }
|
136
|
+
|
137
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
138
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
139
|
+
:other_setting => :some_value }
|
140
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
141
|
+
:other_setting => :some_value }
|
142
|
+
|
143
|
+
cascading_composite_hash.delete( :some_setting )
|
144
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
145
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
146
|
+
|
147
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
148
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
149
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
150
|
+
:yet_another_setting => :some_value }
|
151
|
+
|
152
|
+
sub_cascading_composite_hash.delete( :other_setting )
|
153
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
154
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
###############
|
159
|
+
# delete_if #
|
160
|
+
###############
|
161
|
+
|
162
|
+
it 'can delete elements with a block' do
|
163
|
+
|
164
|
+
cascading_composite_hash = ::CompositingHash.new
|
165
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
166
|
+
|
167
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
168
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
169
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value }
|
170
|
+
|
171
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
172
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
173
|
+
:other_setting => :some_value }
|
174
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
175
|
+
:other_setting => :some_value }
|
176
|
+
cascading_composite_hash.delete_if do |key, value|
|
177
|
+
key == :some_setting
|
178
|
+
end
|
179
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
180
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
181
|
+
|
182
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
183
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
184
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
185
|
+
:yet_another_setting => :some_value }
|
186
|
+
sub_cascading_composite_hash.delete_if do |key, value|
|
187
|
+
key == :other_setting
|
188
|
+
end
|
189
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
190
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
#############
|
195
|
+
# reject! #
|
196
|
+
#############
|
197
|
+
|
198
|
+
it 'can delete elements with a block' do
|
199
|
+
|
200
|
+
cascading_composite_hash = ::CompositingHash.new
|
201
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
202
|
+
|
203
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
204
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
205
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value }
|
206
|
+
|
207
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
208
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
209
|
+
:other_setting => :some_value }
|
210
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
211
|
+
:other_setting => :some_value }
|
212
|
+
cascading_composite_hash.reject! do |key, value|
|
213
|
+
key == :some_setting
|
214
|
+
end
|
215
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
216
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
217
|
+
|
218
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
219
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
220
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
221
|
+
:yet_another_setting => :some_value }
|
222
|
+
sub_cascading_composite_hash.reject! do |key, value|
|
223
|
+
key == :other_setting
|
224
|
+
end
|
225
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
226
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
#############
|
231
|
+
# keep_if #
|
232
|
+
#############
|
233
|
+
|
234
|
+
it 'can keep elements with a block' do
|
235
|
+
|
236
|
+
cascading_composite_hash = ::CompositingHash.new
|
237
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
238
|
+
|
239
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
240
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
241
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value }
|
242
|
+
|
243
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
244
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
245
|
+
:other_setting => :some_value }
|
246
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
247
|
+
:other_setting => :some_value }
|
248
|
+
cascading_composite_hash.keep_if do |key, value|
|
249
|
+
key != :some_setting
|
250
|
+
end
|
251
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
252
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
253
|
+
|
254
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
255
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
256
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
257
|
+
:yet_another_setting => :some_value }
|
258
|
+
sub_cascading_composite_hash.keep_if do |key, value|
|
259
|
+
key != :other_setting
|
260
|
+
end
|
261
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
262
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
#############
|
267
|
+
# select! #
|
268
|
+
#############
|
269
|
+
|
270
|
+
it 'can keep elements with a block' do
|
271
|
+
|
272
|
+
cascading_composite_hash = ::CompositingHash.new
|
273
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
274
|
+
|
275
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
276
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
277
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value }
|
278
|
+
|
279
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
280
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
281
|
+
:other_setting => :some_value }
|
282
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
283
|
+
:other_setting => :some_value }
|
284
|
+
cascading_composite_hash.select! do |key, value|
|
285
|
+
key != :some_setting
|
286
|
+
end
|
287
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
288
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
289
|
+
|
290
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
291
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
292
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
293
|
+
:yet_another_setting => :some_value }
|
294
|
+
sub_cascading_composite_hash.select! do |key, value|
|
295
|
+
key != :other_setting
|
296
|
+
end
|
297
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
298
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
299
|
+
|
300
|
+
end
|
301
|
+
|
302
|
+
############
|
303
|
+
# merge! #
|
304
|
+
# update #
|
305
|
+
############
|
306
|
+
|
307
|
+
it 'can merge from another hash' do
|
308
|
+
|
309
|
+
cascading_composite_hash = ::CompositingHash.new
|
310
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
311
|
+
|
312
|
+
cascading_composite_hash.merge!( :some_setting => :some_value )
|
313
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
314
|
+
cascading_composite_hash.merge!( :other_setting => :some_value )
|
315
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
316
|
+
:other_setting => :some_value }
|
317
|
+
|
318
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
319
|
+
:other_setting => :some_value }
|
320
|
+
sub_cascading_composite_hash.merge!( :yet_another_setting => :some_value )
|
321
|
+
sub_cascading_composite_hash.should == { :some_setting => :some_value,
|
322
|
+
:other_setting => :some_value,
|
323
|
+
:yet_another_setting => :some_value }
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
#############
|
328
|
+
# replace #
|
329
|
+
#############
|
330
|
+
|
331
|
+
it 'can replace existing elements with others' do
|
332
|
+
|
333
|
+
cascading_composite_hash = ::CompositingHash.new
|
334
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
335
|
+
|
336
|
+
cascading_composite_hash.replace( :some_setting => :some_value )
|
337
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
338
|
+
cascading_composite_hash.replace( :other_setting => :some_value )
|
339
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
340
|
+
|
341
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
342
|
+
sub_cascading_composite_hash.replace( :yet_another_setting => :some_value )
|
343
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
344
|
+
|
345
|
+
end
|
346
|
+
|
347
|
+
###########
|
348
|
+
# shift #
|
349
|
+
###########
|
350
|
+
|
351
|
+
it 'can shift the first element' do
|
352
|
+
|
353
|
+
cascading_composite_hash = ::CompositingHash.new
|
354
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
355
|
+
|
356
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
357
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
358
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
359
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
360
|
+
:other_setting => :some_value }
|
361
|
+
cascading_composite_hash.shift
|
362
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
363
|
+
|
364
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
365
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
366
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
367
|
+
:yet_another_setting => :some_value }
|
368
|
+
sub_cascading_composite_hash.shift
|
369
|
+
sub_cascading_composite_hash.should == { :yet_another_setting => :some_value }
|
370
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
###########
|
375
|
+
# clear #
|
376
|
+
###########
|
377
|
+
|
378
|
+
it 'can clear, causing present elements to be excluded' do
|
379
|
+
|
380
|
+
cascading_composite_hash = ::CompositingHash.new
|
381
|
+
sub_cascading_composite_hash = ::CompositingHash.new( cascading_composite_hash )
|
382
|
+
|
383
|
+
cascading_composite_hash.store( :some_setting, :some_value )
|
384
|
+
cascading_composite_hash.should == { :some_setting => :some_value }
|
385
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
386
|
+
cascading_composite_hash.should == { :some_setting => :some_value,
|
387
|
+
:other_setting => :some_value }
|
388
|
+
cascading_composite_hash.clear
|
389
|
+
cascading_composite_hash.should == { }
|
390
|
+
cascading_composite_hash.store( :other_setting, :some_value )
|
391
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
392
|
+
|
393
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value }
|
394
|
+
sub_cascading_composite_hash.store( :yet_another_setting, :some_value )
|
395
|
+
sub_cascading_composite_hash.should == { :other_setting => :some_value,
|
396
|
+
:yet_another_setting => :some_value }
|
397
|
+
sub_cascading_composite_hash.clear
|
398
|
+
sub_cascading_composite_hash.should == { }
|
399
|
+
cascading_composite_hash.should == { :other_setting => :some_value }
|
400
|
+
|
401
|
+
end
|
402
|
+
|
403
|
+
##################
|
404
|
+
# pre_set_hook #
|
405
|
+
##################
|
406
|
+
|
407
|
+
it 'has a hook that is called before setting a value; return value is used in place of object' do
|
408
|
+
|
409
|
+
class ::CompositingHash::SubMockPreSet < ::CompositingHash
|
410
|
+
|
411
|
+
def pre_set_hook( key, object, is_insert = false )
|
412
|
+
return :some_other_value
|
413
|
+
end
|
414
|
+
|
415
|
+
end
|
416
|
+
|
417
|
+
cascading_composite_hash = ::CompositingHash::SubMockPreSet.new
|
418
|
+
|
419
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
420
|
+
|
421
|
+
cascading_composite_hash.should == { :some_key => :some_other_value }
|
422
|
+
|
423
|
+
end
|
424
|
+
|
425
|
+
###################
|
426
|
+
# post_set_hook #
|
427
|
+
###################
|
428
|
+
|
429
|
+
it 'has a hook that is called after setting a value' do
|
430
|
+
|
431
|
+
class ::CompositingHash::SubMockPostSet < ::CompositingHash
|
432
|
+
|
433
|
+
def post_set_hook( key, object, is_insert = false )
|
434
|
+
unless key == :some_other_key
|
435
|
+
self[ :some_other_key ] = :some_other_value
|
436
|
+
end
|
437
|
+
return object
|
438
|
+
end
|
439
|
+
|
440
|
+
end
|
441
|
+
|
442
|
+
cascading_composite_hash = ::CompositingHash::SubMockPostSet.new
|
443
|
+
|
444
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
445
|
+
|
446
|
+
cascading_composite_hash.should == { :some_key => :some_value,
|
447
|
+
:some_other_key => :some_other_value }
|
448
|
+
|
449
|
+
end
|
450
|
+
|
451
|
+
##################
|
452
|
+
# pre_get_hook #
|
453
|
+
##################
|
454
|
+
|
455
|
+
it 'has a hook that is called before getting a value; if return value is false, get does not occur' do
|
456
|
+
|
457
|
+
class ::CompositingHash::SubMockPreGet < ::CompositingHash
|
458
|
+
|
459
|
+
def pre_get_hook( key )
|
460
|
+
return false
|
461
|
+
end
|
462
|
+
|
463
|
+
end
|
464
|
+
|
465
|
+
cascading_composite_hash = ::CompositingHash::SubMockPreGet.new
|
466
|
+
|
467
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
468
|
+
cascading_composite_hash[ :some_key ].should == nil
|
469
|
+
|
470
|
+
cascading_composite_hash.should == { :some_key => :some_value }
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
###################
|
475
|
+
# post_get_hook #
|
476
|
+
###################
|
477
|
+
|
478
|
+
it 'has a hook that is called after getting a value' do
|
479
|
+
|
480
|
+
class ::CompositingHash::SubMockPostGet < ::CompositingHash
|
481
|
+
|
482
|
+
def post_get_hook( key, object )
|
483
|
+
self[ :some_other_key ] = :some_other_value
|
484
|
+
return object
|
485
|
+
end
|
486
|
+
|
487
|
+
end
|
488
|
+
|
489
|
+
cascading_composite_hash = ::CompositingHash::SubMockPostGet.new
|
490
|
+
|
491
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
492
|
+
|
493
|
+
cascading_composite_hash.should == { :some_key => :some_value }
|
494
|
+
|
495
|
+
cascading_composite_hash[ :some_key ].should == :some_value
|
496
|
+
|
497
|
+
cascading_composite_hash.should == { :some_key => :some_value,
|
498
|
+
:some_other_key => :some_other_value }
|
499
|
+
|
500
|
+
end
|
501
|
+
|
502
|
+
#####################
|
503
|
+
# pre_delete_hook #
|
504
|
+
#####################
|
505
|
+
|
506
|
+
it 'has a hook that is called before deleting an key; if return value is false, delete does not occur' do
|
507
|
+
|
508
|
+
class ::CompositingHash::SubMockPreDelete < ::CompositingHash
|
509
|
+
|
510
|
+
def pre_delete_hook( key )
|
511
|
+
return false
|
512
|
+
end
|
513
|
+
|
514
|
+
end
|
515
|
+
|
516
|
+
cascading_composite_hash = ::CompositingHash::SubMockPreDelete.new
|
517
|
+
|
518
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
519
|
+
cascading_composite_hash.delete( :some_key )
|
520
|
+
|
521
|
+
cascading_composite_hash.should == { :some_key => :some_value }
|
522
|
+
|
523
|
+
end
|
524
|
+
|
525
|
+
######################
|
526
|
+
# post_delete_hook #
|
527
|
+
######################
|
528
|
+
|
529
|
+
it 'has a hook that is called after deleting an key' do
|
530
|
+
|
531
|
+
class ::CompositingHash::SubMockPostDelete < ::CompositingHash
|
532
|
+
|
533
|
+
def post_delete_hook( key, object )
|
534
|
+
unless key == :some_other_key
|
535
|
+
delete( :some_other_key )
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
end
|
540
|
+
|
541
|
+
cascading_composite_hash = ::CompositingHash::SubMockPostDelete.new
|
542
|
+
|
543
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
544
|
+
cascading_composite_hash[ :some_other_key ] = :some_other_value
|
545
|
+
cascading_composite_hash.delete( :some_key )
|
546
|
+
|
547
|
+
cascading_composite_hash.should == { }
|
548
|
+
|
549
|
+
end
|
550
|
+
|
551
|
+
########################
|
552
|
+
# child_pre_set_hook #
|
553
|
+
########################
|
554
|
+
|
555
|
+
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
|
556
|
+
|
557
|
+
class ::CompositingHash::SubMockChildPreSet < ::CompositingHash
|
558
|
+
|
559
|
+
def child_pre_set_hook( key, object, is_insert = false )
|
560
|
+
return :some_other_value
|
561
|
+
end
|
562
|
+
|
563
|
+
end
|
564
|
+
|
565
|
+
cascading_composite_hash = ::CompositingHash::SubMockChildPreSet.new
|
566
|
+
sub_cascading_composite_hash = ::CompositingHash::SubMockChildPreSet.new( cascading_composite_hash )
|
567
|
+
|
568
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
569
|
+
|
570
|
+
cascading_composite_hash.should == { :some_key => :some_value }
|
571
|
+
sub_cascading_composite_hash.should == { :some_key => :some_other_value }
|
572
|
+
|
573
|
+
end
|
574
|
+
|
575
|
+
#########################
|
576
|
+
# child_post_set_hook #
|
577
|
+
#########################
|
578
|
+
|
579
|
+
it 'has a hook that is called after setting a value passed by a parent' do
|
580
|
+
|
581
|
+
class ::CompositingHash::SubMockChildPostSet < ::CompositingHash
|
582
|
+
|
583
|
+
def child_post_set_hook( key, object, is_insert = false )
|
584
|
+
self[ :some_other_key ] = :some_other_value
|
585
|
+
end
|
586
|
+
|
587
|
+
end
|
588
|
+
|
589
|
+
cascading_composite_hash = ::CompositingHash::SubMockChildPostSet.new
|
590
|
+
sub_cascading_composite_hash = ::CompositingHash::SubMockChildPostSet.new( cascading_composite_hash )
|
591
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
592
|
+
|
593
|
+
cascading_composite_hash.should == { :some_key => :some_value }
|
594
|
+
sub_cascading_composite_hash.should == { :some_key => :some_value,
|
595
|
+
:some_other_key => :some_other_value }
|
596
|
+
|
597
|
+
end
|
598
|
+
|
599
|
+
###########################
|
600
|
+
# child_pre_delete_hook #
|
601
|
+
###########################
|
602
|
+
|
603
|
+
it 'has a hook that is called before deleting an key that has been passed by a parent; if return value is false, delete does not occur' do
|
604
|
+
|
605
|
+
class ::CompositingHash::SubMockChildPreDelete < ::CompositingHash
|
606
|
+
|
607
|
+
def child_pre_delete_hook( key )
|
608
|
+
false
|
609
|
+
end
|
610
|
+
|
611
|
+
end
|
612
|
+
|
613
|
+
cascading_composite_hash = ::CompositingHash::SubMockChildPreDelete.new
|
614
|
+
sub_cascading_composite_hash = ::CompositingHash::SubMockChildPreDelete.new( cascading_composite_hash )
|
615
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
616
|
+
cascading_composite_hash.delete( :some_key )
|
617
|
+
|
618
|
+
cascading_composite_hash.should == { }
|
619
|
+
sub_cascading_composite_hash.should == { :some_key => :some_value }
|
620
|
+
|
621
|
+
end
|
622
|
+
|
623
|
+
############################
|
624
|
+
# child_post_delete_hook #
|
625
|
+
############################
|
626
|
+
|
627
|
+
it 'has a hook that is called after deleting an key passed by a parent' do
|
628
|
+
|
629
|
+
class ::CompositingHash::SubMockChildPostDelete < ::CompositingHash
|
630
|
+
|
631
|
+
def child_post_delete_hook( key, object )
|
632
|
+
delete( :some_other_key )
|
633
|
+
end
|
634
|
+
|
635
|
+
end
|
636
|
+
|
637
|
+
cascading_composite_hash = ::CompositingHash::SubMockChildPostDelete.new
|
638
|
+
sub_cascading_composite_hash = ::CompositingHash::SubMockChildPostDelete.new( cascading_composite_hash )
|
639
|
+
cascading_composite_hash[ :some_key ] = :some_value
|
640
|
+
sub_cascading_composite_hash[ :some_other_key ] = :some_other_value
|
641
|
+
cascading_composite_hash.delete( :some_key )
|
642
|
+
|
643
|
+
cascading_composite_hash.should == { }
|
644
|
+
sub_cascading_composite_hash.should == { }
|
645
|
+
|
646
|
+
end
|
647
|
+
|
648
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: compositing-hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.15
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Asher
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hooked-hash
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: An implementation of Hash that permits chaining, where children inherit
|
31
|
+
changes to parent and where parent settings can be overridden in children.
|
32
|
+
email: asher@ridiculouspower.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/compositing-hash/CompositingHash.rb
|
38
|
+
- lib/compositing-hash.rb
|
39
|
+
- spec/CompositingHash_spec.rb
|
40
|
+
- README.md
|
41
|
+
- README.rdoc
|
42
|
+
homepage: http://rubygems.org/gems/compositing-hash
|
43
|
+
licenses: []
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project: compositing-hash
|
62
|
+
rubygems_version: 1.8.23
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Provides CompositingHash.
|
66
|
+
test_files: []
|
67
|
+
has_rdoc:
|