activefacts-api 0.8.12 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. data/.rspec +1 -0
  2. data/.travis.yml +9 -0
  3. data/Gemfile +14 -0
  4. data/Rakefile +21 -9
  5. data/VERSION +1 -1
  6. data/activefacts-api.gemspec +31 -12
  7. data/lib/activefacts/api.rb +1 -0
  8. data/lib/activefacts/api/constellation.rb +3 -1
  9. data/lib/activefacts/api/entity.rb +74 -29
  10. data/lib/activefacts/api/exceptions.rb +17 -0
  11. data/lib/activefacts/api/instance.rb +96 -1
  12. data/lib/activefacts/api/instance_index.rb +35 -37
  13. data/lib/activefacts/api/numeric.rb +62 -56
  14. data/lib/activefacts/api/object_type.rb +49 -23
  15. data/lib/activefacts/api/role.rb +8 -2
  16. data/lib/activefacts/api/role_values.rb +8 -26
  17. data/lib/activefacts/api/standard_types.rb +2 -17
  18. data/lib/activefacts/api/vocabulary.rb +1 -1
  19. data/lib/activefacts/tracer.rb +13 -1
  20. data/spec/{constellation_spec.rb → constellation/constellation_spec.rb} +127 -56
  21. data/spec/constellation/instance_index_spec.rb +90 -0
  22. data/spec/{instance_spec.rb → constellation/instance_spec.rb} +48 -42
  23. data/spec/{role_values_spec.rb → fact_type/role_values_spec.rb} +28 -19
  24. data/spec/{roles_spec.rb → fact_type/roles_spec.rb} +55 -21
  25. data/spec/fixtures/tax.rb +45 -0
  26. data/spec/{identification_spec.rb → identification_scheme/identification_spec.rb} +88 -74
  27. data/spec/identification_scheme/identity_change_spec.rb +118 -0
  28. data/spec/identification_scheme/identity_supertype_change_spec.rb +63 -0
  29. data/spec/{entity_type_spec.rb → object_type/entity_type/entity_type_spec.rb} +2 -4
  30. data/spec/object_type/entity_type/multipart_identification_spec.rb +77 -0
  31. data/spec/{autocounter_spec.rb → object_type/value_type/autocounter_spec.rb} +2 -4
  32. data/spec/object_type/value_type/numeric_spec.rb +63 -0
  33. data/spec/{value_type_spec.rb → object_type/value_type/value_type_spec.rb} +10 -14
  34. data/spec/simplecov_helper.rb +8 -0
  35. data/spec/spec_helper.rb +1 -1
  36. metadata +100 -19
@@ -8,6 +8,7 @@
8
8
  # and allow any Class to become an Entity.
9
9
  #
10
10
  require 'date'
11
+ require 'activefacts/api/numeric'
11
12
 
12
13
  module ActiveFacts
13
14
  module API
@@ -20,12 +21,9 @@ module ActiveFacts
20
21
  end
21
22
  end
22
23
  end
23
-
24
- require 'activefacts/api/numeric'
25
-
26
24
  # Add the methods that convert our classes into ObjectType types:
27
25
 
28
- ValueClasses = [String, Date, DateTime, Time, Int, Real, AutoCounter]
26
+ ValueClasses = [String, Date, DateTime, Time, Int, Real, AutoCounter, Decimal]
29
27
  ValueClasses.each{|c|
30
28
  c.send :extend, ActiveFacts::API::ValueClass
31
29
  }
@@ -62,19 +60,6 @@ class Class
62
60
  end
63
61
  end
64
62
 
65
- require 'bigdecimal'
66
- class Decimal < BigDecimal #:nodoc:
67
- extend ActiveFacts::API::ValueClass
68
- # The problem here is you can't pass a BigDecimal to BigDecimal.new. Fix it.
69
- def self.new(v)
70
- if v.is_a?(BigDecimal) || v.is_a?(Bignum)
71
- super(v.to_s)
72
- else
73
- super
74
- end
75
- end
76
- end
77
-
78
63
  # These types are generated on conversion from NORMA's types:
79
64
  class Char < String #:nodoc: # FixedLengthText
80
65
  end
@@ -12,7 +12,7 @@ module ActiveFacts
12
12
  # Vocabulary is a mixin that adds methods to any Module which has any ObjectType classes (ValueType or EntityType).
13
13
  # A Vocabulary knows all the ObjectType classes including forward-referenced ones,
