parallel-ancestry 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,359 @@
1
+
2
+ require_relative '../lib/parallel-ancestry.rb'
3
+
4
+ describe ::ParallelAncestry do
5
+
6
+ before :all do
7
+ module ::ParallelAncestry::Mock
8
+ extend ::ParallelAncestry
9
+ end
10
+ class ::ParallelAncestry::ModuleSubclassMock < ::Module
11
+ include ::ParallelAncestry
12
+ end
13
+ ::ParallelAncestry::ModuleSubclassInstanceMock = ::ParallelAncestry::ModuleSubclassMock.new
14
+ end
15
+
16
+ ##############
17
+ # children #
18
+ ##############
19
+
20
+ it 'tracks an array of children' do
21
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
22
+ this_test.module_eval do
23
+ configuration_instance = ::Module.new
24
+ children_instance = children( configuration_instance )
25
+ children_instance.should == []
26
+ children_instance.should == children( configuration_instance )
27
+ end
28
+ end
29
+ end
30
+
31
+ #############
32
+ # parents #
33
+ #############
34
+
35
+ it 'tracks an array of children' do
36
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
37
+ this_test.module_eval do
38
+ configuration_instance = ::Module.new
39
+ parents_instance = parents( configuration_instance )
40
+ parents_instance.should == []
41
+ parents_instance.should == parents( configuration_instance )
42
+ end
43
+ end
44
+ end
45
+
46
+ ###############################
47
+ # register_child_for_parent #
48
+ ###############################
49
+
50
+ it 'can register children for a given instance so that migration is possible' do
51
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
52
+ this_test.module_eval do
53
+ parent = ::Module.new
54
+ child = ::Module.new
55
+ register_child_for_parent( child, parent )
56
+ children( parent ).should == [ child ]
57
+ end
58
+ end
59
+ end
60
+
61
+ ##############
62
+ # ancestor #
63
+ ##############
64
+
65
+ it 'can return the next ancestor for instance for configuration name' do
66
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
67
+ this_test.module_eval do
68
+ parent = ::Module.new do
69
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
70
+ # since we don't know whether a configuration value has been set yet
71
+ attr_accessor :some_configuration
72
+ end
73
+ child = ::Module.new
74
+ register_child_for_parent( child, parent )
75
+ ancestor( child ) { |this_parent| this_parent == parent } .should == parent
76
+ end
77
+ end
78
+ end
79
+
80
+ ####################
81
+ # ancestor_chain #
82
+ ####################
83
+
84
+ it 'can return a chain of instances corresponding to the configuration inheritance chain' do
85
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
86
+ this_test.module_eval do
87
+ # set up hierarchy
88
+ instance_A = ::Module.new do
89
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
90
+ # since we don't know whether a configuration value has been set yet
91
+ attr_accessor :some_configuration
92
+ end
93
+ instance_B = ::Module.new do
94
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
95
+ # since we don't know whether a configuration value has been set yet
96
+ attr_accessor :some_other_configuration
97
+ include instance_A
98
+ end
99
+ register_child_for_parent( instance_B, instance_A )
100
+ instance_C1 = ::Module.new do
101
+ include instance_B
102
+ attr_accessor :yet_another_configuration
103
+ end
104
+ register_child_for_parent( instance_C1, instance_B )
105
+ instance_C2 = ::Module.new do
106
+ include instance_B
107
+ end
108
+ register_child_for_parent( instance_C2, instance_B )
109
+ instance_D = ::Module.new do
110
+ include instance_C1
111
+ include instance_C2
112
+ end
113
+ register_child_for_parent( instance_D, instance_C1 )
114
+ register_child_for_parent( instance_D, instance_C2 )
115
+ # test ancestor hierarchy for each
116
+ ancestor_proc = ::Proc.new do |this_parent|
117
+ this_parent.method_defined?( :some_configuration )
118
+ end
119
+ ancestor_chain( instance_A, & ancestor_proc ).should == [ instance_A ]
120
+ ancestor_chain( instance_B, & ancestor_proc ).should == [ instance_B, instance_A ]
121
+ ancestor_chain( instance_C1, & ancestor_proc ).should == [ instance_C1, instance_B, instance_A ]
122
+ ancestor_chain( instance_C2, & ancestor_proc ).should == [ instance_C2, instance_B, instance_A ]
123
+ ancestor_chain( instance_D, & ancestor_proc ).should == [ instance_D, instance_C2, instance_B, instance_A ]
124
+
125
+ ancestor_proc = ::Proc.new do |this_parent|
126
+ this_parent.method_defined?( :some_other_configuration )
127
+ end
128
+ ancestor_chain( instance_B, & ancestor_proc ).should == [ instance_B ]
129
+ ancestor_chain( instance_C1, & ancestor_proc ).should == [ instance_C1, instance_B ]
130
+ ancestor_chain( instance_C2, & ancestor_proc ).should == [ instance_C2, instance_B ]
131
+
132
+ ancestor_proc = ::Proc.new do |this_parent|
133
+ this_parent.method_defined?( :yet_another_configuration )
134
+ end
135
+ ancestor_chain( instance_C1, & ancestor_proc ).should == [ instance_C1 ]
136
+ ancestor_chain( instance_D, & ancestor_proc ).should == [ instance_D, instance_C1 ]
137
+ end
138
+ end
139
+ end
140
+
141
+ ####################
142
+ # lowest_parents #
143
+ ####################
144
+
145
+ it 'can return the first ancestor on each parent tree matching block condition' do
146
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
147
+ this_test.module_eval do
148
+ # set up hierarchy
149
+ instance_A = ::Module.new do
150
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
151
+ # since we don't know whether a configuration value has been set yet
152
+ attr_accessor :some_configuration
153
+ end
154
+ instance_B1 = ::Module.new do
155
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
156
+ # since we don't know whether a configuration value has been set yet
157
+ attr_accessor :some_other_configuration
158
+ include instance_A
159
+ end
160
+ register_child_for_parent( instance_B1, instance_A )
161
+ instance_B2 = ::Module.new do
162
+ include instance_A
163
+ end
164
+ register_child_for_parent( instance_B2, instance_A )
165
+ instance_C1 = ::Module.new do
166
+ include instance_B1
167
+ attr_accessor :yet_another_configuration
168
+ end
169
+ register_child_for_parent( instance_C1, instance_B1 )
170
+ instance_C2 = ::Module.new do
171
+ include instance_B1
172
+ end
173
+ register_child_for_parent( instance_C2, instance_B1 )
174
+ instance_D = ::Module.new do
175
+ include instance_B2
176
+ include instance_C1
177
+ include instance_C2
178
+ end
179
+ instance_E = ::Class.new do
180
+ include instance_B2
181
+ include instance_C1
182
+ include instance_C2
183
+ include instance_D
184
+ end
185
+ register_child_for_parent( instance_D, instance_B2 )
186
+ register_child_for_parent( instance_D, instance_C1 )
187
+ register_child_for_parent( instance_D, instance_C2 )
188
+ register_child_for_parent( instance_E, instance_D )
189
+ register_child_for_parent( instance_E, instance_B1 )
190
+ match_proc = ::Proc.new do |this_parent|
191
+ this_parent.method_defined?( :some_configuration )
192
+ end
193
+ lowest_parents( instance_D, & match_proc ).should == [ instance_C2, instance_C1, instance_B2 ]
194
+ lowest_parents( instance_C2, & match_proc ).should == [ instance_B1 ]
195
+ lowest_parents( instance_C1, & match_proc ).should == [ instance_B1 ]
196
+ lowest_parents( instance_B1, & match_proc ).should == [ instance_A ]
197
+ lowest_parents( instance_B2, & match_proc ).should == [ instance_A ]
198
+ lowest_parents( instance_E, & match_proc ).should == [ instance_B1, instance_D ]
199
+ end
200
+ end
201
+ end
202
+
203
+ ######################
204
+ # highest_children #
205
+ ######################
206
+
207
+ it 'can return the first ancestor on each child tree matching block condition' do
208
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
209
+ this_test.module_eval do
210
+ # set up hierarchy
211
+ instance_A = ::Module.new do
212
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
213
+ # since we don't know whether a configuration value has been set yet
214
+ attr_accessor :some_configuration
215
+ end
216
+ instance_B1 = ::Module.new do
217
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
218
+ # since we don't know whether a configuration value has been set yet
219
+ attr_accessor :some_other_configuration
220
+ extend instance_A
221
+ end
222
+ register_child_for_parent( instance_B1, instance_A )
223
+ instance_B2 = ::Module.new do
224
+ extend instance_A
225
+ end
226
+ register_child_for_parent( instance_B2, instance_A )
227
+ instance_C1 = ::Module.new do
228
+ extend instance_B1
229
+ extend instance_A
230
+ attr_accessor :yet_another_configuration
231
+ end
232
+ register_child_for_parent( instance_C1, instance_B1 )
233
+ instance_C2 = ::Module.new do
234
+ extend instance_B2
235
+ extend instance_A
236
+ end
237
+ register_child_for_parent( instance_C2, instance_B1 )
238
+ instance_D = ::Module.new do
239
+ extend instance_B2
240
+ extend instance_C1
241
+ extend instance_A
242
+ end
243
+ instance_E = ::Class.new do
244
+ extend instance_C2
245
+ end
246
+ register_child_for_parent( instance_D, instance_B2 )
247
+ register_child_for_parent( instance_D, instance_C1 )
248
+ register_child_for_parent( instance_D, instance_C2 )
249
+ register_child_for_parent( instance_E, instance_D )
250
+ register_child_for_parent( instance_E, instance_B1 )
251
+ match_proc = ::Proc.new do |this_parent|
252
+ this_parent.respond_to?( :some_configuration )
253
+ end
254
+ highest_children( instance_E, & match_proc ).empty?.should == true
255
+ highest_children( instance_D, & match_proc ).empty?.should == true
256
+ highest_children( instance_C2, & match_proc ).should == [ instance_D ]
257
+ highest_children( instance_C1, & match_proc ).should == [ instance_D ]
258
+ highest_children( instance_B1, & match_proc ).should == [ instance_C1, instance_C2 ]
259
+ highest_children( instance_B2, & match_proc ).should == [ instance_D ]
260
+ highest_children( instance_A, & match_proc ).should == [ instance_B1, instance_B2 ]
261
+ end
262
+ end
263
+ end
264
+
265
+ #####################################
266
+ # match_ancestor_searching_upward #
267
+ #####################################
268
+
269
+ it 'can get the first defined configuration searching up the module configuration inheritance chain' do
270
+ [ ::ParallelAncestry::Mock, ::ParallelAncestry::ModuleSubclassInstanceMock ].each do |this_test|
271
+ this_test.module_eval do
272
+ # set up hierarchy
273
+ instance_A = ::Module.new do
274
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
275
+ # since we don't know whether a configuration value has been set yet
276
+ class << self
277
+ attr_accessor :some_configuration
278
+ end
279
+ end
280
+ instance_B = ::Module.new do
281
+ # we have to mock the method bc that's how the module determines if it has a configuration defined
282
+ # since we don't know whether a configuration value has been set yet
283
+ include instance_A
284
+ class << self
285
+ attr_accessor :some_configuration
286
+ attr_accessor :some_other_configuration
287
+ end
288
+ end
289
+ register_child_for_parent( instance_B, instance_A )
290
+ instance_C1 = ::Module.new do
291
+ include instance_B
292
+ class << self
293
+ attr_accessor :some_configuration
294
+ attr_accessor :some_other_configuration
295
+ attr_accessor :yet_another_configuration
296
+ end
297
+ end
298
+ register_child_for_parent( instance_C1, instance_B )
299
+ instance_C2 = ::Module.new do
300
+ include instance_B
301
+ class << self
302
+ attr_accessor :some_configuration
303
+ attr_accessor :some_other_configuration
304
+ attr_accessor :yet_another_configuration
305
+ end
306
+ end
307
+ register_child_for_parent( instance_C2, instance_B )
308
+ instance_D = ::Module.new do
309
+ include instance_C1
310
+ include instance_C2
311
+ class << self
312
+ attr_accessor :some_configuration
313
+ attr_accessor :some_other_configuration
314
+ attr_accessor :yet_another_configuration
315
+ end
316
+ end
317
+ register_child_for_parent( instance_D, instance_C1 )
318
+ register_child_for_parent( instance_D, instance_C2 )
319
+
320
+ configuration_method = :some_configuration
321
+
322
+ # test ancestor hierarchy for each
323
+ match_proc = ::Proc.new do |this_parent|
324
+ this_parent.__send__( configuration_method )
325
+ end
326
+
327
+ match_ancestor_proc = ::Proc.new do |this_parent|
328
+ this_parent.respond_to?( configuration_method )
329
+ end
330
+
331
+ instance_A.some_configuration = :some_value
332
+ instance_B.some_other_configuration = :some_other_value
333
+
334
+ match_ancestor_searching_upward( instance_B, match_ancestor_proc, & match_proc ).should == instance_A
335
+ match_ancestor_searching_upward( instance_C1, match_ancestor_proc, & match_proc ).should == instance_A
336
+
337
+ configuration_method = :some_other_configuration
338
+ match_ancestor_searching_upward( instance_B, match_ancestor_proc, & match_proc ).should == instance_B
339
+ match_ancestor_searching_upward( instance_C1, match_ancestor_proc, & match_proc ).should == instance_B
340
+
341
+ instance_C2.yet_another_configuration = :another_value
342
+
343
+ configuration_method = :yet_another_configuration
344
+ match_ancestor_searching_upward( instance_C1, match_ancestor_proc, & match_proc ).should == nil
345
+ match_ancestor_searching_upward( instance_D, match_ancestor_proc, & match_proc ).should == instance_C2
346
+
347
+ configuration_method = :some_configuration
348
+ match_ancestor_searching_upward( instance_C2, match_ancestor_proc, & match_proc ).should == instance_A
349
+ match_ancestor_searching_upward( instance_D, match_ancestor_proc, & match_proc ).should == instance_A
350
+
351
+ configuration_method = :some_other_configuration
352
+ match_ancestor_searching_upward( instance_C2, match_ancestor_proc, & match_proc ).should == instance_B
353
+ match_ancestor_searching_upward( instance_D, match_ancestor_proc, & match_proc ).should == instance_B
354
+
355
+ end
356
+ end
357
+ end
358
+
359
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parallel-ancestry
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Asher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: module-cluster
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: Create and track parallel inheritance hierarchies. Hook parallel hierarchies
31
+ (by including a module) to automatically update/register ancestry at include and
32
+ extend, or update/register only manually. Manual registration permits definitions
33
+ of ancestry across, for example, instances of the same type or instances of entirely
34
+ different types. Implementation is provided by simple child/parent trees with an
35
+ block to choose which parent. This permits a simple multiple inheritance model very
36
+ similar to how Ruby handles modules. Conflicts for multiple inheritance are resolved
37
+ by the parent most recently named for the block match. Used heavily by CascadingConfiguration
38
+ gem (cascading-configuration) as well as by forthcoming Persistence and Magnets
39
+ gems (persistence and magnets).
40
+ email: asher@ridiculouspower.com
41
+ executables: []
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - lib/parallel-ancestry/ParallelAncestry/Inheritance/ModuleSubclassInheritance.rb
46
+ - lib/parallel-ancestry/ParallelAncestry/Inheritance.rb
47
+ - lib/parallel-ancestry/ParallelAncestry/ModuleSubclassInheritance.rb
48
+ - lib/parallel-ancestry/ParallelAncestry.rb
49
+ - lib/parallel-ancestry.rb
50
+ - spec/ParallelAncestry/Inheritance_spec.rb
51
+ - spec/ParallelAncestry_spec.rb
52
+ - README.md
53
+ - README.rdoc
54
+ - CHANGELOG.rdoc
55
+ homepage: http://rubygems.org/gems/parallel-ancestry
56
+ licenses: []
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project: parallel-ancestry
75
+ rubygems_version: 1.8.23
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Provides parallel implementations of inheritance hierarchies. This is useful
79
+ both for tracking the existing inheritance tree and for creating trees that function
80
+ independently of inheritance models determined internal to Ruby.
81
+ test_files: []