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.
- data/.rspec +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +14 -0
- data/Rakefile +21 -9
- data/VERSION +1 -1
- data/activefacts-api.gemspec +31 -12
- data/lib/activefacts/api.rb +1 -0
- data/lib/activefacts/api/constellation.rb +3 -1
- data/lib/activefacts/api/entity.rb +74 -29
- data/lib/activefacts/api/exceptions.rb +17 -0
- data/lib/activefacts/api/instance.rb +96 -1
- data/lib/activefacts/api/instance_index.rb +35 -37
- data/lib/activefacts/api/numeric.rb +62 -56
- data/lib/activefacts/api/object_type.rb +49 -23
- data/lib/activefacts/api/role.rb +8 -2
- data/lib/activefacts/api/role_values.rb +8 -26
- data/lib/activefacts/api/standard_types.rb +2 -17
- data/lib/activefacts/api/vocabulary.rb +1 -1
- data/lib/activefacts/tracer.rb +13 -1
- data/spec/{constellation_spec.rb → constellation/constellation_spec.rb} +127 -56
- data/spec/constellation/instance_index_spec.rb +90 -0
- data/spec/{instance_spec.rb → constellation/instance_spec.rb} +48 -42
- data/spec/{role_values_spec.rb → fact_type/role_values_spec.rb} +28 -19
- data/spec/{roles_spec.rb → fact_type/roles_spec.rb} +55 -21
- data/spec/fixtures/tax.rb +45 -0
- data/spec/{identification_spec.rb → identification_scheme/identification_spec.rb} +88 -74
- data/spec/identification_scheme/identity_change_spec.rb +118 -0
- data/spec/identification_scheme/identity_supertype_change_spec.rb +63 -0
- data/spec/{entity_type_spec.rb → object_type/entity_type/entity_type_spec.rb} +2 -4
- data/spec/object_type/entity_type/multipart_identification_spec.rb +77 -0
- data/spec/{autocounter_spec.rb → object_type/value_type/autocounter_spec.rb} +2 -4
- data/spec/object_type/value_type/numeric_spec.rb +63 -0
- data/spec/{value_type_spec.rb → object_type/value_type/value_type_spec.rb} +10 -14
- data/spec/simplecov_helper.rb +8 -0
- data/spec/spec_helper.rb +1 -1
- metadata +100 -19
@@ -2,8 +2,6 @@
|
|
2
2
|
# ActiveFacts tests: Value instances 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 "An instance of every type of ObjectType" do
|
9
7
|
before :each do
|
@@ -19,20 +17,20 @@ describe "An instance of every type of ObjectType" do
|
|
19
17
|
t.name.snakecase
|
20
18
|
end
|
21
19
|
@role_names = @base_type_roles.inject([]) {|a, t|
|
22
|
-
a << :"#{t}
|
20
|
+
a << :"#{t}_val"
|
23
21
|
} +
|
24
22
|
@base_type_roles.inject([]) {|a, t|
|
25
|
-
a << :"#{t}
|
23
|
+
a << :"#{t}_sub_val"
|
26
24
|
}
|
27
25
|
|
28
26
|
# Create a value type and a subtype of that value type for each base type:
|
29
27
|
@base_types.each do |base_type|
|
30
|
-
|
31
|
-
class #{base_type.name}
|
28
|
+
Mod.module_eval <<-END
|
29
|
+
class #{base_type.name}Val < #{base_type.name}
|
32
30
|
value_type
|
33
31
|
end
|
34
32
|
|
35
|
-
class #{base_type.name}
|
33
|
+
class #{base_type.name}SubVal < #{base_type.name}Val
|
36
34
|
# Note no new "value_type" is required here, it comes through inheritance
|
37
35
|
end
|
38
36
|
END
|
@@ -44,11 +42,11 @@ describe "An instance of every type of ObjectType" do
|
|
44
42
|
@base_types.each do |base_type|
|
45
43
|
code = <<-END
|
46
44
|
class TestBy#{base_type.name}
|
47
|
-
identified_by :#{base_type.name.snakecase}
|
45
|
+
identified_by :#{base_type.name.snakecase}_val#{
|
48
46
|
@role_names.map do |role_name|
|
49
47
|
%Q{
|
50
|
-
|
51
|
-
|
48
|
+
#{
|
49
|
+
(role_name == (base_type.name.snakecase+'_val').to_sym ? "one_to_one :#{role_name}, :mandatory => true" : "has_one :#{role_name}")
|
52
50
|
}
|
53
51
|
one_to_one :one_#{role_name}, :class => #{role_name.to_s.camelcase}}
|
54
52
|
end*""
|
@@ -56,10 +54,12 @@ describe "An instance of every type of ObjectType" do
|
|
56
54
|
end
|
57
55
|
|
58
56
|
class TestBy#{base_type.name}Sub
|
59
|
-
identified_by :#{base_type.name.snakecase}
|
57
|
+
identified_by :#{base_type.name.snakecase}_sub_val#{
|
60
58
|
@role_names.map do |role_name|
|
61
59
|
%Q{
|
62
|
-
|
60
|
+
#{
|
61
|
+
(role_name == (base_type.name.snakecase+'_sub_val').to_sym ? "one_to_one :#{role_name}" : "has_one :#{role_name}")
|
62
|
+
}
|
63
63
|
one_to_one :one_#{role_name}, :class => #{role_name.to_s.camelcase}}
|
64
64
|
end*""
|
65
65
|
}
|
@@ -74,7 +74,7 @@ describe "An instance of every type of ObjectType" do
|
|
74
74
|
one_to_one :test_by_#{base_type.name.snakecase}
|
75
75
|
end
|
76
76
|
END
|
77
|
-
|
77
|
+
Mod.module_eval code
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -89,29 +89,29 @@ describe "An instance of every type of ObjectType" do
|
|
89
89
|
@decimal = BigDecimal.new('98765432109876543210')
|
90
90
|
|
91
91
|
# Value Type instances
|
92
|
-
@int_value = Mod::
|
93
|
-
@real_value = Mod::
|
94
|
-
@auto_counter_value = Mod::
|
95
|
-
@new_auto_counter_value = Mod::
|
96
|
-
@string_value = Mod::
|
97
|
-
@date_value = Mod::
|
92
|
+
@int_value = Mod::IntVal.new(1)
|
93
|
+
@real_value = Mod::RealVal.new(1.0)
|
94
|
+
@auto_counter_value = Mod::AutoCounterVal.new(1)
|
95
|
+
@new_auto_counter_value = Mod::AutoCounterVal.new(:new)
|
96
|
+
@string_value = Mod::StringVal.new("one")
|
97
|
+
@date_value = Mod::DateVal.new(2008, 04, 20)
|
98
98
|
# Parse the date:
|
99
|
-
@date_value = Mod::
|
99
|
+
@date_value = Mod::DateVal.new '2nd Nov 2001'
|
100
100
|
d = ::Date.civil(2008, 04, 20)
|
101
|
-
@date_time_value = Mod::
|
101
|
+
@date_time_value = Mod::DateTimeVal.new d # 2008, 04, 20, 10, 28, 14
|
102
102
|
# This next isn't in the same pattern; it makes a Decimal from a BigDecimal rather than a String (coverage reasons)
|
103
|
-
@decimal_value = Mod::
|
103
|
+
@decimal_value = Mod::DecimalVal.new(BigDecimal.new('98765432109876543210'))
|
104
104
|
|
105
105
|
# Value SubType instances
|
106
|
-
@int_sub_value = Mod::
|
107
|
-
@real_sub_value = Mod::
|
108
|
-
@auto_counter_sub_value = Mod::
|
109
|
-
@auto_counter_sub_value_new = Mod::
|
110
|
-
@string_sub_value = Mod::
|
111
|
-
@date_sub_value = Mod::
|
112
|
-
@date_time_sub_value = Mod::
|
106
|
+
@int_sub_value = Mod::IntSubVal.new(4)
|
107
|
+
@real_sub_value = Mod::RealSubVal.new(4.0)
|
108
|
+
@auto_counter_sub_value = Mod::AutoCounterSubVal.new(4)
|
109
|
+
@auto_counter_sub_value_new = Mod::AutoCounterSubVal.new(:new)
|
110
|
+
@string_sub_value = Mod::StringSubVal.new("five")
|
111
|
+
@date_sub_value = Mod::DateSubVal.new(2008, 04, 25)
|
112
|
+
@date_time_sub_value = Mod::DateTimeSubVal.new(::DateTime.civil(2008, 04, 26, 10, 28, 14))
|
113
113
|
# This next isn't in the same pattern; it makes a Decimal from a BigNum rather than a String (coverage reasons)
|
114
|
-
@decimal_sub_value = Mod::
|
114
|
+
@decimal_sub_value = Mod::DecimalSubVal.new(98765432109876543210)
|
115
115
|
|
116
116
|
# Entities identified by Value Type, SubType and Entity-by-value-type instances
|
117
117
|
@test_by_int = Mod::TestByInt.new(2)
|
@@ -164,10 +164,10 @@ describe "An instance of every type of ObjectType" do
|
|
164
164
|
String, Date, DateTime, Decimal
|
165
165
|
]
|
166
166
|
@value_types = [
|
167
|
-
Mod::
|
168
|
-
Mod::
|
169
|
-
Mod::
|
170
|
-
Mod::
|
167
|
+
Mod::IntVal, Mod::RealVal, Mod::AutoCounterVal, Mod::AutoCounterVal,
|
168
|
+
Mod::StringVal, Mod::DateVal, Mod::DateTimeVal, Mod::DecimalVal,
|
169
|
+
Mod::IntSubVal, Mod::RealSubVal, Mod::AutoCounterSubVal, Mod::AutoCounterSubVal,
|
170
|
+
Mod::StringSubVal, Mod::DateSubVal, Mod::DateTimeSubVal, Mod::DecimalSubVal,
|
171
171
|
]
|
172
172
|
@value_instances = [
|
173
173
|
@int_value, @real_value, @auto_counter_value, @new_auto_counter_value,
|
@@ -226,11 +226,11 @@ describe "An instance of every type of ObjectType" do
|
|
226
226
|
'98765432109876543211'
|
227
227
|
]
|
228
228
|
@subtype_role_instances = [
|
229
|
-
Mod::
|
230
|
-
Mod::
|
231
|
-
Mod::
|
232
|
-
Mod::
|
233
|
-
Mod::
|
229
|
+
Mod::IntSubVal.new(6), Mod::RealSubVal.new(6.0),
|
230
|
+
Mod::AutoCounterSubVal.new(:new), Mod::AutoCounterSubVal.new(8),
|
231
|
+
Mod::StringSubVal.new("seven"),
|
232
|
+
Mod::DateSubVal.new(2008,4,29), Mod::DateTimeSubVal.new(2008,4,30,10,28,16),
|
233
|
+
Mod::DecimalSubVal.new('98765432109876543210'),
|
234
234
|
]
|
235
235
|
end
|
236
236
|
|
@@ -308,7 +308,7 @@ describe "An instance of every type of ObjectType" do
|
|
308
308
|
|
309
309
|
it "should disallow treating an unresolved AutoCounter as an integer" do
|
310
310
|
c = ActiveFacts::API::Constellation.new(Mod)
|
311
|
-
a = c.
|
311
|
+
a = c.AutoCounterVal(:new)
|
312
312
|
lambda {
|
313
313
|
b = 2 + a
|
314
314
|
}.should raise_error
|
@@ -322,7 +322,7 @@ describe "An instance of every type of ObjectType" do
|
|
322
322
|
it "should complain when not enough identifying values are provided for an entity" do
|
323
323
|
c = ActiveFacts::API::Constellation.new(Mod)
|
324
324
|
lambda {
|
325
|
-
c.TestByInt(:
|
325
|
+
c.TestByInt(:int_val => nil)
|
326
326
|
}.should raise_error
|
327
327
|
end
|
328
328
|
|
@@ -333,6 +333,13 @@ describe "An instance of every type of ObjectType" do
|
|
333
333
|
}.should raise_error
|
334
334
|
end
|
335
335
|
|
336
|
+
it "should complain when wrong type is used for an entity" do
|
337
|
+
c = ActiveFacts::API::Constellation.new(Mod)
|
338
|
+
lambda {
|
339
|
+
c.TestByInt("Not an Int")
|
340
|
+
}.should raise_error
|
341
|
+
end
|
342
|
+
|
336
343
|
it "should handle a non-mandatory missing identifying role" do
|
337
344
|
module Mod2
|
338
345
|
class Word
|
@@ -380,5 +387,4 @@ describe "An instance of every type of ObjectType" do
|
|
380
387
|
f.is_ok.should == false
|
381
388
|
s.is_ok.should == true
|
382
389
|
end
|
383
|
-
|
384
390
|
end
|
@@ -2,8 +2,6 @@
|
|
2
2
|
# ActiveFacts tests: Value instances 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
|
VALUE_TYPES = Int, Real, AutoCounter, String, Date, DateTime, Decimal
|
9
7
|
RAW_VALUES = [2, 3.0, 4, "5", Date.new(2008, 04, 20), DateTime.new(2008, 04, 20, 10, 28, 14)]
|
@@ -22,20 +20,20 @@ module TestValueTypesModule
|
|
22
20
|
value_type
|
23
21
|
end
|
24
22
|
BASE_VALUE_TYPE_ROLE_NAMES = VALUE_TYPES.map { |base_type| base_type.name.snakecase }
|
25
|
-
VALUE_TYPE_ROLE_NAMES = BASE_VALUE_TYPE_ROLE_NAMES.map { |n| [ :"#{n}
|
23
|
+
VALUE_TYPE_ROLE_NAMES = BASE_VALUE_TYPE_ROLE_NAMES.map { |n| [ :"#{n}_val", :"#{n}_sub_val" ] }.flatten
|
26
24
|
VALUE_TYPES.map do |value_type|
|
27
25
|
code = <<-END
|
28
|
-
class #{value_type.name}
|
26
|
+
class #{value_type.name}Val < #{value_type.name}
|
29
27
|
value_type
|
30
28
|
end
|
31
29
|
|
32
|
-
class #{value_type.name}
|
30
|
+
class #{value_type.name}ValSub < #{value_type.name}Val
|
33
31
|
# Note no new "value_type" is required here, it comes through inheritance
|
34
32
|
end
|
35
33
|
|
36
34
|
class #{value_type.name}Entity
|
37
|
-
identified_by :#{identifying_role_name = "id_#{value_type.name.snakecase}
|
38
|
-
|
35
|
+
identified_by :#{identifying_role_name = "id_#{value_type.name.snakecase}_val"}
|
36
|
+
one_to_one :#{identifying_role_name}, :class => #{value_type.name}Val
|
39
37
|
end
|
40
38
|
|
41
39
|
class #{value_type.name}EntitySub < #{value_type.name}Entity
|
@@ -43,13 +41,13 @@ module TestValueTypesModule
|
|
43
41
|
|
44
42
|
class #{value_type.name}EntitySubCtr < #{value_type.name}Entity
|
45
43
|
identified_by :counter
|
46
|
-
|
44
|
+
one_to_one :counter, :class => "ESCID"
|
47
45
|
end
|
48
46
|
|
49
|
-
VALUE_SUB_FOR_VALUE[#{value_type.name}
|
47
|
+
VALUE_SUB_FOR_VALUE[#{value_type.name}Val] = #{value_type.name}ValSub
|
50
48
|
classes = [
|
51
|
-
#{value_type.name}
|
52
|
-
#{value_type.name}
|
49
|
+
#{value_type.name}Val,
|
50
|
+
#{value_type.name}ValSub,
|
53
51
|
#{value_type.name}Entity,
|
54
52
|
#{value_type.name}EntitySub,
|
55
53
|
#{value_type.name}EntitySubCtr,
|
@@ -57,13 +55,13 @@ module TestValueTypesModule
|
|
57
55
|
OBJECT_TYPES.concat(classes)
|
58
56
|
classes.each { |klass| VALUE_TYPE_FOR_OBJECT_TYPE[klass] = value_type }
|
59
57
|
END
|
60
|
-
|
58
|
+
TestValueTypesModule.module_eval code
|
61
59
|
end
|
62
60
|
OBJECT_TYPE_NAMES = OBJECT_TYPES.map{|object_type| object_type.basename}
|
63
61
|
|
64
62
|
class Octopus
|
65
63
|
identified_by :zero
|
66
|
-
|
64
|
+
one_to_one :zero, :class => IntVal
|
67
65
|
maybe :has_a_unary
|
68
66
|
OBJECT_TYPE_NAMES.each do |object_type_name|
|
69
67
|
has_one object_type_name.snakecase.to_sym
|
@@ -94,7 +92,7 @@ end
|
|
94
92
|
describe "Object type role values" do
|
95
93
|
def object_identifying_parameters object_type_name, value
|
96
94
|
if object_type_name =~ /^(.*)EntitySubCtr$/
|
97
|
-
[{ :"id_#{$1.snakecase}
|
95
|
+
[{ :"id_#{$1.snakecase}_val" => value, :counter => :new}]
|
98
96
|
else
|
99
97
|
[value]
|
100
98
|
end
|
@@ -110,7 +108,7 @@ describe "Object type role values" do
|
|
110
108
|
it "should allow instantiation of a bare #{object_type_name}" do
|
111
109
|
object_identifying_parameters =
|
112
110
|
if object_type_name =~ /^(.*)EntitySubCtr$/
|
113
|
-
[{ :"id_#{$1.snakecase}
|
111
|
+
[{ :"id_#{$1.snakecase}_val" => values[0], :counter => :new}]
|
114
112
|
else
|
115
113
|
[values[0]]
|
116
114
|
end
|
@@ -275,7 +273,7 @@ describe "Object type role values" do
|
|
275
273
|
reflection = assigned.send(role.counterpart.name)
|
276
274
|
reflection.should_not be_empty
|
277
275
|
reflection.size.should == 1
|
278
|
-
reflection.should
|
276
|
+
reflection.should include @object
|
279
277
|
end
|
280
278
|
|
281
279
|
# Update the role to the second value:
|
@@ -299,7 +297,7 @@ describe "Object type role values" do
|
|
299
297
|
# The counterpart should include us in its RoleValues
|
300
298
|
reflection2 = assigned2.send(role.counterpart.name)
|
301
299
|
reflection2.size.should == 1
|
302
|
-
reflection2.should
|
300
|
+
reflection2.should include @object
|
303
301
|
end
|
304
302
|
|
305
303
|
# Nullify the role
|
@@ -388,12 +386,23 @@ describe "Object type role values" do
|
|
388
386
|
|
389
387
|
it "should support each" do
|
390
388
|
count = 0
|
391
|
-
@role_values.each
|
389
|
+
@role_values.each do |v, *a|
|
390
|
+
a.size.should == 0
|
391
|
+
v.should_not be_nil
|
392
|
+
count += 1
|
393
|
+
end
|
392
394
|
count.should == 1
|
393
395
|
end
|
394
396
|
|
395
397
|
it "should support detect" do
|
396
|
-
|
398
|
+
count = 0
|
399
|
+
@role_values.detect do |v, *a|
|
400
|
+
a.size.should == 0
|
401
|
+
v.should_not be_nil
|
402
|
+
count += 1
|
403
|
+
false
|
404
|
+
end
|
405
|
+
count.should == 1
|
397
406
|
end
|
398
407
|
|
399
408
|
it "should verbalise" do
|
@@ -2,19 +2,21 @@
|
|
2
2
|
# ActiveFacts tests: Roles of object_type 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 "Roles" do
|
9
7
|
before :each do
|
10
8
|
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
11
9
|
module Mod
|
12
10
|
class Name < String
|
13
|
-
value_type :length => 40, :scale => 0, :restrict => /^[A-Z][a-
|
11
|
+
value_type :length => 40, :scale => 0, :restrict => /^[A-Z][a-z0-9]*/
|
12
|
+
end
|
13
|
+
class Identifier
|
14
|
+
identified_by :name
|
15
|
+
one_to_one :name
|
14
16
|
end
|
15
17
|
class LegalEntity
|
16
18
|
identified_by :name
|
17
|
-
|
19
|
+
one_to_one :name
|
18
20
|
end
|
19
21
|
class Contract
|
20
22
|
identified_by :first, :second
|
@@ -30,6 +32,11 @@ describe "Roles" do
|
|
30
32
|
alias :given= :name=
|
31
33
|
has_one :related_to, :class => LegalEntity
|
32
34
|
end
|
35
|
+
class Employee
|
36
|
+
identified_by :name
|
37
|
+
one_to_one :identifier
|
38
|
+
one_to_one :name
|
39
|
+
end
|
33
40
|
end
|
34
41
|
# print "object_type: "; p Mod.object_type
|
35
42
|
end
|
@@ -116,10 +123,10 @@ describe "Roles" do
|
|
116
123
|
le = Mod::LegalEntity.new(foo)
|
117
124
|
le.respond_to?(:name).should be_true
|
118
125
|
name = le.name
|
119
|
-
name.respond_to?(:
|
126
|
+
name.respond_to?(:legal_entity).should be_true
|
120
127
|
|
121
128
|
#pending
|
122
|
-
|
129
|
+
[name.legal_entity].should === [le]
|
123
130
|
end
|
124
131
|
|
125
132
|
it "should instantiate subclasses sensibly" do
|
@@ -127,7 +134,7 @@ describe "Roles" do
|
|
127
134
|
bloggs = c.LegalEntity("Bloggs & Co")
|
128
135
|
p = c.Person("Fred", "Bloggs")
|
129
136
|
p.related_to = "Bloggs & Co"
|
130
|
-
p.related_to.should
|
137
|
+
p.related_to.should be_an_instance_of Mod::LegalEntity
|
131
138
|
p.related_to.should == bloggs
|
132
139
|
|
133
140
|
# REVISIT: The raw instance doesn't override == to compare itself to a RoleProxy unfortunately...
|
@@ -136,28 +143,55 @@ describe "Roles" do
|
|
136
143
|
end
|
137
144
|
|
138
145
|
it "should forward missing methods on the role proxies" do
|
146
|
+
c = ActiveFacts::API::Constellation.new(Mod)
|
147
|
+
p = c.Person("Fred", "Bloggs")
|
148
|
+
lambda {p.family.foo}.should raise_error(NoMethodError)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should forward re-raise exceptions from missing methods on the role proxies" do
|
139
152
|
c = ActiveFacts::API::Constellation.new(Mod)
|
140
153
|
p = c.Person("Fred", "Bloggs")
|
154
|
+
class String
|
155
|
+
def foo
|
156
|
+
raise "Yawning"
|
157
|
+
end
|
158
|
+
end
|
141
159
|
|
142
|
-
|
143
|
-
lambda {
|
144
|
-
p.family.foo
|
145
|
-
}.should raise_error(NoMethodError)
|
160
|
+
lambda {p.family.foo}.should raise_error(RuntimeError)
|
146
161
|
end
|
147
162
|
|
148
|
-
it "should
|
163
|
+
it "should keep a trace of the overwritten class when changing identification" do
|
164
|
+
pending
|
149
165
|
c = ActiveFacts::API::Constellation.new(Mod)
|
150
|
-
|
166
|
+
e = c.Employee(:identifier => "Project2501")
|
167
|
+
e.overrides_identification_of.is_a?(Mod::LegalEntity).should be_true
|
168
|
+
end
|
151
169
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
#end
|
156
|
-
lambda {
|
157
|
-
p.family.barf
|
158
|
-
#}.should raise_error(RuntimeError)
|
159
|
-
}.should raise_error(NoMethodError)
|
170
|
+
it "should be able to import an entity from another constellation" do
|
171
|
+
c1 = ActiveFacts::API::Constellation.new(Mod)
|
172
|
+
c2 = ActiveFacts::API::Constellation.new(Mod)
|
160
173
|
|
174
|
+
e = c1.Employee("PuppetMaster")
|
175
|
+
identifier = c2.Identifier("Project2501", :employee => e)
|
176
|
+
identifier.employee.name.should == "PuppetMaster"
|
161
177
|
end
|
162
178
|
|
179
|
+
it "should be able to import an entity from another constellation which subclass another entity" do
|
180
|
+
pending "fails because identify_role_values get only the current class identifying roles" do
|
181
|
+
# in this example, it returns :identifier, but not :name from LegalEntity
|
182
|
+
module Mod
|
183
|
+
class Person2 < LegalEntity
|
184
|
+
identified_by :identifier
|
185
|
+
one_to_one :identifier
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
c1 = ActiveFacts::API::Constellation.new(Mod)
|
190
|
+
c2 = ActiveFacts::API::Constellation.new(Mod)
|
191
|
+
|
192
|
+
p = c1.Person2("Person2Name", :identifier => "Project2501")
|
193
|
+
identifier = c2.Identifier("Project2501", :person2 => p)
|
194
|
+
identifier.person2.name.should == "Person2Name"
|
195
|
+
end
|
196
|
+
end
|
163
197
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'activefacts/api'
|
2
|
+
|
3
|
+
module Tax
|
4
|
+
|
5
|
+
class Name < String
|
6
|
+
value_type
|
7
|
+
end
|
8
|
+
|
9
|
+
class Person
|
10
|
+
identified_by :name
|
11
|
+
one_to_one :name
|
12
|
+
end
|
13
|
+
|
14
|
+
class Australian < Person
|
15
|
+
end
|
16
|
+
|
17
|
+
class TaxPayer < Person
|
18
|
+
end
|
19
|
+
|
20
|
+
class TFN < Int
|
21
|
+
value_type
|
22
|
+
end
|
23
|
+
|
24
|
+
class AustralianTaxPayer < Australian
|
25
|
+
supertypes TaxPayer
|
26
|
+
identified_by :tfn
|
27
|
+
one_to_one :tfn, :class => TFN # Capitalisation rules!
|
28
|
+
end
|
29
|
+
|
30
|
+
class YearNr < Int
|
31
|
+
value_type
|
32
|
+
end
|
33
|
+
|
34
|
+
class Year
|
35
|
+
identified_by :year_nr
|
36
|
+
one_to_one :year_nr
|
37
|
+
end
|
38
|
+
|
39
|
+
class AustralianTaxReturn
|
40
|
+
identified_by :australian_tax_payer, :year
|
41
|
+
has_one :australian_tax_payer
|
42
|
+
has_one :year
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|