14
14
  # and can resolve the forward references when the class is finally defined.
15
- # Construction of a Constellation requires a Vocabuary as argument.
15
+ # Construction of a Constellation requires a Vocabulary as argument.
16
16
  module Vocabulary
17
17
  # With a parameter, look up an object type by name.
18
18
  # Without, return the hash (keyed by the class' basename) of all object_types in this vocabulary
@@ -25,7 +25,17 @@ module ActiveFacts
25
25
  @stderr.puts "---\nDebugging keys available: #{@available.keys.map{|s| s.to_s}.sort*", "}"
26
26
  }
27
27
  end
28
- require 'ruby-debug' if @keys[:debug]
28
+ if @keys[:debug]
29
+ ['pry', 'debugger', 'ruby-debug'].each do |debugger|
30
+ begin
31
+ require debugger
32
+ puts "Loaded "+debugger
33
+ break
34
+ rescue LoadError
35
+ end
36
+ end
37
+ ::Debugger.start rescue nil
38
+ end
29
39
  end
30
40
  end
31
41
 
@@ -107,3 +117,5 @@ class Object
107
117
  (ActiveFacts.tracer ||= ActiveFacts::Tracer.new).trace(*args, &block)
108
118
  end
109
119
  end
120
+
121
+ trace ''
@@ -3,9 +3,6 @@
3
3
  # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
4
  #
5
5
 
6
- require 'rspec'
7
- require 'activefacts/api'
8
-
9
6
  describe "A Constellation instance" do
10
7
  before :each do
11
8
  Object.send :remove_const, :Mod if Object.const_defined?("Mod")
@@ -16,30 +13,30 @@ describe "A Constellation instance" do
16
13
 
17
14
  # Create a value type and a subtype of that value type for each base type:
18
15
  @base_types.each do |base_type|
19
- eval <<-END
20
- class #{base_type.basename}Value < #{base_type.name}
16
+ Mod.module_eval <<-END
17
+ class #{base_type.basename}Val < #{base_type.name}
21
18
  value_type
22
19
  end
23
20
 
24
- class #{base_type.basename}SubValue < #{base_type.name}Value
21
+ class #{base_type.basename}SubVal < #{base_type.name}Val
25
22
  # Note no new "value_type" is required here, it comes through inheritance
26
23
  end
27
24
  END
28
25
  end
29
26
 
30
- class Name < StringValue
27
+ class Name < StringVal
31
28
  value_type
32
29
  #has_one :attr, Name
33
30
  end
34
31
 
35
32
  class LegalEntity
36
33
  identified_by :name
37
- has_one :name, :mandatory => true
34
+ one_to_one :name, :mandatory => true
38
35
  end
39
36
 
40
37
  class SurrogateId
41
- identified_by :auto_counter_value
42
- has_one :auto_counter_value
38
+ identified_by :auto_counter_val
39
+ one_to_one :auto_counter_val
43
40
  end
44
41
 
45
42
  class Company < LegalEntity
@@ -60,18 +57,18 @@ describe "A Constellation instance" do
60
57
 
61
58
  describe "Vocabulary" do
62
59
  it "should create the constellation" do
63
- Mod.constellation.should be_is_a ActiveFacts::API::Constellation
60
+ Mod.constellation.should be_an_instance_of ActiveFacts::API::Constellation
64
61
  end
65
62
 
66
63
  it "should create the constellation by direct populate" do
67
64
  Mod.populate do
68
65
  Name "foo"
69
- end.should be_is_a ActiveFacts::API::Constellation
66
+ end.should be_an_instance_of ActiveFacts::API::Constellation
70
67
  end
71
68
 
72
69
  it "should verbalise" do
73
70
  s = Mod.verbalise
74
- s.should be_is_a String
71
+ s.should be_an_instance_of String
75
72
  end
76
73
  end
77
74
 
@@ -107,8 +104,8 @@ describe "A Constellation instance" do
107
104
  lambda {
108
105
  name = @constellation.Name("foo")
109
106
  foo = @constellation.LegalEntity("foo")
110
- acme = @constellation.Company("Acme, Inc", :auto_counter_value => :new)
111
- fred_fly = @constellation.Person("fred", "fly", :auto_counter_value => :new)
107
+ acme = @constellation.Company("Acme, Inc", :auto_counter_val => :new)
108
+ fred_fly = @constellation.Person("fred", "fly", :auto_counter_val => :new)
112
109
  }.should_not raise_error
113
110
  name.class.should == Mod::Name
