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
@@ -1,5 +1,7 @@
1
- require 'rspec'
2
- require 'activefacts/api'
1
+ #
2
+ # ActiveFacts tests: Value instances in the Runtime API
3
+ # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
+ #
3
5
 
4
6
  describe "An Entity Type" do
5
7
  before :all do
@@ -28,16 +30,14 @@ describe "An Entity Type" do
28
30
  end
29
31
 
30
32
  it "should fail if the role isn't one-to-one" do
31
- pending "Lacks a check for one-to-one identifying role" do
32
- proc do
33
- module Mod
34
- class Cat
35
- identified_by :name
36
- has_one :name
37
- end
33
+ proc do
34
+ module Mod
35
+ class Cat
36
+ identified_by :name
37
+ has_one :name
38
38
  end
39
- end.should raise_error
40
- end
39
+ end
40
+ end.should raise_error
41
41
  end
42
42
 
43
43
  describe "when asserted" do
@@ -81,11 +81,13 @@ describe "An Entity Type" do
81
81
  end
82
82
 
83
83
  it "should fail if the new value already exists" do
84
- pending "Doesn't check validity of rename" do
85
- proc do
86
- @bus.name = 'Acme'
87
- end.should raise_error
88
- end
84
+ proc do
85
+ @fly.name = 'Acme'
86
+ end.should raise_error
87
+ end
88
+
89
+ it "should not fail if the new value is self" do
90
+ lambda { @bus.name = 'Acme' }.should_not raise_error
89
91
  end
90
92
 
91
93
  describe "to a previously-nonexistent value" do
@@ -103,15 +105,11 @@ describe "An Entity Type" do
103
105
  end
104
106
 
105
107
  it "should be found under the new identifier" do
106
- pending "entities are not re-indexed on identifier assignment" do
107
- @c.Business['Bloggs'].should == @bus
108
- end
108
+ @c.Business[['Bloggs']].should == @bus
109
109
  end
110
110
 
111
111
  it "should be in the constellation's index under the new identifier" do
112
- pending "entities are not re-indexed on identifier assignment" do
113
- @c.Business.keys[0].should == ['Bloggs']
114
- end
112
+ @c.Business.keys.should include ['Bloggs']
115
113
  end
116
114
 
117
115
  it "should be the counterpart of the new identifier" do
@@ -119,24 +117,23 @@ describe "An Entity Type" do
119
117
  end
120
118
 
121
119
  it "should not be found in the constellation using the old value" do
122
- pending "entities are not de-indexed on identifier assignment" do
123
- @c.Business[['Acme']].should be_nil
124
- end
120
+ @c.Business[['Acme']].should be_nil
125
121
  end
126
122
 
127
123
  it "the old value's back-reference is set to nil" do
128
124
  @acme.business.should be_nil
129
125
  end
130
126
 
131
- describe "and the old identifying value plays no other roles" do
132
- describe "and the player of the identifying role is not independent" do
133
- it "should retract the previous value" do
134
- pending "All value types default to independent" do
135
- @c.Name['Acme'].should be_nil
136
- end
137
- end
138
- end
139
- end
127
+ #describe "and the old identifying value plays no other roles" do
128
+ # describe "and the player of the identifying role is not independent" do
129
+ # it "should retract the previous value" do
130
+ # pending "All value types default to independent" do
131
+ # @c.Name['Acme'].should be_nil
132
+ # end
133
+ # end
134
+ # end
135
+ #end
136
+
140
137
  end
141
138
  end
142
139
 
@@ -157,11 +154,11 @@ describe "An Entity Type" do
157
154
  @bus.retract
158
155
  end
159
156
 
160
- it "should retract the identifying value also" do
161
- pending "All value types default to independent" do
162
- @c.Name['Acme'].should be_nil
163
- end
164
- end
157
+ #it "should retract the identifying value also" do
158
+ # pending "All value types default to independent" do
159
+ # @c.Name['Acme'].should be_nil
160
+ # end
161
+ #end
165
162
 
166
163
  it "should not appear as the value's counterpart role" do
167
164
  @acme.business.should be_nil
@@ -204,24 +201,39 @@ describe "An Entity Type" do
204
201
  has_one :building
