activefacts-api 1.8.1 → 1.8.3
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.
- checksums.yaml +4 -4
- data/.gitignore +28 -0
- data/.rspec +0 -1
- data/Gemfile +1 -10
- data/Rakefile +3 -27
- data/VERSION +1 -1
- data/activefacts-api.gemspec +35 -95
- data/lib/activefacts/api/version.rb +5 -0
- data/lib/activefacts/tracer.rb +13 -9
- metadata +23 -68
- data/spec/constellation/constellation_spec.rb +0 -577
- data/spec/constellation/instance_index_spec.rb +0 -91
- data/spec/constellation/instance_spec.rb +0 -441
- data/spec/fact_type/role_values_spec.rb +0 -439
- data/spec/fact_type/roles_spec.rb +0 -283
- data/spec/fixtures/tax.rb +0 -45
- data/spec/identification_scheme/identification_spec.rb +0 -420
- data/spec/identification_scheme/identity_change_spec.rb +0 -119
- data/spec/identification_scheme/identity_supertype_change_spec.rb +0 -63
- data/spec/metadata_spec.rb +0 -267
- data/spec/object_type/entity_type/entity_type_spec.rb +0 -102
- data/spec/object_type/entity_type/multipart_identification_spec.rb +0 -82
- data/spec/object_type/value_type/autocounter_spec.rb +0 -87
- data/spec/object_type/value_type/date_time_spec.rb +0 -38
- data/spec/object_type/value_type/guid_spec.rb +0 -71
- data/spec/object_type/value_type/numeric_spec.rb +0 -63
- data/spec/object_type/value_type/value_type_spec.rb +0 -124
- data/spec/simplecov_helper.rb +0 -9
- data/spec/spec_helper.rb +0 -13
- data/spec/support/reduce_exceptions_helper.rb +0 -29
@@ -1,577 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# ActiveFacts tests: Constellation instances in the Runtime API
|
3
|
-
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
|
-
#
|
5
|
-
|
6
|
-
describe "A Constellation instance" do
|
7
|
-
before :each do
|
8
|
-
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
9
|
-
module Mod
|
10
|
-
@base_types = [
|
11
|
-
Int, Real, AutoCounter, String, Date, DateTime, Decimal, Guid
|
12
|
-
]
|
13
|
-
|
14
|
-
# Create a value type and a subtype of that value type for each base type:
|
15
|
-
@base_types.each do |base_type|
|
16
|
-
Mod.module_eval <<-END
|
17
|
-
class #{base_type.basename}Val < #{base_type.name}
|
18
|
-
value_type
|
19
|
-
end
|
20
|
-
|
21
|
-
class #{base_type.basename}SubVal < #{base_type.name}Val
|
22
|
-
# Note no new "value_type" is required here, it comes through inheritance
|
23
|
-
end
|
24
|
-
END
|
25
|
-
end
|
26
|
-
|
27
|
-
class Name < StringVal
|
28
|
-
value_type
|
29
|
-
#has_one :attr, Name
|
30
|
-
has_one :undefined_role # This will be unsatisfied with the non-existence of the UndefinedRole class
|
31
|
-
end
|
32
|
-
|
33
|
-
class LegalEntity
|
34
|
-
identified_by :name
|
35
|
-
one_to_one :name, :mandatory => true
|
36
|
-
end
|
37
|
-
|
38
|
-
class Surrogate
|
39
|
-
identified_by :auto_counter_val
|
40
|
-
one_to_one :auto_counter_val
|
41
|
-
end
|
42
|
-
|
43
|
-
class Company < LegalEntity
|
44
|
-
supertypes Surrogate
|
45
|
-
end
|
46
|
-
|
47
|
-
class Person < LegalEntity
|
48
|
-
identified_by :name, :family_name # REVISIT: want a way to role_alias :name, :given_name
|
49
|
-
supertypes :surrogate # Use a Symbol binding this time
|
50
|
-
|
51
|
-
has_one :family_name, :class => Name
|
52
|
-
has_one :employer, :class => Company
|
53
|
-
one_to_one :birth_name, :class => Name
|
54
|
-
end
|
55
|
-
end
|
56
|
-
@constellation = ActiveFacts::API::Constellation.new(Mod)
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "Vocabulary" do
|
60
|
-
it "should create the constellation" do
|
61
|
-
Mod.constellation.should be_an_instance_of ActiveFacts::API::Constellation
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should create the constellation by direct populate" do
|
65
|
-
Mod.populate do
|
66
|
-
Name "foo"
|
67
|
-
end.should be_an_instance_of ActiveFacts::API::Constellation
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should verbalise" do
|
71
|
-
s = Mod.verbalise
|
72
|
-
s.should be_an_instance_of String
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should allow creating a constellation" do
|
77
|
-
@constellation = ActiveFacts::API::Constellation.new(Mod)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should complain when accessing a non-class as a method" do
|
81
|
-
Mod::Foo = 23
|
82
|
-
lambda { @constellation.Foo }.should raise_error(NoMethodError)
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should complain when accessing a class that isn't an object type" do
|
86
|
-
class Mod::Bar; end
|
87
|
-
proc { @constellation.Bar }.should raise_error(NoMethodError)
|
88
|
-
proc { @constellation.instances[Mod::Bar] }.should raise_error(ActiveFacts::API::InvalidObjectType)
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should deny handling an object type defined outside the current module" do
|
92
|
-
class ::Bar; end
|
93
|
-
lambda { @constellation.Bar }.should raise_error(NoMethodError)
|
94
|
-
lambda { @constellation.instances[Bar] }.should raise_error(ActiveFacts::API::InvalidObjectType)
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should allow inspection" do
|
98
|
-
lambda { @constellation.inspect }.should_not raise_error
|
99
|
-
end
|
100
|
-
|
101
|
-
it "should support fetching its vocabulary" do
|
102
|
-
@constellation.vocabulary.should == Mod
|
103
|
-
end
|
104
|
-
|
105
|
-
# it "should support fetching its query" do
|
106
|
-
# pending
|
107
|
-
# @constellation.query.should == Mod
|
108
|
-
# end
|
109
|
-
|
110
|
-
it "should create methods to assert instances" do
|
111
|
-
# Check that methods have not yet been created:
|
112
|
-
@constellation.should_not respond_to(:Name)
|
113
|
-
@constellation.should_not respond_to(:LegalEntity)
|
114
|
-
@constellation.should_not respond_to(:Company)
|
115
|
-
@constellation.should_not respond_to(:Person)
|
116
|
-
|
117
|
-
# Assert instances
|
118
|
-
name = foo = acme = fred_fly = nil
|
119
|
-
lambda {
|
120
|
-
name = @constellation.Name("foo")
|
121
|
-
foo = @constellation.LegalEntity("foo")
|
122
|
-
acme = @constellation.Company("Acme, Inc", :auto_counter_val => :new)
|
123
|
-
fred_fly = @constellation.Person("fred", "fly", :auto_counter_val => :new)
|
124
|
-
}.should_not raise_error
|
125
|
-
|
126
|
-
# Check that methods have not yet been created:
|
127
|
-
@constellation.should respond_to(:Name)
|
128
|
-
@constellation.should respond_to(:LegalEntity)
|
129
|
-
@constellation.should respond_to(:Company)
|
130
|
-
@constellation.should respond_to(:Person)
|
131
|
-
|
132
|
-
# Check the instances
|
133
|
-
name.class.should == Mod::Name
|
134
|
-
name.constellation.should == @constellation
|
135
|
-
|
136
|
-
foo.class.should == Mod::LegalEntity
|
137
|
-
foo.constellation.should == @constellation
|
138
|
-
foo.inspect.should =~ / in Conste/
|
139
|
-
foo.verbalise.should =~ /LegalEntity\(/
|
140
|
-
|
141
|
-
acme.class.should == Mod::Company
|
142
|
-
acme.constellation.should == @constellation
|
143
|
-
acme.inspect.should =~ / in Conste/
|
144
|
-
acme.verbalise.should =~ /Company\(/
|
145
|
-
|
146
|
-
fred_fly.class.should == Mod::Person
|
147
|
-
fred_fly.constellation.should == @constellation
|
148
|
-
fred_fly.inspect.should =~ / in Conste/
|
149
|
-
fred_fly.verbalise.should =~ /Person\(/
|
150
|
-
end
|
151
|
-
|
152
|
-
it "should re-use instances constructed the same way" do
|
153
|
-
name1 = @constellation.Name("foo")
|
154
|
-
foo1 = @constellation.LegalEntity("foo")
|
155
|
-
acme1 = @constellation.Company("Acme, Inc", :auto_counter_val => :new)
|
156
|
-
fred_fly1 = @constellation.Person("fred", "fly", :auto_counter_val => :new)
|
157
|
-
|
158
|
-
name2 = @constellation.Name("foo")
|
159
|
-
foo2 = @constellation.LegalEntity("foo")
|
160
|
-
acme2 = @constellation.Company("Acme, Inc") # , :auto_counter_val => :new)
|
161
|
-
fred_fly2 = @constellation.Person("fred", "fly") # , :auto_counter_val => :new)
|
162
|
-
|
163
|
-
name1.object_id.should == name2.object_id
|
164
|
-
foo1.object_id.should == foo2.object_id
|
165
|
-
acme1.object_id.should == acme2.object_id
|
166
|
-
fred_fly1.object_id.should == fred_fly2.object_id
|
167
|
-
end
|
168
|
-
|
169
|
-
describe "re-assertion with any one of multiple identifiers" do
|
170
|
-
before :each do
|
171
|
-
# Create some instances:
|
172
|
-
@name1 = @constellation.Name("foo") # Value type
|
173
|
-
@foo1 = @constellation.LegalEntity("foo") # Entity Type with simple identifier
|
174
|
-
@acme1 = @constellation.Company("Acme, Inc", :auto_counter_val => :new)
|
175
|
-
@acme1_id = @acme1.auto_counter_val
|
176
|
-
end
|
177
|
-
|
178
|
-
it "should be allowed with a normal value type id" do
|
179
|
-
# Reassert the instances:
|
180
|
-
@name2 = @constellation.Name("foo")
|
181
|
-
@foo2 = @constellation.LegalEntity("foo")
|
182
|
-
@acme2 = nil
|
183
|
-
lambda {
|
184
|
-
# Without the auto_counter_val
|
185
|
-
@acme2 = @constellation.Company("Acme, Inc")
|
186
|
-
}.should_not raise_error
|
187
|
-
|
188
|
-
# This creates a new auto_counter_val, changing the acme instance (and hence, both references to it)
|
189
|
-
@acme2.auto_counter_val = :new
|
190
|
-
@acme2.should == @acme1
|
191
|
-
@acme2.auto_counter_val.should_not be_defined
|
192
|
-
@acme2.auto_counter_val.to_s.should_not == @acme1_id.to_s
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should be allowed with an autocounter id" do
|
196
|
-
acme3 = @constellation.Surrogate(@acme1_id)
|
197
|
-
acme3.should == @acme1
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
it "Should raise an exception with assigning a role whose referent (object type) has not yet been defined" do
|
202
|
-
n = @constellation.Name("Fred")
|
203
|
-
# This does not raise the "settable_roles_exception". I'm no longer sure how I did this, so I can't get coverage on this code :(
|
204
|
-
proc { n.undefined_role = 'foo' }.should raise_error(NoMethodError)
|
205
|
-
end
|
206
|
-
|
207
|
-
# Maybe not complete yet
|
208
|
-
describe "assigning additional arguments on asserting a value type" do
|
209
|
-
before :each do
|
210
|
-
# This should work, but...
|
211
|
-
# birth_name = @constellation.Name("Smith", :person_as_birth_name => {:name => "Janet", :family_name => "Jones", :auto_counter_val => :new})
|
212
|
-
# for now, use the following form
|
213
|
-
@birth_name = @constellation.Name("Smith", :person_as_birth_name => ["Janet", "Jones", {:auto_counter_val => :new}])
|
214
|
-
@person = @birth_name.person_as_birth_name
|
215
|
-
end
|
216
|
-
|
217
|
-
it "should create required instances" do
|
218
|
-
@person.should_not be_nil
|
219
|
-
@person.family_name.should == "Jones"
|
220
|
-
@person.name.should == "Janet"
|
221
|
-
@person.birth_name.should == "Smith"
|
222
|
-
end
|
223
|
-
|
224
|
-
it "should initialise secondary supertypes" do
|
225
|
-
@acv = @person.auto_counter_val
|
226
|
-
@acv.should_not be_nil
|
227
|
-
@acv.surrogate.should == @person
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
it "should support population blocks" do
|
232
|
-
@constellation.populate do
|
233
|
-
Name("bar")
|
234
|
-
LegalEntity("foo")
|
235
|
-
Person("Fred", "Nerk", :auto_counter_val => :new)
|
236
|
-
Company("Acme, Inc", :auto_counter_val => :new)
|
237
|
-
end
|
238
|
-
@constellation.Name.size.should == 5
|
239
|
-
@constellation.Surrogate.size.should == 2
|
240
|
-
end
|
241
|
-
|
242
|
-
it "should verbalise itself" do
|
243
|
-
@constellation.populate do
|
244
|
-
Name("bar")
|
245
|
-
LegalEntity("foo")
|
246
|
-
c = Company("Acme, Inc", :auto_counter_val => :new)
|
247
|
-
c.is_a?(Mod::Surrogate).should == true
|
248
|
-
c.auto_counter_val.should_not == nil
|
249
|
-
p = Person("Fred", "Nerk", :auto_counter_val => :new)
|
250
|
-
p.employer = c
|
251
|
-
p.birth_name = "Nerk"
|
252
|
-
end
|
253
|
-
s = @constellation.verbalise
|
254
|
-
names = s.split(/\n/).grep(/\tEvery /).map{|l| l.sub(/.*Every (.*):$/, '\1')}
|
255
|
-
expected = ["Company", "LegalEntity", "Name", "Person", "StringVal", "Surrogate"]
|
256
|
-
names.sort.should == expected
|
257
|
-
end
|
258
|
-
|
259
|
-
it "should support string capitalisation functions" do
|
260
|
-
names = ["Company", "LegalEntity", "Name", "Person", "StringVal", "Surrogate"]
|
261
|
-
camelwords = names.map{|n| n.camelwords }
|
262
|
-
camelwords.should == [["Company"], ["Legal", "Entity"], ["Name"], ["Person"], ["String", "Val"], ["Surrogate"]]
|
263
|
-
|
264
|
-
snakes = names.map{|n| n.snakecase }
|
265
|
-
snakes.should == ["company", "legal_entity", "name", "person", "string_val", "surrogate"]
|
266
|
-
|
267
|
-
camelupper = snakes.map{|n| n.camelcase }
|
268
|
-
camelupper.should == ["Company", "LegalEntity", "Name", "Person", "StringVal", "Surrogate"]
|
269
|
-
|
270
|
-
camellower = snakes.map{|n| n.camelcase(:lower) }
|
271
|
-
camellower.should == ["company", "legalEntity", "name", "person", "stringVal", "surrogate"]
|
272
|
-
end
|
273
|
-
|
274
|
-
it "should allow inspection of instance indices" do
|
275
|
-
baz = @constellation.Name("baz")
|
276
|
-
@constellation.Name.inspect.class.should == String
|
277
|
-
end
|
278
|
-
|
279
|
-
it "should index value instances, including by its superclasses" do
|
280
|
-
baz = @constellation.Name("baz")
|
281
|
-
@constellation.Name.keys.sort.should == ["baz"]
|
282
|
-
|
283
|
-
@constellation.StringVal.keys.sort.should == ["baz"]
|
284
|
-
@constellation.StringVal[baz].should == baz
|
285
|
-
@constellation.StringVal["baz"].should == baz
|
286
|
-
end
|
287
|
-
|
288
|
-
describe "instance indices" do
|
289
|
-
it "should support each" do
|
290
|
-
baz = @constellation.Name("baz")
|
291
|
-
count = 0
|
292
|
-
@constellation.Name.each { |k, v| count += 1 }
|
293
|
-
count.should == 1
|
294
|
-
end
|
295
|
-
|
296
|
-
it "should support detect" do
|
297
|
-
baz = @constellation.Name("baz")
|
298
|
-
@constellation.Name.detect { |rv| true }.should be_truthy
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
it "should index entity instances, including by its superclass and secondary supertypes" do
|
303
|
-
name = "Acme, Inc"
|
304
|
-
fred = "Fred"
|
305
|
-
fly = "Fly"
|
306
|
-
acme = @constellation.Company name, :auto_counter_val => :new
|
307
|
-
fred_fly = @constellation.Person fred, fly, :auto_counter_val => :new
|
308
|
-
|
309
|
-
# REVISIT: This should be illegal:
|
310
|
-
#fred_fly.auto_counter_val = :new
|
311
|
-
|
312
|
-
@constellation.Person.keys.sort.should == [[fred, fly]]
|
313
|
-
@constellation.Company.keys.sort.should == [[name]]
|
314
|
-
|
315
|
-
@constellation.LegalEntity.keys.sort.should include [name]
|
316
|
-
@constellation.LegalEntity.keys.sort.should include [fred]
|
317
|
-
|
318
|
-
@constellation.Surrogate.values.should include acme
|
319
|
-
@constellation.Surrogate.values.should include fred_fly
|
320
|
-
end
|
321
|
-
|
322
|
-
it "should handle one-to-ones correctly" do
|
323
|
-
person = @constellation.Person "Fred", "Smith", :auto_counter_val => :new, :birth_name => "Nerk"
|
324
|
-
|
325
|
-
nerk = @constellation.Name["Nerk"]
|
326
|
-
nerk.should_not be_nil
|
327
|
-
nerk.person_as_birth_name.should == person
|
328
|
-
person.birth_name = nil
|
329
|
-
nerk.person_as_birth_name.should be_nil
|
330
|
-
@constellation.Name["Nerk"].should_not be_nil
|
331
|
-
end
|
332
|
-
|
333
|
-
it "should allow retraction of instances" do
|
334
|
-
@constellation.Person
|
335
|
-
person = @constellation.Person "Fred", "Smith", :auto_counter_val => :new, :birth_name => "Nerk"
|
336
|
-
smith = @constellation.Name("Smith")
|
337
|
-
|
338
|
-
# Check things are indexed properly:
|
339
|
-
@constellation.Surrogate.size.should == 1
|
340
|
-
@constellation.LegalEntity.size.should == 1
|
341
|
-
@constellation.Person.size.should == 1
|
342
|
-
person.family_name.should == smith
|
343
|
-
smith.all_person_as_family_name.size.should == 1
|
344
|
-
|
345
|
-
@constellation.retract(smith)
|
346
|
-
|
347
|
-
@constellation.Name["Fred"].should_not be_nil # FamilyName is not mandatory, so Fred still exists
|
348
|
-
@constellation.Name["Smith"].should be_nil
|
349
|
-
|
350
|
-
@constellation.Surrogate.size.should == 1
|
351
|
-
@constellation.LegalEntity.size.should == 1
|
352
|
-
@constellation.Person.size.should == 1
|
353
|
-
|
354
|
-
person.family_name.should be_nil
|
355
|
-
|
356
|
-
smith.all_person_as_family_name.size.should == 0
|
357
|
-
end
|
358
|
-
|
359
|
-
it "should retract linked instances (cascading)" do
|
360
|
-
fred = @constellation.Person "Fred", "Smith", :auto_counter_val => :new, :birth_name => "Nerk"
|
361
|
-
george = @constellation.Person "George", "Smith", :auto_counter_val => :new, :birth_name => "Patrick"
|
362
|
-
smith = @constellation.Name("Smith")
|
363
|
-
|
364
|
-
@constellation.Person.size.should == 2
|
365
|
-
fred.family_name.should == smith
|
366
|
-
george.family_name.should == smith
|
367
|
-
smith.all_person_as_family_name.size.should == 2
|
368
|
-
|
369
|
-
@constellation.retract(fred)
|
370
|
-
|
371
|
-
@constellation.Person.size.should == 1 # Fred is gone, George still exists
|
372
|
-
@constellation.Person.values[0].name.should == 'George'
|
373
|
-
fred.family_name.should be_nil
|
374
|
-
smith.all_person_as_family_name.size.should == 1
|
375
|
-
end
|
376
|
-
|
377
|
-
it "should fail to recognise references to unresolved forward referenced classes" do
|
378
|
-
module Mod2
|
379
|
-
class Foo
|
380
|
-
identified_by :name
|
381
|
-
one_to_one :name
|
382
|
-
has_one :not_yet
|
383
|
-
has_one :baz, :class => "BAZ"
|
384
|
-
end
|
385
|
-
|
386
|
-
class Name < String
|
387
|
-
value_type
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
@c = ActiveFacts::API::Constellation.new(Mod2)
|
392
|
-
le = @c.Foo("Foo")
|
393
|
-
lambda {
|
394
|
-
le.not_yet
|
395
|
-
}.should raise_error(NoMethodError)
|
396
|
-
lambda {
|
397
|
-
le.baz
|
398
|
-
}.should raise_error(NoMethodError)
|
399
|
-
|
400
|
-
# Now define the classes and try again:
|
401
|
-
module Mod2
|
402
|
-
class NotYet < String
|
403
|
-
value_type
|
404
|
-
end
|
405
|
-
class BAZ < String
|
406
|
-
value_type
|
407
|
-
end
|
408
|
-
end
|
409
|
-
lambda {
|
410
|
-
le.not_yet
|
411
|
-
le.not_yet = 'not_yet'
|
412
|
-
}.should_not raise_error
|
413
|
-
lambda {
|
414
|
-
le.baz
|
415
|
-
le.baz = 'baz'
|
416
|
-
}.should_not raise_error
|
417
|
-
end
|
418
|
-
|
419
|
-
it "should not allow references to classes outside the vocabulary" do
|
420
|
-
module Outside
|
421
|
-
class Other < String
|
422
|
-
value_type
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
lambda {
|
427
|
-
module Mod
|
428
|
-
class IntVal
|
429
|
-
has_one :thingummy, :class => Outside::Other
|
430
|
-
end
|
431
|
-
end
|
432
|
-
}.should raise_error(ActiveFacts::API::CrossVocabularyRoleException)
|
433
|
-
end
|
434
|
-
|
435
|
-
it "should disallow unrecognised supertypes" do
|
436
|
-
lambda {
|
437
|
-
module Mod
|
438
|
-
class LegalEntity
|
439
|
-
supertypes :foo
|
440
|
-
end
|
441
|
-
end
|
442
|
-
}.should raise_error(NameError)
|
443
|
-
|
444
|
-
lambda {
|
445
|
-
module Mod
|
446
|
-
class LegalEntity
|
447
|
-
supertypes Bignum
|
448
|
-
end
|
449
|
-
end
|
450
|
-
}.should raise_error(ActiveFacts::API::InvalidSupertypeException)
|
451
|
-
|
452
|
-
lambda {
|
453
|
-
module Mod
|
454
|
-
class LegalEntity
|
455
|
-
supertypes 3
|
456
|
-
end
|
457
|
-
end
|
458
|
-
}.should raise_error(ActiveFacts::API::InvalidSupertypeException)
|
459
|
-
end
|
460
|
-
|
461
|
-
it "should allow supertypes with supertypes" do
|
462
|
-
lambda {
|
463
|
-
module Mod
|
464
|
-
class ListedCompany < Company
|
465
|
-
end
|
466
|
-
end
|
467
|
-
c = @constellation.ListedCompany("foo", :auto_counter_val => 23)
|
468
|
-
}.should_not raise_error
|
469
|
-
end
|
470
|
-
|
471
|
-
it "should be able to attach a new supertype on an entity type to make it a (sub-)subtype" do
|
472
|
-
module Mod
|
473
|
-
class Dad
|
474
|
-
identified_by :name
|
475
|
-
end
|
476
|
-
class Son < Dad
|
477
|
-
identified_by :name
|
478
|
-
end
|
479
|
-
# the grand son will be linked on the fly
|
480
|
-
class GrandSon
|
481
|
-
identified_by :name
|
482
|
-
end
|
483
|
-
end
|
484
|
-
Mod::GrandSon.supertypes(Mod::Son)
|
485
|
-
Mod::GrandSon.supertypes.should include Mod::Son
|
486
|
-
Mod::Son.supertypes.should include Mod::Dad
|
487
|
-
end
|
488
|
-
|
489
|
-
it "should keep information on where the identification came from" do
|
490
|
-
module Mod
|
491
|
-
class Dad
|
492
|
-
identified_by :name
|
493
|
-
end
|
494
|
-
class Son < Dad
|
495
|
-
identified_by :name
|
496
|
-
end
|
497
|
-
# Note the inheritance.
|
498
|
-
class GrandSon < Son
|
499
|
-
identified_by :name
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
Mod::Son.identification_inherited_from.should == Mod::Dad
|
504
|
-
Mod::Son.identification_inherited_from.should == Mod::Dad
|
505
|
-
Mod::GrandSon.identification_inherited_from.should == Mod::Son
|
506
|
-
Mod::GrandSon.overrides_identification_of.should == Mod::Dad
|
507
|
-
end
|
508
|
-
|
509
|
-
it "should disallow using a value type as a supertypes for an entity type" do
|
510
|
-
lambda {
|
511
|
-
module Mod
|
512
|
-
class CompanyName
|
513
|
-
identified_by :name
|
514
|
-
supertypes :name
|
515
|
-
end
|
516
|
-
end
|
517
|
-
}.should raise_error(ActiveFacts::API::InvalidSupertypeException)
|
518
|
-
end
|
519
|
-
|
520
|
-
it "should error on invalid :class values" do
|
521
|
-
lambda {
|
522
|
-
module Mod
|
523
|
-
class Surrogate
|
524
|
-
has_one :Name, :class => 3
|
525
|
-
end
|
526
|
-
end
|
527
|
-
}.should raise_error(ArgumentError)
|
528
|
-
end
|
529
|
-
|
530
|
-
it "should error on misleading :class values" do
|
531
|
-
lambda {
|
532
|
-
module Mod
|
533
|
-
class Surrogate
|
534
|
-
has_one :Name, :class => Extra
|
535
|
-
end
|
536
|
-
end
|
537
|
-
}.should raise_error(NameError)
|
538
|
-
end
|
539
|
-
|
540
|
-
it "should allow assert using an object of the same type" do
|
541
|
-
c = @constellation.Company("foo", :auto_counter_val => 23)
|
542
|
-
c2 = ActiveFacts::API::Constellation.new(Mod)
|
543
|
-
lambda {
|
544
|
-
c2.Company(c, :auto_counter_val => :new)
|
545
|
-
}.should_not raise_error
|
546
|
-
c2.Company.keys.should == [["foo"]]
|
547
|
-
end
|
548
|
-
|
549
|
-
it "should allow cross-constellation construction" do
|
550
|
-
c = @constellation.Company("foo", :auto_counter_val => 23)
|
551
|
-
lambda {
|
552
|
-
c2 = ActiveFacts::API::Constellation.new(Mod)
|
553
|
-
c2.Company(c.name, :auto_counter_val => :new)
|
554
|
-
}.should_not raise_error
|
555
|
-
end
|
556
|
-
|
557
|
-
it "should copy values during cross-constellation assignment" do
|
558
|
-
c = @constellation.Company("foo", :auto_counter_val => 23)
|
559
|
-
|
560
|
-
# Now make a new constellation and use the above values to initialise new instances
|
561
|
-
p = nil
|
562
|
-
lambda {
|
563
|
-
c2 = ActiveFacts::API::Constellation.new(Mod)
|
564
|
-
p = c2.Person('Fred', 'Smith', :auto_counter_val => :new)
|
565
|
-
p.employer = [ c.name, {:auto_counter_val => c.auto_counter_val}]
|
566
|
-
}.should_not raise_error
|
567
|
-
c.auto_counter_val.should_not === p.employer.auto_counter_val
|
568
|
-
c.auto_counter_val.should_not == p.employer.auto_counter_val
|
569
|
-
c.auto_counter_val.to_s.should == p.employer.auto_counter_val.to_s
|
570
|
-
p.employer.should_not === c
|
571
|
-
|
572
|
-
lambda {
|
573
|
-
# Disallowed because it re-assigns the auto_counter_val identification value
|
574
|
-
p.employer = [ "foo", {:auto_counter_val => :new}]
|
575
|
-
}.should raise_error(ActiveFacts::API::TypeConflictException)
|
576
|
-
end
|
577
|
-
end
|