114
111
  name.constellation.should == @constellation
@@ -132,13 +129,13 @@ describe "A Constellation instance" do
132
129
  it "should re-use instances constructed the same way" do
133
130
  name1 = @constellation.Name("foo")
134
131
  foo1 = @constellation.LegalEntity("foo")
135
- acme1 = @constellation.Company("Acme, Inc", :auto_counter_value => :new)
136
- fred_fly1 = @constellation.Person("fred", "fly", :auto_counter_value => :new)
132
+ acme1 = @constellation.Company("Acme, Inc", :auto_counter_val => :new)
133
+ fred_fly1 = @constellation.Person("fred", "fly", :auto_counter_val => :new)
137
134
 
138
135
  name2 = @constellation.Name("foo")
139
136
  foo2 = @constellation.LegalEntity("foo")
140
- acme2 = @constellation.Company("Acme, Inc", :auto_counter_value => :new)
141
- fred_fly2 = @constellation.Person("fred", "fly", :auto_counter_value => :new)
137
+ acme2 = @constellation.Company("Acme, Inc") # , :auto_counter_val => :new)
138
+ fred_fly2 = @constellation.Person("fred", "fly") # , :auto_counter_val => :new)
142
139
 
143
140
  name1.object_id.should == name2.object_id
144
141
  foo1.object_id.should == foo2.object_id
@@ -146,13 +143,23 @@ describe "A Constellation instance" do
146
143
  fred_fly1.object_id.should == fred_fly2.object_id
147
144
  end
148
145
 
146
+ it "should reject re-assertion with additional assignments" do
147
+ name1 = @constellation.Name("foo")
148
+ foo1 = @constellation.LegalEntity("foo")
149
+ acme1 = @constellation.Company("Acme, Inc", :auto_counter_val => :new)
150
+
151
+ name2 = @constellation.Name("foo")
152
+ foo2 = @constellation.LegalEntity("foo")
153
+ lambda { @constellation.Company("Acme, Inc", :auto_counter_val => :new) }.should raise_error
154
+ end
155
+
149
156
  it "should support methods to assert instances via the class for that type" do
150
157
  name = foo = acme = fred_fly = nil
151
158
  lambda {
152
159
  name = @constellation.Name.assert("foo")
153
160
  foo = @constellation.LegalEntity.assert("foo")
154
- acme = @constellation.Company.assert("Acme, Inc", :auto_counter_value => :new)
155
- fred_fly = @constellation.Person.assert("fred", "fly", :auto_counter_value => :new)
161
+ acme = @constellation.Company.assert("Acme, Inc", :auto_counter_val => :new)
162
+ fred_fly = @constellation.Person.assert("fred", "fly", :auto_counter_val => :new)
156
163
  }.should_not raise_error
157
164
  name.class.should == Mod::Name
158
165
  name.constellation.should == @constellation
@@ -177,8 +184,8 @@ describe "A Constellation instance" do
177
184
  @constellation.populate do
178
185
  Name("bar")
179
186
  LegalEntity("foo")
180
- Person("Fred", "Nerk", :auto_counter_value => :new)
181
- Company("Acme, Inc", :auto_counter_value => :new)
187
+ Person("Fred", "Nerk", :auto_counter_val => :new)
188
+ Company("Acme, Inc", :auto_counter_val => :new)
182
189
  end
183
190
  @constellation.Name.size.should == 5
184
191
  @constellation.SurrogateId.size.should == 2
@@ -188,29 +195,29 @@ describe "A Constellation instance" do
188
195
  @constellation.populate do
189
196
  Name("bar")
190
197
  LegalEntity("foo")
191
- c = Company("Acme, Inc", :auto_counter_value => :new)
192
- p = Person("Fred", "Nerk", :auto_counter_value => :new, :employer => c)
198
+ c = Company("Acme, Inc", :auto_counter_val => :new)
199
+ p = Person("Fred", "Nerk", :auto_counter_val => :new, :employer => c)
193
200
  p.birth_name = "Nerk"
194
201
  end
195
202
  s = @constellation.verbalise
196
203
  names = s.split(/\n/).grep(/\tEvery /).map{|l| l.sub(/.*Every (.*):$/, '\1')}
197
- expected = ["AutoCounterValue", "Company", "LegalEntity", "Name", "Person", "StringValue", "SurrogateId"]
204
+ expected = ["AutoCounterVal", "Company", "LegalEntity", "Name", "Person", "StringVal", "SurrogateId"]
198
205
  names.sort.should == expected