205
202
  has_one :number
206
203
  end
204
+
205
+ class OwnershipId < Int
206
+ value_type
207
+ end
208
+
209
+ class Owner
210
+ identified_by :ownership_id, :building
211
+ has_one :ownership_id
212
+ has_one :building
213
+ end
214
+
215
+ class OwnerRoom
216
+ identified_by :owner, :room
217
+ has_one :owner
218
+ has_one :room
219
+ end
207
220
  end
208
221
  end
222
+
209
223
  before :each do
210
224
  @c = ActiveFacts::API::Constellation.new(Mod)
211
225
  end
212
226
 
213
227
  it "should fail if any role is one-to-one" do
214
- pending "Lacks a check for one-to-one identifying role" do
215
- proc do
216
- module Mod
217
- class Floor
218
- identified_by :building, :number
219
- has_one :building
220
- one_to_one :number # Error, invalid identifier
221
- end
228
+ proc do
229
+ module Mod
230
+ class Floor
231
+ identified_by :building, :number
232
+ has_one :building
233
+ one_to_one :number # Error, invalid identifier
222
234
  end
223
- end.should raise_error
224
- end
235
+ end
236
+ end.should raise_error
225
237
  end
226
238
 
227
239
  describe "when asserted" do
@@ -230,6 +242,9 @@ describe "An Entity Type" do
230
242
  @mackay = @c.Name['Mackay']
231
243
  @r = @c.Room(@b, 101)
232
244
  @rn = @r.number
245
+
246
+ @o = @c.Owner(1_001, @b)
247
+ @or = @c.OwnerRoom(@o, @r)
233
248
  end
234
249
 
235
250
  it "should return a new instance if not previously present" do
@@ -271,15 +286,14 @@ describe "An Entity Type" do
271
286
  @mackay = @c.Name['Mackay']
272
287
  @r = @c.Room(@b, 101)
273
288
  @rn = @r.number
289
+
290
+ @o = @c.Owner(1_001, @b)
291
+ @or = @c.OwnerRoom(@o, @r)
274
292
  end
275
293
 
276
294
  it "should fail if the new value already exists" do
277
295
  @c.Room(@b, 102)
278
- pending "Doesn't check validity of rename" do
279
- proc {
280
- @r.number = 102
281
- }.should raise_error
282
- end
296
+ lambda { @r.number = 102 }.should raise_error
283
297
  end
284
298
 
285
299
  describe "to a previously-nonexistent value" do
@@ -298,16 +312,18 @@ describe "An Entity Type" do
298
312
  end
299
313
 
300
314
  it "should be found under the new identifier" do
301
- pending "entities are not re-indexed on identifier assignment" do
302
- @c.Room[[@b.identifying_role_values, 103]].should == @r
303
- @c.Room[[['Mackay'], 101]].should be_nil
304
- end
315
+ @c.Room[[@b.identifying_role_values, 103]].should == @r
316
+ @c.Room[[['Mackay'], 101]].should be_nil
317
+ end
318
+
319
+ it "should be found under the new identifier even on deep associations" do
320
+ @c.OwnerRoom[[@o.identifying_role_values, @r.identifying_role_values]].should == @or
321
+ @c.OwnerRoom[[[1_001, ['Mackay']], [['Mackay'], 103]]].should == @or
322
+ @c.OwnerRoom[[[1_001, ['Mackay']], [['Mackay'], 101]]].should be_nil
305
323
  end
306
324
 
307
325
  it "should be in the constellation's index under the new identifier" do
308
- pending "entities are not de-indexed on identifier assignment" do
309
- @c.Room.keys[0].should == [['Mackay'], @r.number]
310
- end
326
+ @c.Room.keys[0].should == [['Mackay'], @r.number]
311
327
  end
312
328
 
313
329
  it "should be included in the counterparts of the new identifier roles" do
@@ -316,24 +332,22 @@ describe "An Entity Type" do
316
332
  end
317
333
 
318
334
  it "should not be found in the constellation using the old value" do
319
- pending "entities are not de-indexed on identifier assignment" do
320
- @c.Room.keys[0].should_not == [['Mackay'],101]
321
- end
335
+ @c.Room.keys[0].should_not == [['Mackay'],101]
322
336
  end
