activefacts-api 0.8.12 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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