199
206
  end
200
207
 
201
208
  it "should support string capitalisation functions" do
202
- names = ["Company", "LegalEntity", "Name", "Person", "StringValue", "SurrogateId"]
209
+ names = ["Company", "LegalEntity", "Name", "Person", "StringVal", "SurrogateId"]
203
210
  camelwords = names.map{|n| n.camelwords }
204
- camelwords.should == [["Company"], ["Legal", "Entity"], ["Name"], ["Person"], ["String", "Value"], ["Surrogate", "Id"]]
211
+ camelwords.should == [["Company"], ["Legal", "Entity"], ["Name"], ["Person"], ["String", "Val"], ["Surrogate", "Id"]]
205
212
 
206
213
  snakes = names.map{|n| n.snakecase }
207
- snakes.should == ["company", "legal_entity", "name", "person", "string_value", "surrogate_id"]
214
+ snakes.should == ["company", "legal_entity", "name", "person", "string_val", "surrogate_id"]
208
215
 
209
216
  camelupper = snakes.map{|n| n.camelcase }
210
- camelupper.should == ["Company", "LegalEntity", "Name", "Person", "StringValue", "SurrogateId"]
217
+ camelupper.should == ["Company", "LegalEntity", "Name", "Person", "StringVal", "SurrogateId"]
211
218
 
212
219
  camellower = snakes.map{|n| n.camelcase(:lower) }
213
- camellower.should == ["company", "legalEntity", "name", "person", "stringValue", "surrogateId"]
220
+ camellower.should == ["company", "legalEntity", "name", "person", "stringVal", "surrogateId"]
214
221
  end
215
222
 
216
223
  it "should allow inspection of instance indices" do
@@ -222,9 +229,9 @@ describe "A Constellation instance" do
222
229
  baz = @constellation.Name("baz")
223
230
  @constellation.Name.keys.sort.should == ["baz"]
224
231
 
225
- @constellation.StringValue.keys.sort.should == ["baz"]
226
- @constellation.StringValue.include?(baz).should == baz
227
- @constellation.StringValue.include?("baz").should == baz
232
+ @constellation.StringVal.keys.sort.should == ["baz"]
233
+ @constellation.StringVal.include?(baz).should == baz
234
+ @constellation.StringVal.include?("baz").should == baz
228
235
  end
229
236
 
230
237
  describe "instance indices" do
@@ -245,24 +252,24 @@ describe "A Constellation instance" do
245
252
  name = "Acme, Inc"
246
253
  fred = "Fred"
247
254
  fly = "Fly"
248
- acme = @constellation.Company name, :auto_counter_value => :new
249
- fred_fly = @constellation.Person fred, fly, :auto_counter_value => :new
255
+ acme = @constellation.Company name, :auto_counter_val => :new
256
+ fred_fly = @constellation.Person fred, fly, :auto_counter_val => :new
250
257
 
251
258
  # REVISIT: This should be illegal:
252
- #fred_fly.auto_counter_value = :new
259
+ #fred_fly.auto_counter_val = :new
253
260
 
254
261
  @constellation.Person.keys.sort.should == [[fred, fly]]
255
262
  @constellation.Company.keys.sort.should == [[name]]
256
263
 
257
- @constellation.LegalEntity.keys.sort.should be_include([name])
258
- @constellation.LegalEntity.keys.sort.should be_include([fred])
264
+ @constellation.LegalEntity.keys.sort.should include [name]
265
+ @constellation.LegalEntity.keys.sort.should include [fred]
259
266
 
260
- @constellation.SurrogateId.values.should be_include(acme)
261
- @constellation.SurrogateId.values.should be_include(fred_fly)
267
+ @constellation.SurrogateId.values.should include acme
268
+ @constellation.SurrogateId.values.should include fred_fly
262
269
  end
263
270
 
264
271
  it "should handle one-to-ones correctly" do
265
- person = @constellation.Person "Fred", "Smith", :auto_counter_value => :new, :birth_name => "Nerk"
272
+ person = @constellation.Person "Fred", "Smith", :auto_counter_val => :new, :birth_name => "Nerk"
266
273
 
267
274
  nerk = @constellation.Name["Nerk"]
268
275
  nerk.should_not be_nil
@@ -273,7 +280,7 @@ describe "A Constellation instance" do
273
280
  end
274
281
 
275
282
  it "should allow retraction of instances" do
