activefacts-api 0.9.9 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/TODO +1 -39
- data/VERSION +1 -1
- data/activefacts-api.gemspec +4 -4
- data/lib/activefacts/api/constellation.rb +23 -16
- data/lib/activefacts/api/entity.rb +13 -14
- data/lib/activefacts/api/fact_type.rb +23 -1
- data/lib/activefacts/api/instance.rb +13 -9
- data/lib/activefacts/api/object_type.rb +46 -26
- data/lib/activefacts/api/role.rb +3 -3
- data/lib/activefacts/api/role_values.rb +32 -14
- data/lib/activefacts/api/value.rb +2 -4
- data/lib/activefacts/api/vocabulary.rb +1 -1
- data/spec/constellation/constellation_spec.rb +1 -1
- data/spec/constellation/instance_index_spec.rb +8 -7
- data/spec/constellation/instance_spec.rb +2 -8
- data/spec/fact_type/role_values_spec.rb +4 -4
- data/spec/fact_type/roles_spec.rb +48 -9
- data/spec/identification_scheme/identification_spec.rb +17 -14
- data/spec/metadata_spec.rb +2 -5
- data/spec/object_type/entity_type/entity_type_spec.rb +8 -8
- data/spec/object_type/entity_type/multipart_identification_spec.rb +18 -13
- data/spec/object_type/value_type/value_type_spec.rb +25 -13
- metadata +18 -10
data/lib/activefacts/api/role.rb
CHANGED
@@ -22,14 +22,15 @@ module ActiveFacts
|
|
22
22
|
attr_reader :value_constraint # Counterpart Instances playing this role must meet this constraint
|
23
23
|
attr_reader :is_identifying # Is this an identifying role for object_type?
|
24
24
|
|
25
|
-
def initialize(fact_type, object_type,
|
25
|
+
def initialize(fact_type, object_type, role_name, mandatory, unique)
|
26
26
|
@fact_type = fact_type
|
27
27
|
@fact_type.all_role << self
|
28
28
|
@object_type = object_type
|
29
|
-
@name =
|
29
|
+
@name = role_name
|
30
30
|
@mandatory = mandatory
|
31
31
|
@unique = unique
|
32
32
|
@is_identifying = @object_type.is_entity_type && @object_type.identifying_role_names.include?(@name)
|
33
|
+
object_type.add_role(self)
|
33
34
|
associate_role(@object_type)
|
34
35
|
end
|
35
36
|
|
@@ -87,7 +88,6 @@ module ActiveFacts
|
|
87
88
|
end
|
88
89
|
|
89
90
|
# Every ObjectType has a Role collection
|
90
|
-
# REVISIT: You can enumerate the object_type's own roles, or inherited roles as well.
|
91
91
|
class RoleCollection < Hash #:nodoc:
|
92
92
|
def verbalise
|
93
93
|
keys.sort_by(&:to_s).inspect
|
@@ -8,11 +8,15 @@ module ActiveFacts
|
|
8
8
|
module API
|
9
9
|
|
10
10
|
class RoleValues #:nodoc:
|
11
|
+
attr_accessor :object_type
|
11
12
|
attr_accessor :sort
|
13
|
+
attr_accessor :index_roles
|
12
14
|
|
13
|
-
def initialize sort =
|
14
|
-
@
|
15
|
+
def initialize object_type, index_roles = nil, sort = nil
|
16
|
+
@object_type = object_type
|
17
|
+
@sort = sort == nil ? API::sorted : !!sort
|
15
18
|
@a = @sort ? RBTree.new : []
|
19
|
+
@index_roles = index_roles
|
16
20
|
end
|
17
21
|
|
18
22
|
def +(a)
|
@@ -23,6 +27,17 @@ module ActiveFacts
|
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
30
|
+
def [](*a)
|
31
|
+
if @sort
|
32
|
+
# REVISIT: Consider whether to return an array when a partial key is provided.
|
33
|
+
key = form_key(Array(a))
|
34
|
+
@a[key]
|
35
|
+
else
|
36
|
+
# Slow: Search the array for an element having the matching key:
|
37
|
+
@a.detect{|e| index_values(e) == a}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
26
41
|
def to_a
|
27
42
|
@sort ? @a.values : @a
|
28
43
|
end
|
@@ -36,12 +51,24 @@ module ActiveFacts
|
|
36
51
|
end
|
37
52
|
|
38
53
|
def form_key a
|
39
|
-
|
54
|
+
a = Array(a)
|
55
|
+
if @index_roles && @index_roles.size != a.size
|
56
|
+
raise "Incorrectly-sized key #{a.inspect}. Index roles are #{@index_roles.map(&:name).inspect}"
|
57
|
+
end
|
58
|
+
KeyArray.new(a)
|
59
|
+
end
|
60
|
+
|
61
|
+
def index_values object
|
62
|
+
if @index_roles
|
63
|
+
@index_roles.map{|r| object.send(r.name).identifying_role_values}
|
64
|
+
else
|
65
|
+
object.identifying_role_values
|
66
|
+
end
|
40
67
|
end
|
41
68
|
|
42
69
|
def add_instance(value, key)
|
43
70
|
if @sort
|
44
|
-
@a[form_key(
|
71
|
+
@a[form_key(index_values(value))] = value
|
45
72
|
else
|
46
73
|
@a << value
|
47
74
|
end
|
@@ -51,17 +78,8 @@ module ActiveFacts
|
|
51
78
|
if @sort
|
52
79
|
deleted = @a.delete(form_key(key))
|
53
80
|
else
|
54
|
-
deleted = @a.delete(value)
|
81
|
+
deleted = @a.delete(value) # Slow: it has to search the array
|
55
82
|
end
|
56
|
-
|
57
|
-
# Test code:
|
58
|
-
unless deleted
|
59
|
-
p @a
|
60
|
-
p value
|
61
|
-
debugger
|
62
|
-
true
|
63
|
-
end
|
64
|
-
|
65
83
|
end
|
66
84
|
|
67
85
|
def verbalise
|
@@ -37,7 +37,6 @@ module ActiveFacts
|
|
37
37
|
include Instance::ClassMethods
|
38
38
|
|
39
39
|
def value_type *args, &block #:nodoc:
|
40
|
-
# REVISIT: args could be a hash, with keys :length, :scale, :unit, :allow
|
41
40
|
options = (args[-1].is_a?(Hash) ? args.pop : {})
|
42
41
|
options.each do |key, value|
|
43
42
|
raise UnrecognisedOptionsException.new('ValueType', basename, key) unless respond_to?(key)
|
@@ -67,9 +66,7 @@ module ActiveFacts
|
|
67
66
|
|
68
67
|
# verbalise this ValueType
|
69
68
|
def verbalise
|
70
|
-
#
|
71
|
-
# REVISIT: Set vocabulary name of superclass if not same as this
|
72
|
-
"#{basename} = #{superclass.basename}();"
|
69
|
+
"#{basename} < #{superclass.basename}();"
|
73
70
|
end
|
74
71
|
|
75
72
|
def identifying_role_values(constellation, args) #:nodoc:
|
@@ -129,6 +126,7 @@ module ActiveFacts
|
|
129
126
|
def inherited(other) #:nodoc:
|
130
127
|
# Copy the type parameters here, etc?
|
131
128
|
other.send :realise_supertypes, self
|
129
|
+
TypeInheritanceFactType.new(self, other)
|
132
130
|
vocabulary.__add_object_type(other)
|
133
131
|
super
|
134
132
|
end
|
@@ -58,7 +58,7 @@ module ActiveFacts
|
|
58
58
|
@object_type.keys.sort.map do |object_type|
|
59
59
|
c = @object_type[object_type]
|
60
60
|
__bind(c.basename)
|
61
|
-
c.verbalise + "\n\t\t// Roles played: " + c.
|
61
|
+
c.verbalise + "\n\t\t// Roles played: " + c.all_role.verbalise
|
62
62
|
end.
|
63
63
|
join("\n\t")
|
64
64
|
end
|
@@ -465,7 +465,7 @@ describe "A Constellation instance" do
|
|
465
465
|
end
|
466
466
|
end
|
467
467
|
c = @constellation.ListedCompany("foo", :auto_counter_val => 23)
|
468
|
-
}.should_not raise_error
|
468
|
+
}.should_not raise_error
|
469
469
|
end
|
470
470
|
|
471
471
|
it "should be able to attach a new supertype on an entity type to make it a (sub-)subtype" do
|
@@ -21,11 +21,12 @@ describe ActiveFacts::API::InstanceIndex do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
class EntityB < EntityA
|
24
|
-
identified_by :
|
25
|
-
one_to_one :
|
24
|
+
identified_by :value_c
|
25
|
+
one_to_one :value_c, :class => ValueB
|
26
26
|
end
|
27
27
|
|
28
28
|
class EntityD < EntityA
|
29
|
+
has_one :value_d, :class => ValueB
|
29
30
|
end
|
30
31
|
|
31
32
|
class EntityC < EntityB
|
@@ -35,8 +36,8 @@ describe ActiveFacts::API::InstanceIndex do
|
|
35
36
|
|
36
37
|
@constellation = ActiveFacts::API::Constellation.new(Mod)
|
37
38
|
@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 => '
|
39
|
+
@b = @constellation.EntityB(:value_a => 12, :value_b => 'ab', :value_c => 'abc')
|
40
|
+
@c = @constellation.EntityC(:value_a => 123, :value_b => 'abc1', :value_c => 'abc2', :value_d => 'abcd')
|
40
41
|
end
|
41
42
|
|
42
43
|
it "should index an instance under its own class" do
|
@@ -55,12 +56,12 @@ describe ActiveFacts::API::InstanceIndex do
|
|
55
56
|
end
|
56
57
|
|
57
58
|
it "should recursively try to use identifying role values within an array" do
|
58
|
-
value_b = @constellation.ValueB('
|
59
|
+
value_b = @constellation.ValueB('abc2')
|
59
60
|
@constellation.EntityC[[value_b]].should == @c
|
60
61
|
end
|
61
62
|
|
62
63
|
it "should use the value as-is if it doesn't have identifying role values" do
|
63
|
-
@constellation.EntityC[%w{
|
64
|
+
@constellation.EntityC[%w{abc2}].should == @c
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -79,7 +80,7 @@ describe ActiveFacts::API::InstanceIndex do
|
|
79
80
|
b_index = @constellation.EntityB
|
80
81
|
b_index.size.should == 2
|
81
82
|
b_index.send(api) do |k, v, *a|
|
82
|
-
[['ab'], ['abc']].should include(k)
|
83
|
+
[['ab'], ['abc'], ['abc2']].should include(k)
|
83
84
|
[@b, @c].should include v
|
84
85
|
a.size.should == 0
|
85
86
|
false
|
@@ -3,12 +3,6 @@
|
|
3
3
|
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
4
|
#
|
5
5
|
|
6
|
-
#require 'ruby-debug'; Debugger.start
|
7
|
-
#trap "INT" do
|
8
|
-
# puts caller*"\n\t"
|
9
|
-
# debugger
|
10
|
-
#end
|
11
|
-
|
12
6
|
describe "An instance of every type of ObjectType" do
|
13
7
|
before :all do
|
14
8
|
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
@@ -302,7 +296,7 @@ describe "An instance of every type of ObjectType" do
|
|
302
296
|
# All identifying roles should be in the verbalisation.
|
303
297
|
# Strictly this should be the role name, but we don't set names here.
|
304
298
|
entity_type.identifying_role_names.each do |ir|
|
305
|
-
role = entity_type.
|
299
|
+
role = entity_type.all_role(ir)
|
306
300
|
role.should_not be_nil
|
307
301
|
counterpart_object_type = role.counterpart.object_type
|
308
302
|
verbalisation.should =~ %r{\b#{counterpart_object_type.basename}\b}
|
@@ -336,7 +330,7 @@ describe "An instance of every type of ObjectType" do
|
|
336
330
|
verbalisation = entity.verbalise
|
337
331
|
verbalisation.should =~ %r{\b#{entity.class.basename}\b}
|
338
332
|
entity.class.identifying_role_names.each do |ir|
|
339
|
-
role = entity.class.
|
333
|
+
role = entity.class.all_role(ir)
|
340
334
|
role.should_not be_nil
|
341
335
|
counterpart_object_type = role.counterpart.object_type
|
342
336
|
verbalisation.should =~ %r{\b#{counterpart_object_type.basename}\b}
|
@@ -82,7 +82,7 @@ end
|
|
82
82
|
describe "Roles of an Object Type" do
|
83
83
|
|
84
84
|
it "should return a roles collection" do
|
85
|
-
roles = TestValueTypesModule::Octopus.
|
85
|
+
roles = TestValueTypesModule::Octopus.all_role
|
86
86
|
roles.should_not be_nil
|
87
87
|
roles.size.should == 2+VALUE_TYPES.size*5*2
|
88
88
|
|
@@ -215,7 +215,7 @@ describe "Object type role values" do
|
|
215
215
|
octopus = @constellation.Octopus(0)
|
216
216
|
octopus_role_name = :"octopus_as_one_#{object_type_name.snakecase}"
|
217
217
|
object.send(:"#{octopus_role_name}=", octopus)
|
218
|
-
counterpart_name = object.class.
|
218
|
+
counterpart_name = object.class.all_role[octopus_role_name].counterpart.name
|
219
219
|
|
220
220
|
# Create a reference by assigning the object from a RoleProxy:
|
221
221
|
proxy = octopus.send(counterpart_name)
|
@@ -239,7 +239,7 @@ describe "Object type role values" do
|
|
239
239
|
before :each do
|
240
240
|
@constellation = ActiveFacts::API::Constellation.new(TestValueTypesModule)
|
241
241
|
@object = @constellation.Octopus(0)
|
242
|
-
@roles = @object.class.
|
242
|
+
@roles = @object.class.all_role
|
243
243
|
end
|
244
244
|
|
245
245
|
it "should return its constellation and vocabulary" do
|
@@ -249,7 +249,7 @@ describe "Object type role values" do
|
|
249
249
|
@object.class.vocabulary.should == TestValueTypesModule
|
250
250
|
end
|
251
251
|
|
252
|
-
TestValueTypesModule::Octopus.
|
252
|
+
TestValueTypesModule::Octopus.all_role.each do |role_name, role|
|
253
253
|
next if role_name == :zero
|
254
254
|
|
255
255
|
it "should respond to getting its #{role_name} role" do
|
@@ -48,7 +48,7 @@ describe "Roles" do
|
|
48
48
|
has_one :name
|
49
49
|
end
|
50
50
|
end
|
51
|
-
role = Mod::Existing1.
|
51
|
+
role = Mod::Existing1.all_role(:name)
|
52
52
|
role.should_not be_nil
|
53
53
|
role.inspect.class.should == String
|
54
54
|
role.counterpart.object_type.should == Mod::Name
|
@@ -138,10 +138,10 @@ describe "Roles" do
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
# REVISIT: need to make more tests for the class's role accessor methods:
|
141
|
-
Mod::Name.
|
141
|
+
Mod::Name.all_role(:all_existing1).should == Mod::Name.all_existing1_role
|
142
142
|
|
143
|
-
Mod::Name.
|
144
|
-
Mod::LegalEntity.
|
143
|
+
Mod::Name.all_role(:all_existing1).should_not be_nil
|
144
|
+
Mod::LegalEntity.all_role(:all_contract_as_first).should_not be_nil
|
145
145
|
end
|
146
146
|
|
147
147
|
it "should associate a role name with a matching object_type after it's created" do
|
@@ -151,8 +151,8 @@ describe "Roles" do
|
|
151
151
|
has_one :given_name
|
152
152
|
end
|
153
153
|
end
|
154
|
-
# print "Mod::Existing2.
|
155
|
-
r = Mod::Existing2.
|
154
|
+
# print "Mod::Existing2.all_role = "; p Mod::Existing2.all_role
|
155
|
+
r = Mod::Existing2.all_role(:given_name)
|
156
156
|
r.should_not be_nil
|
157
157
|
r.counterpart.should be_nil
|
158
158
|
module Mod
|
@@ -161,7 +161,7 @@ describe "Roles" do
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
# puts "Should resolve now:"
|
164
|
-
r = Mod::Existing2.
|
164
|
+
r = Mod::Existing2.all_role(:given_name)
|
165
165
|
r.should_not be_nil
|
166
166
|
r.counterpart.object_type.should == Mod::GivenName
|
167
167
|
end
|
@@ -173,10 +173,10 @@ describe "Roles" do
|
|
173
173
|
one_to_one :patriarch, :class => Person
|
174
174
|
end
|
175
175
|
end
|
176
|
-
r = Mod::FamilyName.
|
176
|
+
r = Mod::FamilyName.all_role(:patriarch)
|
177
177
|
r.should_not be_nil
|
178
178
|
r.counterpart.object_type.should == Mod::Person
|
179
|
-
r.counterpart.object_type.
|
179
|
+
r.counterpart.object_type.all_role(:family_name_as_patriarch).counterpart.object_type.should == Mod::FamilyName
|
180
180
|
end
|
181
181
|
|
182
182
|
it "should instantiate the matching object_type on assignment" do
|
@@ -241,4 +241,43 @@ describe "Roles" do
|
|
241
241
|
identifier.employee.name.should == "PuppetMaster"
|
242
242
|
end
|
243
243
|
|
244
|
+
it "should create TypeInheritance fact type and roles" do
|
245
|
+
module Mod
|
246
|
+
class GivenName < Name
|
247
|
+
end
|
248
|
+
class Document
|
249
|
+
identified_by :name
|
250
|
+
one_to_one :name
|
251
|
+
end
|
252
|
+
class Contract
|
253
|
+
supertypes Document
|
254
|
+
end
|
255
|
+
end
|
256
|
+
[Mod::GivenName, Mod::Person, Mod::Contract].each do |subtype|
|
257
|
+
subtype.supertypes.each do |supertype|
|
258
|
+
# Get the role names:
|
259
|
+
supertype_role_name = supertype.name.gsub(/.*::/,'').to_sym
|
260
|
+
subtype_role_name = subtype.name.gsub(/.*::/,'').to_sym
|
261
|
+
|
262
|
+
# Check that the roles are indexed:
|
263
|
+
subtype.all_role.should include(supertype_role_name)
|
264
|
+
supertype.all_role.should include(subtype_role_name)
|
265
|
+
|
266
|
+
# Get the role objects:
|
267
|
+
supertype_role = subtype.all_role[supertype_role_name]
|
268
|
+
subtype_role = supertype.all_role[subtype_role_name]
|
269
|
+
|
270
|
+
# Check uniqueness and mandatory:
|
271
|
+
supertype_role.unique.should be_true
|
272
|
+
subtype_role.unique.should be_true
|
273
|
+
supertype_role.mandatory.should be_true
|
274
|
+
subtype_role.mandatory.should be_false
|
275
|
+
|
276
|
+
# Check they belong to the same TypeInheritanceFactType:
|
277
|
+
subtype_role.fact_type.class.should be(ActiveFacts::API::TypeInheritanceFactType)
|
278
|
+
subtype_role.fact_type.should == supertype_role.fact_type
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
244
283
|
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
describe "An Entity Type" do
|
7
7
|
before :all do
|
8
|
-
module
|
8
|
+
module ModIS
|
9
9
|
class Name < String
|
10
10
|
value_type
|
11
11
|
end
|
@@ -16,12 +16,12 @@ describe "An Entity Type" do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
before :each do
|
19
|
-
@c = ActiveFacts::API::Constellation.new(
|
19
|
+
@c = ActiveFacts::API::Constellation.new(ModIS)
|
20
20
|
end
|
21
21
|
|
22
22
|
describe "whose instances are identified by a single value role" do
|
23
23
|
before :all do
|
24
|
-
module
|
24
|
+
module ModIS
|
25
25
|
class Business
|
26
26
|
identified_by :name
|
27
27
|
one_to_one :name
|
@@ -31,7 +31,7 @@ describe "An Entity Type" do
|
|
31
31
|
|
32
32
|
it "should fail if the role isn't one-to-one" do
|
33
33
|
proc do
|
34
|
-
module
|
34
|
+
module ModIS
|
35
35
|
class Cat
|
36
36
|
identified_by :name
|
37
37
|
has_one :name
|
@@ -48,11 +48,11 @@ describe "An Entity Type" do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should return a new instance if not previously present" do
|
51
|
-
@bus.should be_a(
|
51
|
+
@bus.should be_a(ModIS::Business)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should assert the identifying value" do
|
55
|
-
@acme.should be_a(
|
55
|
+
@acme.should be_a(ModIS::Name)
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should be found in the constellation using the value" do
|
@@ -97,7 +97,7 @@ describe "An Entity Type" do
|
|
97
97
|
end
|
98
98
|
|
99
99
|
it "should assert the new identifier" do
|
100
|
-
@c.Name['Bloggs'].should be_a(
|
100
|
+
@c.Name['Bloggs'].should be_a(ModIS::Name)
|
101
101
|
end
|
102
102
|
|
103
103
|
it "should allow the change" do
|
@@ -168,7 +168,7 @@ describe "An Entity Type" do
|
|
168
168
|
|
169
169
|
describe "and the identifying value plays other roles" do
|
170
170
|
before :all do
|
171
|
-
module
|
171
|
+
module ModIS
|
172
172
|
class Dog
|
173
173
|
identified_by :name
|
174
174
|
one_to_one :name
|
@@ -191,7 +191,7 @@ describe "An Entity Type" do
|
|
191
191
|
|
192
192
|
describe "identified by two values" do
|
193
193
|
before :all do
|
194
|
-
module
|
194
|
+
module ModIS
|
195
195
|
class Building
|
196
196
|
identified_by :name
|
197
197
|
one_to_one :name
|
@@ -222,12 +222,12 @@ describe "An Entity Type" do
|
|
222
222
|
end
|
223
223
|
|
224
224
|
before :each do
|
225
|
-
@c = ActiveFacts::API::Constellation.new(
|
225
|
+
@c = ActiveFacts::API::Constellation.new(ModIS)
|
226
226
|
end
|
227
227
|
|
228
228
|
it "should fail if any role is one-to-one" do
|
229
229
|
proc do
|
230
|
-
module
|
230
|
+
module ModIS
|
231
231
|
class Floor
|
232
232
|
identified_by :building, :number
|
233
233
|
has_one :building
|
@@ -249,11 +249,11 @@ describe "An Entity Type" do
|
|
249
249
|
end
|
250
250
|
|
251
251
|
it "should return a new instance if not previously present" do
|
252
|
-
@r.should be_a(
|
252
|
+
@r.should be_a(ModIS::Room)
|
253
253
|
end
|
254
254
|
|
255
255
|
it "should assert the identifying values" do
|
256
|
-
@rn.should be_a(
|
256
|
+
@rn.should be_a(ModIS::Number)
|
257
257
|
@c.Number[@rn.identifying_role_values].should == @rn # Yes
|
258
258
|
@c.Number[101].should == @rn # No
|
259
259
|
@c.Number[101].should be_eql 101 # No
|
@@ -318,6 +318,9 @@ describe "An Entity Type" do
|
|
318
318
|
end
|
319
319
|
|
320
320
|
it "should be found under the new identifier even on deep associations" do
|
321
|
+
# p @c.OwnerRoom.keys[0]
|
322
|
+
# p @new_number
|
323
|
+
# p [@o.identifying_role_values, @r.identifying_role_values]
|
321
324
|
@c.OwnerRoom[[@o.identifying_role_values, @r.identifying_role_values]].should == @or
|
322
325
|
@c.OwnerRoom[[[1_001, ['Mackay']], [['Mackay'], 103]]].should == @or
|
323
326
|
@c.OwnerRoom[[[1_001, ['Mackay']], [['Mackay'], 101]]].should be_nil
|
@@ -378,7 +381,7 @@ describe "An Entity Type" do
|
|
378
381
|
|
379
382
|
describe "which has a supertype that has separate identification" do
|
380
383
|
before :each do
|
381
|
-
module
|
384
|
+
module ModIS
|
382
385
|
class Animal
|
383
386
|
identified_by :number
|
384
387
|
one_to_one :neumber
|