323
337
 
324
338
  it "the old value's back-reference is set to nil" do
325
- @rn.all_room.to_a.should_not be_include(@r)
339
+ @rn.all_room.to_a.should_not include @r
326
340
  end
327
341
 
328
- describe "and the old identifying value plays no other roles" do
329
- describe "and the player of the identifying role is not independent" do
330
- it "should retract the previous value" do
331
- pending "All value types default to independent" do
332
- @c.Number[101].should be_nil
333
- end
334
- end
335
- end
336
- end
342
+ #describe "and the old identifying value plays no other roles" do
343
+ # describe "and the player of the identifying role is not independent" do
344
+ # it "should retract the previous value" do
345
+ # pending "All value types default to independent" do
346
+ # @c.Number[101].should be_nil
347
+ # end
348
+ # end
349
+ # end
350
+ #end
337
351
  end
338
352
  end
339
353
 
@@ -0,0 +1,118 @@
1
+ #
2
+ # ActiveFacts tests: Value instances in the Runtime API
3
+ # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
+ #
5
+
6
+ require 'fixtures/tax'
7
+ include ActiveFacts::API
8
+
9
+ describe "identity" do
10
+ before :each do
11
+ @c1 = Constellation.new(Tax)
12
+ @juliar = "Juliar Gillard"
13
+
14
+ @p1 = @c1.Australian(@juliar)
15
+ end
16
+
17
+ it "should be indexed" do
18
+ @c1.Name.keys.should == [@juliar]
19
+ @c1.Name.values.should == [@juliar]
20
+ @c1.Person.keys.should == [[@juliar]]
21
+ @c1.Person.values.should == [@p1]
22
+ @c1.Australian.keys.should == [[@juliar]]
23
+ @c1.Australian.values.should == [@p1]
24
+ end
25
+
26
+ describe "change" do
27
+ before :each do
28
+ @tony = "Tony Abbot"
29
+ @p3 = @c1.AustralianTaxPayer(:tfn => 123, :name => @tony)
30
+
31
+ @r1 = @c1.AustralianTaxReturn(@p3, 2010)
32
+ @c1.AustralianTaxReturn.keys.should == [[[123], [2010]]]
33
+ @c1.AustralianTaxReturn.values.should == [@r1]
34
+
35
+ @c1.Name.keys.should =~ [@juliar, @tony]
36
+ @c1.Name.values.should =~ [@juliar, @tony]
37
+ @c1.Person.keys.should =~ [[@juliar], [@tony]]
38
+ @c1.Person.values.should =~ [@p1, @p3]
39
+ @c1.Australian.keys.should =~ [[@juliar], [@tony]]
40
+ @c1.Australian.values.should =~ [@p1, @p3]
41
+ @c1.AustralianTaxPayer.keys.should =~ [[123]]
42
+ @c1.AustralianTaxPayer.values.should =~ [@p3]
43
+ end
44
+
45
+ describe "that implies change of subtype" do
46
+ before :each do
47
+ @p2 = nil
48
+ @change = proc {
49
+ @p2 = @c1.AustralianTaxPayer(:tfn => 789, :name => "Juliar Gillard")
50
+ }
51
+ end
52
+
53
+ it "should be denied" do
54
+ @change.should raise_error(DuplicateIdentifyingValueException)
55
+ end
56
+
57
+ it "should not change instance subtype" do
58
+ @p1.class.should == Tax::Australian
59
+ end
60
+
61
+ it "should have no side-effects" do
62
+ begin
63
+ @change.call
64
+ rescue DuplicateIdentifyingValueException => e
65
+ end
66
+
67
+ @p2.should be_nil
68
+ @c1.Name.values.should =~ [@juliar, @tony]
69
+ @c1.Name.keys.should =~ [@juliar, @tony]
70
+ @c1.TFN.keys.should =~ [123]
71
+ @c1.Person.values.should =~ [@p1, @p3]
72
+ @c1.Person.keys.should =~ [[@juliar],[@tony]]
73
+ @c1.Australian.values.should =~ [@p1, @p3]
74
+ end
75
+
76
+ it "should have no side-effects (retracting values which shouldn't)" do
77
+ @p2_tfn = @c1.TFN(789)
78
+ begin
79
+ @change.call
80
+ rescue DuplicateIdentifyingValueException => e
81
+ end
82
+
83
+ @c1.TFN.keys.should =~ [123, 789]
84
+ end
85
+ end
86
+
87
+ describe "causing conflict" do
88
+ it "should fail and make no change" do
89
+ proc {
90
+ @p3.name = "Juliar Gillard" # Must fail; must leave @p3 untouched.
91
+ }.should raise_error # (ActiveFacts::API::AmbiguousIdentityChange)
92
+
93
+ @p3.name.should == @tony
94
+ end
95
+ end
96
+
97
+ describe "without conflict" do
98
+ before :each do
99
+ @p3.tfn = 456
100
+ end
101
+
102
+ it "should be allowed" do
103
+ @p3.identifying_role_values.should == [456]
104
+ end
105
+
106
+ it "should be re-indexed" do
107
+ @c1.AustralianTaxPayer.keys.should == [[456]]
108
+ end
109
+
110
+ it "should be propagated" do
111
+ key = [[456], [2010]]
112
+ @r1.identifying_role_values.should == key
113
+ @c1.AustralianTaxReturn.keys.should == [key]
114
+ @c1.AustralianTaxReturn.values.should == [@r1]
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # ActiveFacts tests: Value instances in the Runtime API
3
+ # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
+ #
5
+
6
+ describe 'identity change on subtype' do
7
+ before :all do
8
+ module Mod
9
+ class EntityA
10
+ identified_by :value_a
11
+ one_to_one :value_a
12
+ has_one :value_b
13
+ end
14
+
15
+ class ValueA < Int
16
+ value_type
17
+ end
18
+
19
+ class ValueB < String
20
+ value_type
21
+ end
22
+
23
+ class EntityB < EntityA
24
+ identified_by :value_b
25
+ end
26
+ end
27
+
28
+ @constellation = ActiveFacts::API::Constellation.new(Mod)
29
+ @a = @constellation.EntityA(123)
30
+ end
31
+
32
+ it "should fail if the value is the same" do
33
+ lambda { @b = @constellation.EntityB(123, 'abc') }.should raise_error
34
+ end
35
+
36
+ context "on a deep-subtype" do
37
+ before :all do
38
+ module Mod
39
+ class EntityC < EntityB
40
+ end
41
+ end
42
+
43
+ @c = @constellation.EntityC(:value_a => 1, :value_b => 'abc')
44
+ end
45
+
46
+ it "should fail if the value already exist" do
47
+ @a.value_a.should == 123
48
+ @c.value_a.should == 1
49
+ lambda { @a.value_a = 1 }.should raise_error(ActiveFacts::API::DuplicateIdentifyingValueException)
50
+ lambda { @c.value_a = 123 }.should raise_error(ActiveFacts::API::DuplicateIdentifyingValueException)
51
+ end
52
+
53
+ it "should keep the previous value intact" do
54
+ @a.value_a.should == 123
55
+ @c.value_a.should == 1
56
+ end
57
+
58
+ it "should allow the change when the value doesn't exist" do
59
+ @c.value_a = 987
60
+ @c.value_a.should == 987
61
+ end
62
+ end
63
+ end
@@ -2,8 +2,6 @@
2
2
  # ActiveFacts tests: Entity classes in the Runtime API
3
3
  # Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
4
4
  #
5
- require 'rspec'
6
- require 'activefacts/api'
7
5
 
8
6
  describe "Entity Type class definitions" do
9
7
  before :each do
@@ -16,7 +14,7 @@ describe "Entity Type class definitions" do
16
14
  end
17
15
  class Person < LegalEntity
18
16
  identified_by :name
19
- has_one :name, :class => Name
17
+ one_to_one :name, :class => Name
20
18
  end
21
19
  end
22
20
  end
@@ -77,7 +75,7 @@ describe "Entity Type class definitions" do
77
75
  Mod::Person.roles.include?(:name).should be_true
78
76
  end
79
77
 
80
- it "should fail on a ValueClass" do
78
+ it "should fail on a ValClass" do
81
79
  lambda{
82
80
  class SomeClass < String
83
81
  identified_by