276
- person = @constellation.Person "Fred", "Smith", :auto_counter_value => :new, :birth_name => "Nerk"
283
+ person = @constellation.Person "Fred", "Smith", :auto_counter_val => :new, :birth_name => "Nerk"
277
284
 
278
285
  @constellation.retract(@constellation.Name("Smith"))
279
286
  @constellation.Name["Smith"].should be_nil
@@ -282,9 +289,14 @@ describe "A Constellation instance" do
282
289
  person.family_name.should be_nil
283
290
  @constellation.retract(@constellation.Name("Fred"))
284
291
  @constellation.Name["Fred"].should be_nil
285
- pending "Retraction of identifiers doesn't de/re-index" do
286
- @constellation.Person.size.should == 0
287
- end
292
+ end
293
+
294
+ it "should retract linked instances (cascading)" do
295
+ @constellation.Person "Fred", "Smith", :auto_counter_val => :new, :birth_name => "Nerk"
296
+ @constellation.Person "George", "Smith", :auto_counter_val => :new, :birth_name => "Patrick"
297
+ @constellation.Person.size.should == 2
298
+ @constellation.retract(@constellation.Name("Smith"))
299
+ @constellation.Person.size.should == 0
288
300
  end
289
301
 
290
302
  it "should fail to recognise references to unresolved forward referenced classes" do
@@ -338,7 +350,7 @@ describe "A Constellation instance" do
338
350
 
339
351
  lambda {
340
352
  module Mod
341
- class IntValue
353
+ class IntVal
342
354
  has_one :thingummy, :class => Outside::Other
343
355
  end
344
356
  end
@@ -377,10 +389,70 @@ describe "A Constellation instance" do
377
389
  class ListedCompany < Company
378
390
  end
379
391
  end
380
- c = @constellation.ListedCompany("foo", :auto_counter_value => 23)
392
+ c = @constellation.ListedCompany("foo", :auto_counter_val => 23)
381
393
  }.should_not raise_error(NameError)
382
394
  end
383
395
 
396
+ it "should be able to attach a new supertype on an entity type to make it a (sub-)subtype" do
397
+ module Mod
398
+ class Dad
399
+ identified_by :name
400
+ end
401
+ class Son < Dad
402
+ identified_by :name
403
+ end
404
+ # the grand son will be linked on the fly
405
+ class GrandSon
406
+ identified_by :name
407
+ end
408
+ end
409
+ Mod::GrandSon.supertypes(Mod::Son)
410
+ Mod::GrandSon.supertypes.should include Mod::Son
411
+ Mod::Son.supertypes.should include Mod::Dad
412
+ end
413
+
414
+ it "should keep information on where the identification came from" do
415
+ module Mod
416
+ class Dad
417
+ identified_by :name
418
+ end
419
+ class Son < Dad
420
+ identified_by :name
421
+ end
422
+ # Note the inheritance.
423
+ class GrandSon < Son
424
+ identified_by :name
425
+ end
426
+ end
427
+
428
+ Mod::Son.identification_inherited_from.should == Mod::Dad
429
+ Mod::Son.identification_inherited_from.should == Mod::Dad
430
+ Mod::GrandSon.identification_inherited_from.should == Mod::Son
431
+ Mod::GrandSon.overrides_identification_of.should == Mod::Dad
432
+ end
433
+
434
+ it "should disallow using a value type as a supertypes for an entity type" do
435
+ lambda {
436
+ module Mod
437
+ class CompanyName
438
+ identified_by :name
439
+ supertypes :name
440
+ end
441
+ end
442
+ }.should raise_error
443
+ end
444
+
445
+ it "should complain when role name and counter part mismatch" do
446
+ lambda {
447
+ module Mod
448
+ class CompanyName
449
+ identified_by :name
450
+ has_one :company, :class => :person
451
+ end
452
+ end
453
+ }.should raise_error(Exception, /indicates a different counterpart object_type/)
454
+ end
455
+
384
456
  it "should error on invalid :class values" do
