activefacts-api 1.9.5 → 1.9.6
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/lib/activefacts/api/constellation.rb +195 -195
- data/lib/activefacts/api/date.rb +8 -8
- data/lib/activefacts/api/entity.rb +228 -228
- data/lib/activefacts/api/exceptions.rb +13 -13
- data/lib/activefacts/api/fact_type.rb +5 -5
- data/lib/activefacts/api/guid.rb +9 -9
- data/lib/activefacts/api/instance.rb +93 -88
- data/lib/activefacts/api/instance_index.rb +52 -52
- data/lib/activefacts/api/numeric.rb +14 -14
- data/lib/activefacts/api/object_type.rb +231 -231
- data/lib/activefacts/api/role_values.rb +68 -68
- data/lib/activefacts/api/standard_types.rb +1 -1
- data/lib/activefacts/api/version.rb +1 -1
- data/lib/activefacts/api/vocabulary.rb +13 -7
- metadata +1 -1
@@ -98,14 +98,14 @@ module ActiveFacts
|
|
98
98
|
def identifying_role_values(constellation, args)
|
99
99
|
arg_hash = args[-1].is_a?(Hash) ? args.pop : {}
|
100
100
|
n =
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
101
|
+
case
|
102
|
+
when args == [:new] # A new object has no identifying_role_values
|
103
|
+
:new
|
104
|
+
when args.size == 1 && args[0].is_a?(AutoCounter)
|
105
|
+
args[0] # An AutoCounter is its own key
|
106
|
+
else
|
107
|
+
new(*args)
|
108
|
+
end
|
109
109
|
args.replace([arg_hash])
|
110
110
|
n
|
111
111
|
end
|
@@ -125,10 +125,10 @@ class AutoCounter
|
|
125
125
|
@place_holder_number = (@@place_holder+=1)
|
126
126
|
when AutoCounter
|
127
127
|
if i.defined?
|
128
|
-
|
128
|
+
@value = i.to_i
|
129
129
|
else
|
130
|
-
|
131
|
-
|
130
|
+
@place_holder_number = i.place_holder_number
|
131
|
+
@value = nil
|
132
132
|
end
|
133
133
|
else
|
134
134
|
@place_holder_number = @value = i.to_i;
|
@@ -191,12 +191,12 @@ class AutoCounter
|
|
191
191
|
to_s.eql?(o.to_s)
|
192
192
|
end
|
193
193
|
|
194
|
-
def <=>(o)
|
194
|
+
def <=>(o) #:nodoc:
|
195
195
|
if self.defined? && !o == [] && o.defined?
|
196
196
|
if (c = (self.class <=> o.class.name)) != 0
|
197
|
-
|
197
|
+
return c
|
198
198
|
else
|
199
|
-
|
199
|
+
return to_i <=> o.to_i
|
200
200
|
end
|
201
201
|
else
|
202
202
|
to_s.<=>(o.to_s)
|
@@ -50,25 +50,25 @@ module ActiveFacts
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def add_role(role)
|
53
|
-
|
54
|
-
|
53
|
+
all_role[role.name] = role
|
54
|
+
@all_role_transitive = nil # Undo the caching
|
55
55
|
end
|
56
56
|
|
57
57
|
def all_role_transitive
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
return @all_role_transitive if @all_role_transitive
|
59
|
+
@all_role_transitive = all_role.dup
|
60
|
+
supertypes_transitive.each do |klass|
|
61
|
+
@all_role_transitive.merge!(klass.all_role)
|
62
|
+
end
|
63
|
+
@all_role_transitive
|
64
64
|
end
|
65
65
|
|
66
66
|
# Define a unary fact type attached to this object_type; in essence, a boolean attribute.
|
67
67
|
#
|
68
68
|
# Example: maybe :is_ceo
|
69
69
|
def maybe(role_name, options = {})
|
70
|
-
|
71
|
-
|
70
|
+
raise UnrecognisedOptionsException.new("role", role_name, options.keys) unless options.empty?
|
71
|
+
fact_type = FactType.new
|
72
72
|
realise_role(Role.new(fact_type, self, role_name, false, true))
|
73
73
|
end
|
74
74
|
|
@@ -110,11 +110,11 @@ module ActiveFacts
|
|
110
110
|
case type
|
111
111
|
when :has_one
|
112
112
|
if identifying_role_names.size == 1
|
113
|
-
|
113
|
+
raise InvalidIdentificationException.new(self, role, true)
|
114
114
|
end
|
115
115
|
when :one_to_one
|
116
116
|
if identifying_role_names.size > 1
|
117
|
-
|
117
|
+
raise InvalidIdentificationException.new(self, role, false)
|
118
118
|
end
|
119
119
|
end
|
120
120
|
end
|
@@ -127,48 +127,48 @@ module ActiveFacts
|
|
127
127
|
# Without parameters, it returns the array of ObjectType supertypes
|
128
128
|
# (one by Ruby inheritance, any others as defined using this method)
|
129
129
|
def supertypes(*object_types)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
130
|
+
@supertypes ||= []
|
131
|
+
all_supertypes = supertypes_transitive
|
132
|
+
object_types.each do |object_type|
|
133
|
+
next if all_supertypes.include? object_type
|
134
|
+
supertype =
|
135
|
+
case object_type
|
136
|
+
when Class
|
137
|
+
object_type
|
138
|
+
when Symbol
|
139
|
+
# No late binding here:
|
140
|
+
(object_type = vocabulary.const_get(object_type.to_s.camelcase))
|
141
|
+
else
|
142
|
+
raise InvalidSupertypeException.new("Illegal supertype #{object_type.inspect} for #{self.class.basename}")
|
143
|
+
end
|
144
|
+
unless supertype.respond_to?(:vocabulary) and supertype.vocabulary == self.vocabulary
|
145
|
+
raise InvalidSupertypeException.new("#{supertype.name} must be an object type in #{vocabulary.name}")
|
146
|
+
end
|
147
|
+
|
148
|
+
if is_entity_type != supertype.is_entity_type
|
149
|
+
raise InvalidSupertypeException.new("#{self} < #{supertype}: A value type may not be a supertype of an entity type, and vice versa")
|
150
|
+
end
|
151
|
+
|
152
|
+
TypeInheritanceFactType.new(supertype, self)
|
153
|
+
@supertypes << supertype
|
154
|
+
|
155
|
+
# Realise the roles (create accessors) of this supertype.
|
156
|
+
realise_supertypes(object_type, all_supertypes)
|
157
|
+
end
|
158
|
+
[(superclass.respond_to?(:vocabulary) ? superclass : nil), *@supertypes].compact
|
159
159
|
end
|
160
160
|
|
161
161
|
# Return the array of all ObjectType supertypes, transitively.
|
162
162
|
def supertypes_transitive
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
163
|
+
supertypes = []
|
164
|
+
v = superclass.respond_to?(:vocabulary) ? superclass.vocabulary : nil
|
165
|
+
supertypes << superclass if v.kind_of?(Module)
|
166
|
+
supertypes += (@supertypes ||= [])
|
167
|
+
sts = supertypes.inject([]) do |a, t|
|
168
|
+
next if a.include?(t)
|
169
|
+
a += [t] + t.supertypes_transitive
|
170
|
+
end.uniq
|
171
|
+
sts # The local variable unconfuses rcov
|
172
172
|
end
|
173
173
|
|
174
174
|
def subtypes
|
@@ -176,7 +176,7 @@ module ActiveFacts
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def subtypes_transitive
|
179
|
-
|
179
|
+
(subtypes+subtypes.map(&:subtypes_transitive)).flatten.uniq
|
180
180
|
end
|
181
181
|
|
182
182
|
# Every new role added or inherited comes through here:
|
@@ -218,210 +218,210 @@ module ActiveFacts
|
|
218
218
|
|
219
219
|
# Shared code for both kinds of binary fact type (has_one and one_to_one)
|
220
220
|
def define_binary_fact_type(one_to_one, role_name, related, mandatory, related_role_name, restrict)
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
221
|
+
if r = all_role_transitive[role_name]
|
222
|
+
# Allow a one-to-one to be defined identically from both ends:
|
223
|
+
if one_to_one and
|
224
|
+
r.unique and
|
225
|
+
!r.unary? and
|
226
|
+
r.object_type == self and # Cannot be an inherited role
|
227
|
+
r.counterpart.unique and
|
228
|
+
related == r.counterpart.object_type
|
229
|
+
# and related_role_name == r.counterpart.name
|
230
|
+
# REVISIT: Cannot add a value constraint here yet
|
231
|
+
r.make_mandatory if mandatory && !r.mandatory # This was impossible
|
232
|
+
return
|
233
|
+
end
|
234
|
+
|
235
|
+
raise DuplicateRoleException.new("#{name} cannot have more than one role named #{role_name}")
|
236
|
+
end
|
237
|
+
fact_type = FactType.new
|
238
238
|
role = Role.new(fact_type, self, role_name, mandatory, true, restrict)
|
239
239
|
|
240
240
|
# There may be a forward reference here where role_name is a Symbol,
|
241
241
|
# and the block runs later when that Symbol is bound to the object_type.
|
242
242
|
when_bound(related, self, role_name, related_role_name) do |target, definer, role_name, related_role_name|
|
243
|
-
|
243
|
+
counterpart = Role.new(fact_type, target, related_role_name, false, one_to_one)
|
244
244
|
realise_role(role)
|
245
245
|
target.realise_role(counterpart)
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
249
249
|
def define_unary_role_accessor(role)
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
250
|
+
define_method role.setter do |value, options = 0|
|
251
|
+
# Normalise the value to be assigned (nil, false, true):
|
252
|
+
value = case value
|
253
|
+
when nil; nil
|
254
|
+
when false; false
|
255
|
+
else true
|
256
|
+
end
|
257
|
+
|
258
|
+
old = instance_variable_get(role.variable)
|
259
|
+
return value if old == value
|
260
|
+
|
261
|
+
if role.is_identifying and (options&CHECKED_IDENTIFYING_ROLE) == 0
|
262
|
+
check_identification_change_legality(role, value)
|
263
|
+
impacts = analyse_impacts(role)
|
264
|
+
end
|
265
|
+
|
266
|
+
instance_variable_set(role.variable, value)
|
267
|
+
|
268
|
+
if impacts
|
269
|
+
@constellation.when_admitted do
|
270
|
+
# REVISIT: Consider whether we want to provide a way to find all instances
|
271
|
+
# playing/not playing this boolean role, analogous to true.all_thing_as_role_name...
|
272
|
+
apply_impacts(impacts) # Propagate dependent key changes
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
unless @constellation.loggers.empty? or options != 0
|
277
|
+
sv = self.identifying_role_values(role.object_type)
|
278
|
+
@constellation.loggers.each{|l| l.call(:assign, role.object_type, role, sv, old, value) }
|
279
|
+
end
|
280
|
+
|
281
|
+
value
|
282
|
+
end
|
283
283
|
define_single_role_getter(role)
|
284
284
|
end
|
285
285
|
|
286
286
|
def define_single_role_getter(role)
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
287
|
+
define_method role.getter do |*a|
|
288
|
+
if a.size > 0
|
289
|
+
raise ArgumentError.new("wrong number of arguments (#{a.size} for 0)")
|
290
|
+
end
|
291
|
+
instance_variable_get(role.variable)
|
292
|
+
end
|
293
293
|
end
|
294
294
|
|
295
295
|
def define_one_to_one_accessor(role)
|
296
296
|
define_single_role_getter(role)
|
297
297
|
|
298
|
-
|
299
|
-
|
300
|
-
|
298
|
+
# What I want is the following, but it doesn't work in Ruby 1.8
|
299
|
+
define_method role.setter do |value, options = 0|
|
300
|
+
role_var = role.variable
|
301
301
|
|
302
|
-
|
303
|
-
|
304
|
-
|
302
|
+
# Get old value, and jump out early if it's unchanged:
|
303
|
+
old = instance_variable_get(role_var)
|
304
|
+
return value if old == value
|
305
305
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
306
|
+
# assert a new instance for the role value if necessary
|
307
|
+
if value and o = role.counterpart.object_type and (!value.is_a?(o) || value.constellation != @constellation)
|
308
|
+
value = @constellation.assert(o, *Array(value))
|
309
|
+
return value if old == value
|
310
|
+
end
|
311
311
|
|
312
|
-
|
313
|
-
|
314
|
-
|
312
|
+
# We're changing this object's key. Check legality and prepare to propagate
|
313
|
+
if role.is_identifying and (options&CHECKED_IDENTIFYING_ROLE) == 0
|
314
|
+
check_identification_change_legality(role, value)
|
315
315
|
|
316
|
-
|
317
|
-
|
318
|
-
|
316
|
+
# puts "Starting to analyse impact of changing 1-1 #{role.inspect} to #{value.inspect}"
|
317
|
+
impacts = analyse_impacts(role)
|
318
|
+
end
|
319
319
|
|
320
|
-
|
320
|
+
instance_variable_set(role_var, value)
|
321
321
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
322
|
+
# Remove self from the old counterpart:
|
323
|
+
if old and (options&SKIP_MUTUAL_PROPAGATION) == 0
|
324
|
+
old.send(role.counterpart.setter, nil, options|SKIP_MUTUAL_PROPAGATION)
|
325
|
+
end
|
326
326
|
|
327
|
-
|
328
|
-
|
329
|
-
|
327
|
+
@constellation.when_admitted do
|
328
|
+
# Assign self to the new counterpart
|
329
|
+
value.send(role.counterpart.setter, self, options) if value && (options&SKIP_MUTUAL_PROPAGATION) == 0
|
330
330
|
|
331
|
-
|
332
|
-
|
331
|
+
apply_impacts(impacts) if impacts # Propagate dependent key changes
|
332
|
+
end
|
333
333
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
334
|
+
unless @constellation.loggers.empty? or options != 0
|
335
|
+
sv = self.identifying_role_values(role.object_type)
|
336
|
+
ov = old.identifying_role_values
|
337
|
+
nv = value.identifying_role_values
|
338
|
+
@constellation.loggers.each{|l| l.call(:assign, role.object_type, role, sv, ov, nv) }
|
339
|
+
end
|
340
340
|
|
341
|
-
|
342
|
-
|
341
|
+
value
|
342
|
+
end
|
343
343
|
end
|
344
344
|
|
345
345
|
def define_one_to_many_accessor(role)
|
346
346
|
define_single_role_getter(role)
|
347
347
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
348
|
+
define_method role.setter do |value, options = 0|
|
349
|
+
role_var = role.variable
|
350
|
+
|
351
|
+
# Get old value, and jump out early if it's unchanged:
|
352
|
+
old = instance_variable_get(role_var)
|
353
|
+
return value if old == value
|
354
|
+
|
355
|
+
# assert a new instance for the role value if necessary
|
356
|
+
if value and o = role.counterpart.object_type and (!value.is_a?(o) || value.constellation != @constellation)
|
357
|
+
value = @constellation.assert(o, *Array(value))
|
358
|
+
return value if old == value # Occurs when another instance having the same value is assigned
|
359
|
+
end
|
360
|
+
|
361
|
+
if role.is_identifying and (options&CHECKED_IDENTIFYING_ROLE) == 0
|
362
|
+
# We're changing this object's key. Check legality and prepare to propagate
|
363
|
+
check_identification_change_legality(role, value)
|
364
|
+
|
365
|
+
# puts "Starting to analyse impact of changing 1-N #{role.inspect} to #{value.inspect}"
|
366
|
+
impacts = analyse_impacts(role)
|
367
|
+
end
|
368
|
+
|
369
|
+
if old and (options&SKIP_MUTUAL_PROPAGATION) == 0
|
370
|
+
old_role_values = old.send(getter = role.counterpart.getter)
|
371
|
+
old_key = old_role_values.index_values(self)
|
372
|
+
end
|
373
|
+
|
374
|
+
instance_variable_set(role_var, value)
|
375
|
+
|
376
|
+
# Remove "self" from the old counterpart:
|
377
|
+
if old_key
|
378
|
+
old_role_values.delete_instance(self, old_key)
|
379
|
+
if (old_role_values.empty? && !old.class.is_entity_type)
|
380
|
+
old.retract if old.plays_no_role
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
@constellation.when_admitted do
|
385
|
+
# Add "self" into the counterpart
|
386
|
+
if value
|
387
|
+
rv = value.send(getter ||= role.counterpart.getter)
|
388
|
+
rv.add_instance(self, identifying_role_values(role.object_type))
|
389
|
+
end
|
390
|
+
|
391
|
+
apply_impacts(impacts) if impacts # Propagate dependent key changes
|
392
|
+
end
|
393
|
+
|
394
|
+
unless @constellation.loggers.empty? or options != 0
|
395
|
+
sv = self.identifying_role_values(role.object_type)
|
396
|
+
ov = old.identifying_role_values
|
397
|
+
nv = value.identifying_role_values
|
398
|
+
@constellation.loggers.each{|l| l.call(:assign, role.object_type, role, sv, ov, nv) }
|
399
|
+
end
|
400
|
+
|
401
|
+
value
|
402
|
+
end
|
403
403
|
end
|
404
404
|
|
405
405
|
def define_many_to_one_accessor(role)
|
406
406
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
407
|
+
define_method role.getter do |*keys|
|
408
|
+
role_var = role.variable
|
409
|
+
role_values =
|
410
|
+
instance_variable_get(role_var) || begin
|
411
|
+
|
412
|
+
# Decide which roles this index will use (exclude the counterpart role from the id)
|
413
|
+
if role.counterpart and
|
414
|
+
counterpart = role.counterpart.object_type and
|
415
|
+
counterpart.is_entity_type
|
416
|
+
excluded_role = counterpart.identifying_roles.index(role.counterpart)
|
417
|
+
else
|
418
|
+
index_roles = nil
|
419
|
+
end
|
420
|
+
|
421
|
+
instance_variable_set(role_var, RoleValues.new(role.counterpart, excluded_role))
|
422
|
+
end
|
423
|
+
# Look up a value by the key provided, or return the whole collection
|
424
|
+
keys.size == 0 ? role_values : role_values.[](*keys)
|
425
425
|
end
|
426
426
|
end
|
427
427
|
|
@@ -455,13 +455,13 @@ module ActiveFacts
|
|
455
455
|
# The counterpart class (type) might be forward-referenced, so handle a Symbol/String instead of a Class.
|
456
456
|
specified_class = options.delete(:class)
|
457
457
|
case specified_class
|
458
|
-
when Class
|
458
|
+
when Class # Preferred and most common case
|
459
459
|
counterpart_type_or_name = specified_class
|
460
460
|
counterpart_type_default_role_name = specified_class.basename.to_s.snakecase
|
461
|
-
when Symbol, String
|
461
|
+
when Symbol, String # Use this to handle forward references
|
462
462
|
counterpart_type_or_name = specified_class.to_s.camelcase
|
463
463
|
counterpart_type_default_role_name = specified_class.to_s.snakecase
|
464
|
-
when nil
|
464
|
+
when nil # No :class provided, assume it matches the role_name
|
465
465
|
counterpart_type_or_name = role_name.to_s.camelcase
|
466
466
|
counterpart_type_default_role_name = role_name.to_s
|
467
467
|
else
|
@@ -470,11 +470,11 @@ module ActiveFacts
|
|
470
470
|
|
471
471
|
# resolve the Symbol or String to a Class now if possible:
|
472
472
|
unless counterpart_type_or_name.is_a?(Class)
|
473
|
-
|
474
|
-
|
475
|
-
|
473
|
+
resolved = vocabulary.object_type(counterpart_type_or_name)
|
474
|
+
counterpart_type_or_name = resolved if resolved
|
475
|
+
end
|
476
476
|
|
477
|
-
|
477
|
+
# If the role is played by a known Class, check it's in the same vocabulary:
|
478
478
|
if counterpart_type_or_name.is_a?(Class)
|
479
479
|
unless counterpart_type_or_name.respond_to?(:vocabulary) and counterpart_type_or_name.vocabulary == self.vocabulary
|
480
480
|
raise CrossVocabularyRoleException.new(counterpart_type_or_name, vocabulary)
|
@@ -491,15 +491,15 @@ module ActiveFacts
|
|
491
491
|
default_role_name = self.basename.snakecase # Default name of counterpart role (played by self)
|
492
492
|
counterpart_role_name = options.delete(:counterpart)
|
493
493
|
counterpart_role_name = counterpart_role_name.to_s if counterpart_role_name
|
494
|
-
|
494
|
+
counterpart_role_name ||= default_role_name
|
495
495
|
|
496
|
-
|
496
|
+
raise UnrecognisedOptionsException.new("role", role_name, options.keys) unless options.empty?
|
497
497
|
|
498
498
|
# If you have a role "supervisor" and a sub-class "Supervisor", this'll bitch.
|
499
|
-
if !specified_class and
|
500
|
-
|
501
|
-
|
502
|
-
|
499
|
+
if !specified_class and # No specified :class was provided
|
500
|
+
counterpart_type_or_name.is_a?(Class) and
|
501
|
+
(indicated = vocabulary.object_type(role_name)) and
|
502
|
+
indicated != counterpart_type_or_name
|
503
503
|
raise "Role name #{role_name} indicates a different counterpart object_type #{indicated} than specified"
|
504
504
|
end
|
505
505
|
|
@@ -511,7 +511,7 @@ module ActiveFacts
|
|
511
511
|
(one_to_one ? "" : "all_") +
|
512
512
|
counterpart_role_name
|
513
513
|
if counterpart_role_name == default_role_name and
|
514
|
-
|
514
|
+
role_name.to_s != counterpart_type_default_role_name
|
515
515
|
other_role_method += "_as_#{role_name}"
|
516
516
|
end
|
517
517
|
|
@@ -519,7 +519,7 @@ module ActiveFacts
|
|
519
519
|
counterpart_type_or_name,
|
520
520
|
mandatory,
|
521
521
|
other_role_method.to_sym,
|
522
|
-
|
522
|
+
restrict
|
523
523
|
]
|
524
524
|
end
|
525
525
|
|