385
457
  lambda {
386
458
  module Mod
@@ -402,29 +474,28 @@ describe "A Constellation instance" do
402
474
  end
403
475
 
404
476
  it "should allow assert using an object of the same type" do
405
- c = @constellation.Company("foo", :auto_counter_value => 23)
477
+ c = @constellation.Company("foo", :auto_counter_val => 23)
406
478
  c2 = ActiveFacts::API::Constellation.new(Mod)
407
479
  lambda {
408
- c2.Company(c, :auto_counter_value => :new)
480
+ c2.Company(c, :auto_counter_val => :new)
409
481
  }.should_not raise_error
410
482
  c2.Company.keys.should == [["foo"]]
411
483
  end
412
484
 
413
485
  it "should allow cross-constellation construction" do
414
- c = @constellation.Company("foo", :auto_counter_value => 23)
486
+ c = @constellation.Company("foo", :auto_counter_val => 23)
415
487
  lambda {
416
488
  c2 = ActiveFacts::API::Constellation.new(Mod)
417
- c2.Company(c.name, :auto_counter_value => :new)
489
+ c2.Company(c.name, :auto_counter_val => :new)
418
490
  }.should_not raise_error
419
491
  end
420
492
 
421
493
  it "should allow cross-constellation assignment" do
422
- c = @constellation.Company("foo", :auto_counter_value => 23)
494
+ c = @constellation.Company("foo", :auto_counter_val => 23)
423
495
  lambda {
424
496
  c2 = ActiveFacts::API::Constellation.new(Mod)
425
- p = c2.Person('Fred', 'Smith', :auto_counter_value => :new)
426
- p.employer = [c, {:auto_counter_value => :new}]
497
+ p = c2.Person('Fred', 'Smith', :auto_counter_val => :new)
498
+ p.employer = [c, {:auto_counter_val => :new}]
427
499
  }.should_not raise_error
428
500
  end
429
-
430
501
  end
@@ -0,0 +1,90 @@
1
+ #
2
+ # ActiveFacts tests: Value instances in the Runtime API
3
+ # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
+ #
5
+
6
+ describe ActiveFacts::API::InstanceIndex do
7
+ before :all do
8
+ module Mod
9
+ class ValueA < Int
10
+ value_type
11
+ end
12
+
13
+ class ValueB < String
14
+ value_type
15
+ end
16
+
17
+ class EntityA
18
+ identified_by :value_a
19
+ one_to_one :value_a
20
+ has_one :value_b
21
+ end
22
+
23
+ class EntityB < EntityA
24
+ identified_by :value_b
25
+ one_to_one :value_b
26
+ end
27
+
28
+ class EntityD < EntityA
29
+ end
30
+
31
+ class EntityC < EntityB
32
+ supertypes EntityD
33
+ end
34
+ end
35
+
36
+ @constellation = ActiveFacts::API::Constellation.new(Mod)
37
+ @a = @constellation.EntityA(:value_a => 1, :value_b => 'a')
38
+ @b = @constellation.EntityB(:value_a => 12, :value_b => 'ab')
39
+ @c = @constellation.EntityC(:value_a => 123, :value_b => 'abc')
40
+ end
41
+
42
+ it "should index an instance under its own class" do
43
+ @constellation.instances[Mod::EntityC].size.should == 1
44
+ end
45
+
46
+ it "should index instances of subtypes" do
47
+ @constellation.instances[Mod::EntityA].size.should == 3
48
+ @constellation.instances[Mod::EntityB].size.should == 2
49
+ @constellation.instances[Mod::EntityD].size.should == 1
50
+ end
51
+
52
+ describe "#flatten_key" do
53
+ it "should use identifying role values when using an entity type" do
54
+ @constellation.EntityA[@a].should == @a
55
+ end
56
+
57
+ it "should recursively try to use identifying role values within an array" do
58
+ value_b = @constellation.ValueB('abc')
59
+ @constellation.EntityC[[value_b]].should == @c
60
+ end
61
+
62
+ it "should use the value as-is if it doesn't have identifying role values" do
63
+ @constellation.EntityC[%w{abc}].should == @c
64
+ end
65
+ end
66
+
67
+ describe "should iterate over instances" do
68
+ [:each, :map, :detect].each do |api|
69
+ it "Should pass the key and object to #{api}" do
70
+ a_index = @constellation.EntityA
71
+ a_index.size.should == 3
72
+ a_index.send(api) do |k, v, *a|
73
+ [[1], [12], [123]].should include(k)
74
+ [@a, @b, @c].should include(v)
75
+ a.size.should == 0
76
+ false
77
+ end
78
+
79
+ b_index = @constellation.EntityB
80
+ b_index.size.should == 2
81
+ b_index.send(api) do |k, v, *a|
82
+ [['ab'], ['abc']].should include(k)
83
+ [@b, @c].should include v
84
+ a.size.should == 0
85
+ false
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end