activefacts-api 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/Gemfile +3 -0
- data/Rakefile +26 -7
- data/VERSION +1 -1
- data/activefacts-api.gemspec +14 -2
- data/lib/activefacts/api/constellation.rb +5 -24
- data/lib/activefacts/api/entity.rb +38 -3
- data/lib/activefacts/api/exceptions.rb +28 -1
- data/lib/activefacts/api/guid.rb +57 -0
- data/lib/activefacts/api/instance_index.rb +11 -1
- data/lib/activefacts/api/numeric.rb +1 -0
- data/lib/activefacts/api/object_type.rb +22 -17
- data/lib/activefacts/api/role.rb +1 -1
- data/lib/activefacts/api/standard_types.rb +2 -1
- data/lib/activefacts/api/support.rb +1 -1
- data/lib/activefacts/api/vocabulary.rb +13 -7
- data/lib/activefacts/tracer.rb +14 -2
- data/spec/constellation/constellation_spec.rb +1 -1
- data/spec/constellation/instance_spec.rb +38 -9
- data/spec/fact_type/role_values_spec.rb +4 -4
- data/spec/fact_type/roles_spec.rb +42 -0
- data/spec/identification_scheme/identity_change_spec.rb +1 -0
- data/spec/object_type/value_type/date_time_spec.rb +38 -0
- data/spec/object_type/value_type/guid_spec.rb +71 -0
- metadata +54 -3
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -5,6 +5,9 @@ gem 'rake', :group => [:development, :test]
|
|
5
5
|
group :development do
|
6
6
|
gem 'jeweler'
|
7
7
|
gem 'rspec', '~>2.6.0'
|
8
|
+
gem 'ruby-debug', :platforms => [:mri_18]
|
9
|
+
gem 'debugger', :platforms => [:mri_19]
|
10
|
+
gem 'pry', :platforms => [:jruby, :rbx]
|
8
11
|
end
|
9
12
|
|
10
13
|
group :test do
|
data/Rakefile
CHANGED
@@ -31,22 +31,41 @@ require 'rspec/core'
|
|
31
31
|
require 'rspec/core/rake_task'
|
32
32
|
require 'rdoc/task'
|
33
33
|
|
34
|
+
gem "rspec", :require => "spec/rake/spectask"
|
35
|
+
|
34
36
|
task :default => :spec
|
35
37
|
|
36
38
|
desc "Run Rspec tests"
|
37
|
-
RSpec::Core::RakeTask.new(:spec)
|
39
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
40
|
+
t.rspec_opts = %w{-f d}
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :spec do
|
44
|
+
namespace :rubies do
|
45
|
+
SUPPORTED_RUBIES = %w{ 1.8.7 1.9.2 1.9.3 jruby-1.7.0 rbx }
|
46
|
+
|
47
|
+
desc "Run Rspec tests on all supported rubies"
|
48
|
+
task :all_tasks => [:install_gems, :exec]
|
49
|
+
|
50
|
+
desc "Run `bundle install` on all rubies"
|
51
|
+
task :install_gems do
|
52
|
+
sh %{ rvm #{SUPPORTED_RUBIES.join(',')} exec bundle install }
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Run `bundle exec rake` on all rubies"
|
56
|
+
task :exec do
|
57
|
+
sh %{ rvm #{SUPPORTED_RUBIES.join(',')} exec bundle exec rake spec }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
38
61
|
|
39
62
|
desc "Run RSpec tests and produce coverage files (results viewable in coverage/index.html)"
|
40
63
|
RSpec::Core::RakeTask.new(:coverage) do |spec|
|
41
64
|
if RUBY_VERSION < '1.9'
|
42
|
-
spec.rcov_opts =
|
43
|
-
'--exclude', 'spec',
|
44
|
-
'--exclude', 'lib/activefacts/tracer.rb',
|
45
|
-
'--exclude', 'gem/*'
|
46
|
-
]
|
65
|
+
spec.rcov_opts = %{ --exclude spec --exclude lib/activefacts/tracer.rb --exclude gem/* }
|
47
66
|
spec.rcov = true
|
48
67
|
else
|
49
|
-
spec.rspec_opts =
|
68
|
+
spec.rspec_opts = %w{ --require simplecov_helper }
|
50
69
|
end
|
51
70
|
end
|
52
71
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.3
|
data/activefacts-api.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "activefacts-api"
|
8
|
-
s.version = "0.9.
|
8
|
+
s.version = "0.9.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Clifford Heath"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-11-01"
|
13
13
|
s.description = "\nThe ActiveFacts API is a Ruby DSL for managing constellations of elementary facts.\nEach fact is either existential (a value or an entity), characteristic (boolean) or\nbinary relational (A rel B). Relational facts are consistently co-referenced, so you\ncan traverse them efficiently in any direction. Each constellation maintains constraints\nover the fact population.\n"
|
14
14
|
s.email = "clifford.heath@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/activefacts/api/constellation.rb",
|
32
32
|
"lib/activefacts/api/entity.rb",
|
33
33
|
"lib/activefacts/api/exceptions.rb",
|
34
|
+
"lib/activefacts/api/guid.rb",
|
34
35
|
"lib/activefacts/api/instance.rb",
|
35
36
|
"lib/activefacts/api/instance_index.rb",
|
36
37
|
"lib/activefacts/api/numeric.rb",
|
@@ -54,6 +55,8 @@ Gem::Specification.new do |s|
|
|
54
55
|
"spec/object_type/entity_type/entity_type_spec.rb",
|
55
56
|
"spec/object_type/entity_type/multipart_identification_spec.rb",
|
56
57
|
"spec/object_type/value_type/autocounter_spec.rb",
|
58
|
+
"spec/object_type/value_type/date_time_spec.rb",
|
59
|
+
"spec/object_type/value_type/guid_spec.rb",
|
57
60
|
"spec/object_type/value_type/numeric_spec.rb",
|
58
61
|
"spec/object_type/value_type/value_type_spec.rb",
|
59
62
|
"spec/simplecov_helper.rb",
|
@@ -72,6 +75,9 @@ Gem::Specification.new do |s|
|
|
72
75
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
73
76
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
74
77
|
s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
|
78
|
+
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
79
|
+
s.add_development_dependency(%q<debugger>, [">= 0"])
|
80
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
75
81
|
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
76
82
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
77
83
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
@@ -80,6 +86,9 @@ Gem::Specification.new do |s|
|
|
80
86
|
s.add_dependency(%q<rake>, [">= 0"])
|
81
87
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
82
88
|
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
89
|
+
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
90
|
+
s.add_dependency(%q<debugger>, [">= 0"])
|
91
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
83
92
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
84
93
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
85
94
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
@@ -89,6 +98,9 @@ Gem::Specification.new do |s|
|
|
89
98
|
s.add_dependency(%q<rake>, [">= 0"])
|
90
99
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
91
100
|
s.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
101
|
+
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
102
|
+
s.add_dependency(%q<debugger>, [">= 0"])
|
103
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
92
104
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
93
105
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
94
106
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
@@ -43,7 +43,9 @@ module ActiveFacts
|
|
43
43
|
def initialize(vocabulary)
|
44
44
|
@vocabulary = vocabulary
|
45
45
|
@instances = Hash.new do |h,k|
|
46
|
-
|
46
|
+
unless k.is_a?(Class) and k.modspace == vocabulary
|
47
|
+
raise "A constellation over #{@vocabulary.name} can only index instances of classes in that vocabulary, not #{k.inspect}"
|
48
|
+
end
|
47
49
|
h[k] = InstanceIndex.new(self, k)
|
48
50
|
end
|
49
51
|
end
|
@@ -66,27 +68,6 @@ module ActiveFacts
|
|
66
68
|
self
|
67
69
|
end
|
68
70
|
|
69
|
-
=begin
|
70
|
-
def assert *args
|
71
|
-
case
|
72
|
-
when args.size >= 1
|
73
|
-
args.each do |arg|
|
74
|
-
assert arg
|
75
|
-
end
|
76
|
-
when args[0].is_a?(Hash)
|
77
|
-
args[0].each do |key, value|
|
78
|
-
klass_name = key.is_a?(Symbol) ? key.to_s.camelcase : key.to_s
|
79
|
-
klass = vocabulary.const_get(klass_name)
|
80
|
-
send(klass_name).assert(*Array(value))
|
81
|
-
end
|
82
|
-
else
|
83
|
-
args.each do |arg|
|
84
|
-
assert(arg)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
=end
|
89
|
-
|
90
71
|
# Constellations verbalise all members of all classes in alphabetical order, showing
|
91
72
|
# non-identifying role values as well
|
92
73
|
def verbalise
|
@@ -137,8 +118,8 @@ module ActiveFacts
|
|
137
118
|
# With no parameters, return the collection of all instances of that object_type.
|
138
119
|
# With parameters, assert an instance of the object_type identified by the values passed as args.
|
139
120
|
def method_missing(m, *args, &b)
|
140
|
-
|
141
|
-
|
121
|
+
klass = @vocabulary.const_get(m)
|
122
|
+
if klass and klass.is_a?(Class) and klass.respond_to?(:assert_instance)
|
142
123
|
(class << self; self; end).
|
143
124
|
send(:define_method, sym = m.to_sym) do |*args|
|
144
125
|
instance_index = @instances[klass]
|
@@ -58,10 +58,41 @@ module ActiveFacts
|
|
58
58
|
# Assign the identifying roles in order. Any other roles will be assigned by our caller
|
59
59
|
klass.identifying_role_names.zip(args).each do |role_name, value|
|
60
60
|
role = self.class.roles(role_name)
|
61
|
-
|
61
|
+
begin
|
62
|
+
send(role.setter, value)
|
63
|
+
rescue NoMethodError => e
|
64
|
+
raise settable_roles_exception(e, role_name)
|
65
|
+
end
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
69
|
+
def settable_roles_exception e, role_name
|
70
|
+
n = e.class.new(
|
71
|
+
"#{self.class} has no setter for #{role_name}.\n" +
|
72
|
+
"Settable roles are #{settable_roles*', '}.\n" +
|
73
|
+
(if self.class.vocabulary.delayed.empty?
|
74
|
+
''
|
75
|
+
else
|
76
|
+
"This could be because the following expected object types are still not defined: #{self.class.vocabulary.delayed.keys.sort*', '}\n"
|
77
|
+
end
|
78
|
+
)
|
79
|
+
)
|
80
|
+
n.set_backtrace(e.backtrace)
|
81
|
+
n
|
82
|
+
end
|
83
|
+
|
84
|
+
def settable_roles
|
85
|
+
([self.class]+self.class.supertypes_transitive).
|
86
|
+
map do |k|
|
87
|
+
k.roles.
|
88
|
+
map do |name, role|
|
89
|
+
role.unique ? name : nil
|
90
|
+
end.
|
91
|
+
compact
|
92
|
+
end.
|
93
|
+
flatten
|
94
|
+
end
|
95
|
+
|
65
96
|
def inspect #:nodoc:
|
66
97
|
inc = constellation ? " in #{constellation.inspect}" : ""
|
67
98
|
# REVISIT: Where there are one-to-one roles, this cycles
|
@@ -196,7 +227,7 @@ module ActiveFacts
|
|
196
227
|
end
|
197
228
|
if arg == nil # But not false
|
198
229
|
if role.mandatory
|
199
|
-
raise
|
230
|
+
raise MissingMandatoryRoleValueException.new(self, role)
|
200
231
|
end
|
201
232
|
else
|
202
233
|
role.counterpart_object_type.identifying_role_values(*arg)
|
@@ -246,13 +277,17 @@ module ActiveFacts
|
|
246
277
|
elsif !arg
|
247
278
|
value = role_key = nil
|
248
279
|
else
|
280
|
+
=begin
|
281
|
+
# REVISIT; These next few lines are bogus; they generate TypeError exceptions which are caught and ignored
|
282
|
+
# A new approach will follow shortly which won't @create_instances that won't be needed
|
249
283
|
if role.counterpart.object_type.is_entity_type
|
250
284
|
add = !constellation.send(role.counterpart.object_type.basename.to_sym).include?([arg])
|
251
285
|
else
|
252
286
|
add = !constellation.send(role.counterpart.object_type.basename.to_sym).include?(arg)
|
253
287
|
end
|
288
|
+
=end
|
254
289
|
value, role_key = role.counterpart.object_type.assert_instance(constellation, Array(arg))
|
255
|
-
@created_instances << [role.counterpart, value] if add
|
290
|
+
# @created_instances << [role.counterpart, value] if add
|
256
291
|
end
|
257
292
|
key << role_key
|
258
293
|
value
|
@@ -6,7 +6,34 @@
|
|
6
6
|
|
7
7
|
module ActiveFacts
|
8
8
|
module API
|
9
|
-
class
|
9
|
+
class ActiveFactsException < StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
class ActiveFactsSchemaException < ActiveFactsException
|
13
|
+
end
|
14
|
+
|
15
|
+
class ActiveFactsRuntimeException < ActiveFactsException
|
16
|
+
end
|
17
|
+
|
18
|
+
class CrossVocabularyRoleException < ActiveFactsSchemaException
|
19
|
+
def initialize klass, vocabulary
|
20
|
+
super "#{klass} must be an object type in #{vocabulary.name}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class RoleNotDefinedException < ActiveFactsRuntimeException
|
25
|
+
def initialize klass, role_name
|
26
|
+
super "Role #{klass.basename}.#{role_name} is not defined"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class MissingMandatoryRoleValueException < ActiveFactsRuntimeException
|
31
|
+
def initialize klass, role
|
32
|
+
super "A #{role.counterpart.object_type.basename} is required to satisfy the #{role.name.inspect} role of #{klass.basename}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class DuplicateIdentifyingValueException < ActiveFactsRuntimeException
|
10
37
|
def initialize(desc)
|
11
38
|
super("Illegal attempt to assert #{desc[:class].basename} having identifying value" +
|
12
39
|
" (#{desc[:role].name} is #{desc[:value].verbalise})," +
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'date'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
unless defined? SecureRandom.uuid
|
6
|
+
# I think this only applies to 1.8.6 (and JRuby/Rubinius in 1.8 mode) now:
|
7
|
+
def SecureRandom.uuid
|
8
|
+
hex(16).sub(/(........)(....)(....)(....)(............)/,'\1-\2-\3-\4-\5')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# The Guid class is what it says on the packet, but you can assert a :new one.
|
13
|
+
class Guid
|
14
|
+
def initialize(i = :new)
|
15
|
+
if i == :new
|
16
|
+
@value = SecureRandom.uuid.freeze
|
17
|
+
elsif (v = i.to_s).length == 36 and !(v !~ /[^0-9a-f]/i)
|
18
|
+
@value = v.clone.freeze
|
19
|
+
else
|
20
|
+
raise "Illegal non-Guid value #{i.inspect} given for Guid"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@value
|
26
|
+
end
|
27
|
+
|
28
|
+
# if the value is unassigned, it equal?(:new).
|
29
|
+
def equal? value
|
30
|
+
@value == value
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"\#<Guid #{@value}>"
|
35
|
+
end
|
36
|
+
|
37
|
+
def hash #:nodoc:
|
38
|
+
@value.hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def eql?(o) #:nodoc:
|
42
|
+
to_s.eql?(o.to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
# def self.inherited(other) #:nodoc:
|
46
|
+
# def other.identifying_role_values(*args)
|
47
|
+
# return nil if args == [:new] # A new object has no identifying_role_values
|
48
|
+
# if args.size == 1
|
49
|
+
# return args[0] if args[0].is_a?(AutoCounter)
|
50
|
+
# return args[0].send(self.basename.snakecase.to_sym) if args[0].respond_to?(self.basename.snakecase.to_sym)
|
51
|
+
# end
|
52
|
+
# return new(*args)
|
53
|
+
# end
|
54
|
+
# super
|
55
|
+
# end
|
56
|
+
|
57
|
+
end
|
@@ -44,7 +44,17 @@ module ActiveFacts
|
|
44
44
|
if args.size == 1 && args[0].is_a?(@klass)
|
45
45
|
key = args[0].identifying_role_values
|
46
46
|
else
|
47
|
-
|
47
|
+
begin
|
48
|
+
key = @klass.identifying_role_values(*args)
|
49
|
+
rescue TypeError => e
|
50
|
+
# This happens (and should not) during assert_instance when checking
|
51
|
+
# for new asserts of identifying values that might get rolled back
|
52
|
+
# when the assert fails (for example because of an implied subtyping change)
|
53
|
+
key = nil
|
54
|
+
rescue ActiveFactsRuntimeException => e
|
55
|
+
# This is currently only known to happen during a retract()
|
56
|
+
key = nil
|
57
|
+
end
|
48
58
|
end
|
49
59
|
|
50
60
|
@hash[key]
|
@@ -29,13 +29,17 @@ module ActiveFacts
|
|
29
29
|
unless role = @roles[role_name.to_sym]
|
30
30
|
role = nil
|
31
31
|
supertypes.each do |supertype|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
begin
|
33
|
+
role = supertype.roles(role_name)
|
34
|
+
rescue RoleNotDefinedException
|
35
|
+
next
|
36
|
+
end
|
35
37
|
break
|
36
38
|
end
|
37
39
|
end
|
38
|
-
|
40
|
+
unless role
|
41
|
+
raise RoleNotDefinedException.new(self, role_name)
|
42
|
+
end
|
39
43
|
role
|
40
44
|
else
|
41
45
|
nil
|
@@ -132,7 +136,7 @@ module ActiveFacts
|
|
132
136
|
# REVISIT: Need to check all superclass roles recursively, unless we hit a common supertype
|
133
137
|
realise_supertypes(object_type, all_supertypes)
|
134
138
|
end
|
135
|
-
[(superclass.vocabulary
|
139
|
+
[(superclass.respond_to?(:vocabulary) ? superclass : nil), *@supertypes].compact
|
136
140
|
end
|
137
141
|
end
|
138
142
|
|
@@ -140,12 +144,12 @@ module ActiveFacts
|
|
140
144
|
def supertypes_transitive
|
141
145
|
class_eval do
|
142
146
|
supertypes = []
|
143
|
-
|
147
|
+
v = superclass.respond_to?(:vocabulary) ? superclass.vocabulary : nil
|
148
|
+
supertypes << superclass if v.kind_of?(Module)
|
144
149
|
supertypes += (@supertypes ||= [])
|
145
150
|
sts = supertypes.inject([]) do |a, t|
|
146
151
|
next if a.include?(t)
|
147
|
-
a += [t]
|
148
|
-
a += t.supertypes_transitive rescue []
|
152
|
+
a += [t] + t.supertypes_transitive
|
149
153
|
end.uniq
|
150
154
|
sts # The local variable unconfuses rcov
|
151
155
|
end
|
@@ -236,7 +240,7 @@ module ActiveFacts
|
|
236
240
|
class_eval do
|
237
241
|
define_method role.getter do |*a|
|
238
242
|
raise "Parameters passed to #{self.class.name}\##{role.name}" if a.size > 0
|
239
|
-
instance_variable_get(role.variable)
|
243
|
+
instance_variable_get(role.variable)
|
240
244
|
end
|
241
245
|
end
|
242
246
|
end
|
@@ -247,7 +251,7 @@ module ActiveFacts
|
|
247
251
|
class_eval do
|
248
252
|
define_method role.setter do |value|
|
249
253
|
|
250
|
-
old = instance_variable_get(role.variable)
|
254
|
+
old = instance_variable_get(role.variable)
|
251
255
|
return true if old.equal?(value) # Occurs when another instance having the same value is assigned
|
252
256
|
|
253
257
|
value = role.adapt(@constellation, value) if value
|
@@ -288,7 +292,7 @@ module ActiveFacts
|
|
288
292
|
role_var = role.variable
|
289
293
|
|
290
294
|
# Get old value, and jump out early if it's unchanged:
|
291
|
-
old = instance_variable_get(role_var)
|
295
|
+
old = instance_variable_get(role_var)
|
292
296
|
return value if old.equal?(value) # Occurs during one_to_one assignment, for example
|
293
297
|
|
294
298
|
value = role.adapt(constellation, value) if value
|
@@ -324,10 +328,9 @@ module ActiveFacts
|
|
324
328
|
def define_many_to_one_accessor(role)
|
325
329
|
class_eval do
|
326
330
|
define_method role.getter do
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
r
|
331
|
+
role_var = role.variable
|
332
|
+
instance_variable_get(role_var) or
|
333
|
+
instance_variable_set(role_var, RoleValues.new)
|
331
334
|
end
|
332
335
|
end
|
333
336
|
end
|
@@ -388,10 +391,12 @@ module ActiveFacts
|
|
388
391
|
end
|
389
392
|
|
390
393
|
# resolve the Symbol to a Class now if possible:
|
391
|
-
resolved = vocabulary.object_type(related)
|
394
|
+
resolved = vocabulary.object_type(related)
|
392
395
|
related = resolved if resolved
|
393
396
|
if related.is_a?(Class)
|
394
|
-
|
397
|
+
unless related.respond_to?(:vocabulary) and related.vocabulary == self.vocabulary
|
398
|
+
raise CrossVocabularyRoleException.new(related, vocabulary)
|
399
|
+
end
|
395
400
|
end
|
396
401
|
|
397
402
|
if options.delete(:mandatory) == true
|
data/lib/activefacts/api/role.rb
CHANGED
@@ -101,7 +101,7 @@ module ActiveFacts
|
|
101
101
|
role = self
|
102
102
|
klass.class_eval do
|
103
103
|
role_accessor_name = "#{role.name}_role"
|
104
|
-
unless (
|
104
|
+
unless respond_to?(role_accessor_name)
|
105
105
|
(class << self; self; end).
|
106
106
|
send(:define_method, role_accessor_name) do
|
107
107
|
role
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#
|
10
10
|
require 'date'
|
11
11
|
require 'activefacts/api/numeric'
|
12
|
+
require 'activefacts/api/guid'
|
12
13
|
|
13
14
|
module ActiveFacts
|
14
15
|
module API
|
@@ -23,7 +24,7 @@ module ActiveFacts
|
|
23
24
|
end
|
24
25
|
# Add the methods that convert our classes into ObjectType types:
|
25
26
|
|
26
|
-
ValueClasses = [String, Date, DateTime, Time, Int, Real, AutoCounter, Decimal]
|
27
|
+
ValueClasses = [String, Date, DateTime, Time, Int, Real, AutoCounter, Decimal, Guid]
|
27
28
|
ValueClasses.each{|c|
|
28
29
|
c.send :extend, ActiveFacts::API::ValueClass
|
29
30
|
}
|
@@ -21,7 +21,9 @@ module ActiveFacts
|
|
21
21
|
return @object_type unless name
|
22
22
|
|
23
23
|
if name.is_a? Class
|
24
|
-
|
24
|
+
unless name.respond_to?(:vocabulary) and name.vocabulary == self
|
25
|
+
raise CrossVocabularyRoleException.new(name, self)
|
26
|
+
end
|
25
27
|
return name
|
26
28
|
end
|
27
29
|
|
@@ -31,7 +33,7 @@ module ActiveFacts
|
|
31
33
|
c
|
32
34
|
else
|
33
35
|
begin
|
34
|
-
const_get(
|
36
|
+
const_get(camel)
|
35
37
|
rescue NameError
|
36
38
|
nil
|
37
39
|
end
|
@@ -64,22 +66,26 @@ module ActiveFacts
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def __delay(object_type_name, args, &block) #:nodoc:
|
67
|
-
|
68
|
-
@delayed[object_type_name] << [args, block]
|
69
|
+
delayed[object_type_name] << [args, block]
|
69
70
|
end
|
70
71
|
|
71
72
|
# __bind raises an error if the named class doesn't exist yet.
|
72
73
|
def __bind(object_type_name) #:nodoc:
|
73
74
|
object_type = const_get(object_type_name)
|
74
|
-
if (
|
75
|
-
d =
|
75
|
+
if (delayed.include?(object_type_name))
|
76
|
+
d = delayed[object_type_name]
|
76
77
|
d.each{|(a,b)|
|
77
78
|
b.call(object_type, *a)
|
78
79
|
}
|
79
|
-
|
80
|
+
delayed.delete(object_type_name)
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
84
|
+
def delayed
|
85
|
+
@delayed ||= Hash.new { |h,k| h[k] = [] }
|
86
|
+
@delayed
|
87
|
+
end
|
88
|
+
|
83
89
|
end
|
84
90
|
end
|
85
91
|
end
|
data/lib/activefacts/tracer.rb
CHANGED
@@ -26,14 +26,26 @@ module ActiveFacts
|
|
26
26
|
}
|
27
27
|
end
|
28
28
|
if @keys[:debug]
|
29
|
-
|
29
|
+
errors = []
|
30
|
+
success = false
|
31
|
+
[ENV["DEBUG_PREFERENCE"]].compact+
|
32
|
+
[
|
33
|
+
'pry',
|
34
|
+
'debugger',
|
35
|
+
'ruby-debug'
|
36
|
+
].each do |debugger|
|
30
37
|
begin
|
31
38
|
require debugger
|
32
39
|
puts "Loaded "+debugger
|
40
|
+
success = true
|
33
41
|
break
|
34
|
-
rescue LoadError
|
42
|
+
rescue LoadError => e
|
43
|
+
errors << e
|
35
44
|
end
|
36
45
|
end
|
46
|
+
unless success
|
47
|
+
puts "Can't load any debugger, failed on:\n#{errors.inspect}"
|
48
|
+
end
|
37
49
|
::Debugger.start rescue nil
|
38
50
|
end
|
39
51
|
end
|
@@ -8,7 +8,7 @@ describe "A Constellation instance" do
|
|
8
8
|
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
9
9
|
module Mod
|
10
10
|
@base_types = [
|
11
|
-
Int, Real, AutoCounter, String, Date, DateTime
|
11
|
+
Int, Real, AutoCounter, String, Date, DateTime, Decimal, Guid
|
12
12
|
]
|
13
13
|
|
14
14
|
# Create a value type and a subtype of that value type for each base type:
|
@@ -9,7 +9,7 @@ describe "An instance of every type of ObjectType" do
|
|
9
9
|
module Mod
|
10
10
|
# These are the base value types we're going to test:
|
11
11
|
@base_types = [
|
12
|
-
Int, Real, AutoCounter, String, Date, DateTime, Decimal
|
12
|
+
Int, Real, AutoCounter, String, Date, DateTime, Decimal, Guid
|
13
13
|
]
|
14
14
|
|
15
15
|
# Construct the names of the roles they play:
|
@@ -74,7 +74,13 @@ 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
|
+
|
78
|
+
begin
|
79
|
+
Mod.module_eval code
|
80
|
+
rescue Exception => e
|
81
|
+
puts "Failure: #{e}"
|
82
|
+
puts "Failed on: <<END\n#{code}\nEND"
|
83
|
+
end
|
78
84
|
end
|
79
85
|
end
|
80
86
|
|
@@ -87,6 +93,7 @@ describe "An instance of every type of ObjectType" do
|
|
87
93
|
@date = [2008, 04, 19]
|
88
94
|
@date_time = [2008, 04, 19, 10, 28, 14]
|
89
95
|
@decimal = BigDecimal.new('98765432109876543210')
|
96
|
+
@guid = '01234567-89ab-cdef-0123-456789abcdef'
|
90
97
|
|
91
98
|
# Value Type instances
|
92
99
|
@int_value = Mod::IntVal.new(1)
|
@@ -101,6 +108,7 @@ describe "An instance of every type of ObjectType" do
|
|
101
108
|
@date_time_value = Mod::DateTimeVal.new d # 2008, 04, 20, 10, 28, 14
|
102
109
|
# This next isn't in the same pattern; it makes a Decimal from a BigDecimal rather than a String (coverage reasons)
|
103
110
|
@decimal_value = Mod::DecimalVal.new(BigDecimal.new('98765432109876543210'))
|
111
|
+
@guid_value = Mod::GuidVal.new(:new)
|
104
112
|
|
105
113
|
# Value SubType instances
|
106
114
|
@int_sub_value = Mod::IntSubVal.new(4)
|
@@ -112,6 +120,7 @@ describe "An instance of every type of ObjectType" do
|
|
112
120
|
@date_time_sub_value = Mod::DateTimeSubVal.new(::DateTime.civil(2008, 04, 26, 10, 28, 14))
|
113
121
|
# This next isn't in the same pattern; it makes a Decimal from a BigNum rather than a String (coverage reasons)
|
114
122
|
@decimal_sub_value = Mod::DecimalSubVal.new(98765432109876543210)
|
123
|
+
@guid_sub_value = Mod::GuidSubVal.new(:new)
|
115
124
|
|
116
125
|
# Entities identified by Value Type, SubType and Entity-by-value-type instances
|
117
126
|
@test_by_int = Mod::TestByInt.new(2)
|
@@ -125,6 +134,7 @@ describe "An instance of every type of ObjectType" do
|
|
125
134
|
@test_by_date_time = Mod::TestByDateTime.new([[2008,04,28,10,28,15]])
|
126
135
|
#@test_by_date_time = Mod::TestByDateTime.new(DateTime.new(2008,04,28,10,28,15))
|
127
136
|
@test_by_decimal = Mod::TestByDecimal.new('98765432109876543210')
|
137
|
+
@test_by_guid = Mod::TestByGuid.new('01234567-89ab-cdef-0123-456789abcdef')
|
128
138
|
|
129
139
|
@test_by_int_sub = Mod::TestByIntSub.new(2)
|
130
140
|
@test_by_real_sub = Mod::TestByRealSub.new(5.0)
|
@@ -134,6 +144,7 @@ describe "An instance of every type of ObjectType" do
|
|
134
144
|
@test_by_date_sub = Mod::TestByDateSub.new(Date.new(2008,04,27))
|
135
145
|
@test_by_date_time_sub = Mod::TestByDateTimeSub.new(2008,04,29,10,28,15)
|
136
146
|
@test_by_decimal_sub = Mod::TestByDecimalSub.new('98765432109876543210')
|
147
|
+
@test_by_guid_sub = Mod::TestByGuidSub.new('01234567-89ab-cdef-0123-456789abcdef')
|
137
148
|
|
138
149
|
@test_by_int_entity = Mod::TestByIntEntity.new(@test_by_int)
|
139
150
|
@test_by_real_entity = Mod::TestByRealEntity.new(@test_by_real)
|
@@ -143,6 +154,7 @@ describe "An instance of every type of ObjectType" do
|
|
143
154
|
@test_by_date_entity = Mod::TestByDateEntity.new(@test_by_date)
|
144
155
|
@test_by_date_time_entity = Mod::TestByDateTimeEntity.new(@test_by_date_time)
|
145
156
|
@test_by_decimal_entity = Mod::TestByDecimalEntity.new(@test_by_decimal)
|
157
|
+
@test_by_guid_entity = Mod::TestByGuidEntity.new(@test_by_guid)
|
146
158
|
|
147
159
|
# Entity subtypes
|
148
160
|
@test_sub_by_int = Mod::TestSubByInt.new(2)
|
@@ -153,45 +165,54 @@ describe "An instance of every type of ObjectType" do
|
|
153
165
|
@test_sub_by_date = Mod::TestSubByDate.new(Date.new(2008,04,28))
|
154
166
|
@test_sub_by_date_time = Mod::TestSubByDateTime.new(2008,04,28,10,28,15)
|
155
167
|
@test_sub_by_decimal = Mod::TestSubByDecimal.new('98765432109876543210')
|
168
|
+
@test_sub_by_guid = Mod::TestSubByGuid.new('01234567-89ab-cdef-0123-456789abcdef')
|
156
169
|
|
157
170
|
# These arrays get zipped together in various ways. Keep them aligned.
|
158
171
|
@values = [
|
159
172
|
@int, @real, @auto_counter, @new_auto_counter,
|
160
|
-
@string, @date, @date_time, @decimal
|
173
|
+
@string, @date, @date_time, @decimal, @guid
|
161
174
|
]
|
162
175
|
@classes = [
|
163
176
|
Int, Real, AutoCounter, AutoCounter,
|
164
|
-
String, Date, DateTime, Decimal
|
177
|
+
String, Date, DateTime, Decimal, Guid
|
165
178
|
]
|
166
179
|
@value_types = [
|
167
180
|
Mod::IntVal, Mod::RealVal, Mod::AutoCounterVal, Mod::AutoCounterVal,
|
168
181
|
Mod::StringVal, Mod::DateVal, Mod::DateTimeVal, Mod::DecimalVal,
|
182
|
+
Mod::GuidVal,
|
169
183
|
Mod::IntSubVal, Mod::RealSubVal, Mod::AutoCounterSubVal, Mod::AutoCounterSubVal,
|
170
184
|
Mod::StringSubVal, Mod::DateSubVal, Mod::DateTimeSubVal, Mod::DecimalSubVal,
|
185
|
+
Mod::GuidSubVal,
|
171
186
|
]
|
172
187
|
@value_instances = [
|
173
188
|
@int_value, @real_value, @auto_counter_value, @new_auto_counter_value,
|
174
|
-
@string_value, @date_value, @date_time_value, @decimal_value,
|
189
|
+
@string_value, @date_value, @date_time_value, @decimal_value, @guid_value,
|
175
190
|
@int_sub_value, @real_sub_value, @auto_counter_sub_value, @auto_counter_sub_value_new,
|
176
|
-
@string_sub_value, @date_sub_value, @date_time_sub_value, @decimal_sub_value,
|
191
|
+
@string_sub_value, @date_sub_value, @date_time_sub_value, @decimal_sub_value, @guid_sub_value,
|
177
192
|
@int_value, @real_value, @auto_counter_value, @new_auto_counter_value,
|
178
|
-
@string_value, @date_value, @date_time_value, @decimal_value,
|
193
|
+
@string_value, @date_value, @date_time_value, @decimal_value, @guid_value,
|
179
194
|
]
|
180
195
|
@entity_types = [
|
181
196
|
Mod::TestByInt, Mod::TestByReal, Mod::TestByAutoCounter, Mod::TestByAutoCounter,
|
182
197
|
Mod::TestByString, Mod::TestByDate, Mod::TestByDateTime, Mod::TestByDecimal,
|
198
|
+
Mod::TestByGuid,
|
183
199
|
Mod::TestByIntSub, Mod::TestByRealSub, Mod::TestByAutoCounterSub, Mod::TestByAutoCounterSub,
|
184
200
|
Mod::TestByStringSub, Mod::TestByDateSub, Mod::TestByDateTimeSub, Mod::TestByDecimalSub,
|
201
|
+
Mod::TestByGuidSub,
|
185
202
|
Mod::TestSubByInt, Mod::TestSubByReal, Mod::TestSubByAutoCounter, Mod::TestSubByAutoCounter,
|
186
203
|
Mod::TestSubByString, Mod::TestSubByDate, Mod::TestSubByDateTime, Mod::TestByDecimalEntity,
|
204
|
+
Mod::TestByGuidEntity,
|
187
205
|
]
|
188
206
|
@entities = [
|
189
207
|
@test_by_int, @test_by_real, @test_by_auto_counter, @test_by_auto_counter_new,
|
190
208
|
@test_by_string, @test_by_date, @test_by_date_time, @test_by_decimal,
|
209
|
+
@test_by_guid,
|
191
210
|
@test_by_int_sub, @test_by_real_sub, @test_by_auto_counter_sub, @test_by_auto_counter_new_sub,
|
192
211
|
@test_by_string_sub, @test_by_date_sub, @test_by_date_time_sub, @test_by_decimal_sub,
|
212
|
+
@test_by_guid_sub,
|
193
213
|
@test_sub_by_int, @test_sub_by_real, @test_sub_by_auto_counter, @test_sub_by_auto_counter_new,
|
194
214
|
@test_sub_by_string, @test_sub_by_date, @test_sub_by_date_time, @test_sub_by_decimal,
|
215
|
+
@test_sub_by_guid,
|
195
216
|
]
|
196
217
|
@entities_by_entity = [
|
197
218
|
@test_by_int_entity,
|
@@ -202,28 +223,35 @@ describe "An instance of every type of ObjectType" do
|
|
202
223
|
@test_by_date_entity,
|
203
224
|
@test_by_date_time_entity,
|
204
225
|
@test_by_decimal_entity,
|
226
|
+
@test_by_guid_entity,
|
205
227
|
]
|
206
228
|
@entities_by_entity_types = [
|
207
229
|
Mod::TestByIntEntity, Mod::TestByRealEntity, Mod::TestByAutoCounterEntity, Mod::TestByAutoCounterEntity,
|
208
230
|
Mod::TestByStringEntity, Mod::TestByDateEntity, Mod::TestByDateTimeEntity, Mod::TestByDecimalEntity,
|
231
|
+
Mod::TestByGuidEntity,
|
209
232
|
]
|
210
233
|
@test_role_names = [
|
211
234
|
:int_value, :real_value, :auto_counter_value, :auto_counter_value,
|
212
235
|
:string_value, :date_value, :date_time_value, :decimal_value,
|
236
|
+
:guid_value,
|
213
237
|
:int_sub_value, :real_sub_value, :auto_counter_sub_value, :auto_counter_sub_value,
|
214
238
|
:string_sub_value, :date_sub_value, :date_time_sub_value, :decimal_sub_value,
|
239
|
+
:guid_sub_value,
|
215
240
|
:int_value, :real_value, :auto_counter_value, :auto_counter_value,
|
216
241
|
:string_value, :date_value, :date_time_value, :decimal_value,
|
242
|
+
:guid_value,
|
217
243
|
]
|
218
244
|
@role_values = [
|
219
245
|
3, 4.0, 5, 6,
|
220
246
|
"three", Date.new(2008,4,21), DateTime.new(2008,4,22,10,28,16),
|
221
|
-
'98765432109876543210'
|
247
|
+
'98765432109876543210',
|
248
|
+
'01234567-89ab-cdef-0123-456789abcdef'
|
222
249
|
]
|
223
250
|
@role_alternate_values = [
|
224
251
|
4, 5.0, 6, 7,
|
225
252
|
"four", Date.new(2009,4,21), DateTime.new(2009,4,22,10,28,16),
|
226
|
-
'98765432109876543211'
|
253
|
+
'98765432109876543211',
|
254
|
+
'01234567-89ab-cdef-0123-456789abcdef'
|
227
255
|
]
|
228
256
|
@subtype_role_instances = [
|
229
257
|
Mod::IntSubVal.new(6), Mod::RealSubVal.new(6.0),
|
@@ -231,6 +259,7 @@ describe "An instance of every type of ObjectType" do
|
|
231
259
|
Mod::StringSubVal.new("seven"),
|
232
260
|
Mod::DateSubVal.new(2008,4,29), Mod::DateTimeSubVal.new(2008,4,30,10,28,16),
|
233
261
|
Mod::DecimalSubVal.new('98765432109876543210'),
|
262
|
+
Mod::DecimalSubVal.new('01234567-89ab-cdef-0123-456789abcdef'),
|
234
263
|
]
|
235
264
|
end
|
236
265
|
|
@@ -3,9 +3,9 @@
|
|
3
3
|
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
4
|
#
|
5
5
|
|
6
|
-
VALUE_TYPES = Int, Real, AutoCounter, String, Date, DateTime, Decimal
|
7
|
-
RAW_VALUES = [2, 3.0, 4, "5", Date.new(2008, 04, 20), DateTime.new(2008, 04, 20, 10, 28, 14)]
|
8
|
-
ALT_VALUES = [3, 4.0, 5, "6", Date.new(2009, 04, 20), DateTime.new(2009, 04, 20, 10, 28, 14)]
|
6
|
+
VALUE_TYPES = Int, Real, AutoCounter, String, Date, DateTime, Decimal, Guid
|
7
|
+
RAW_VALUES = [2, 3.0, 4, "5", Date.new(2008, 04, 20), DateTime.new(2008, 04, 20, 10, 28, 14), '43210.98765', '01234567-89ab-cdef-0123-456789abcdef']
|
8
|
+
ALT_VALUES = [3, 4.0, 5, "6", Date.new(2009, 04, 20), DateTime.new(2009, 04, 20, 10, 28, 14), '56789.01234', 'fedcba987654-3210-fedc-ba98-76543210']
|
9
9
|
VALUE_SUB_FOR_VALUE = {}
|
10
10
|
VALUES_FOR_TYPE = VALUE_TYPES.zip(RAW_VALUES, ALT_VALUES).inject({}) do |h, (vt, v1, v2)|
|
11
11
|
next h unless v1 and v2
|
@@ -186,7 +186,7 @@ describe "Object type role values" do
|
|
186
186
|
it "should allow nullifying and reassigning a #{object_type_name} entity's identifying role value" do
|
187
187
|
object = @constellation.send(object_type_name, *object_identifying_parameters(object_type_name, values[0]))
|
188
188
|
object.class.identifying_roles.each do |identifying_role|
|
189
|
-
next if identifying_role.name
|
189
|
+
next if [:counter, :id_guid_val].include?(identifying_role.name)
|
190
190
|
assigned = object.send(:"#{identifying_role.name}=", nil)
|
191
191
|
assigned.should be_nil
|
192
192
|
object.send(:"#{identifying_role.name}=", values[1])
|
@@ -54,6 +54,48 @@ describe "Roles" do
|
|
54
54
|
role.counterpart.object_type.should == Mod::Name
|
55
55
|
end
|
56
56
|
|
57
|
+
it "should prevent association of a role name with an object_type from the wrong module" do
|
58
|
+
lambda {
|
59
|
+
module Mod2
|
60
|
+
class Unrelated
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module Mod
|
65
|
+
class Existing1 < String
|
66
|
+
value_type
|
67
|
+
has_one :unrelated, :class => Mod2::Unrelated
|
68
|
+
end
|
69
|
+
end
|
70
|
+
}.should raise_error(ActiveFacts::API::CrossVocabularyRoleException)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should prevent association of a role name with a non-object_type" do
|
74
|
+
lambda {
|
75
|
+
module Mod
|
76
|
+
class NonObject
|
77
|
+
end
|
78
|
+
class Existing1 < String
|
79
|
+
value_type
|
80
|
+
has_one :non_object, :class => NonObject
|
81
|
+
end
|
82
|
+
end
|
83
|
+
}.should raise_error(ActiveFacts::API::CrossVocabularyRoleException)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should prevent association of a role name with an implied non-object_type" do
|
87
|
+
lambda {
|
88
|
+
module Mod
|
89
|
+
class NonObject
|
90
|
+
end
|
91
|
+
class Existing1 < String
|
92
|
+
value_type
|
93
|
+
has_one :non_object
|
94
|
+
end
|
95
|
+
end
|
96
|
+
}.should raise_error(ActiveFacts::API::CrossVocabularyRoleException)
|
97
|
+
end
|
98
|
+
|
57
99
|
it "should provide value type metadata" do
|
58
100
|
Mod::Name.length.should == 40
|
59
101
|
Mod::Name.scale.should == 0
|
@@ -67,6 +67,7 @@ describe "identity" do
|
|
67
67
|
@p2.should be_nil
|
68
68
|
@c1.Name.values.should =~ [@juliar, @tony]
|
69
69
|
@c1.Name.keys.should =~ [@juliar, @tony]
|
70
|
+
pending "This functionality was poorly implemented and has been temporarily switched off"
|
70
71
|
@c1.TFN.keys.should =~ [123]
|
71
72
|
@c1.Person.values.should =~ [@p1, @p3]
|
72
73
|
@c1.Person.keys.should =~ [[@juliar],[@tony]]
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts tests: Value instances in the Runtime API
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
|
+
#
|
5
|
+
require 'activefacts/api'
|
6
|
+
|
7
|
+
describe Date do
|
8
|
+
it "should construct with no arguments" do
|
9
|
+
proc {
|
10
|
+
@d = Date.new()
|
11
|
+
}.should_not raise_error
|
12
|
+
@d.year.should == -4712
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should construct with a nil argument" do
|
16
|
+
proc {
|
17
|
+
@d = Date.new(nil)
|
18
|
+
}.should_not raise_error
|
19
|
+
@d.year.should == -4712
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should construct with a full arguments" do
|
23
|
+
proc {
|
24
|
+
@d = Date.civil(2012, 10, 31)
|
25
|
+
}.should_not raise_error
|
26
|
+
@d.to_s.should == "2012-10-31"
|
27
|
+
end
|
28
|
+
|
29
|
+
=begin
|
30
|
+
it "should be encodable in JSON" do
|
31
|
+
proc {
|
32
|
+
@d = Date.new(2012, 10, 31)
|
33
|
+
@d.to_json.should == "REVISIT"
|
34
|
+
}.should_not raise_error
|
35
|
+
end
|
36
|
+
=end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts tests: Value instances in the Runtime API
|
3
|
+
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
|
+
#
|
5
|
+
|
6
|
+
describe "Guid Value Type instances" do
|
7
|
+
before :each do
|
8
|
+
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
9
|
+
module Mod
|
10
|
+
class ThingId < Guid
|
11
|
+
value_type
|
12
|
+
end
|
13
|
+
class Thing
|
14
|
+
identified_by :thing_id
|
15
|
+
one_to_one :thing_id
|
16
|
+
end
|
17
|
+
class Ordinal < Int
|
18
|
+
value_type
|
19
|
+
end
|
20
|
+
class ThingFacet
|
21
|
+
identified_by :thing, :ordinal
|
22
|
+
has_one :thing
|
23
|
+
has_one :ordinal
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@constellation = ActiveFacts::API::Constellation.new(Mod)
|
27
|
+
@thing = Mod::Thing.new(:new)
|
28
|
+
@thing_id = Mod::ThingId.new
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should respond to verbalise" do
|
32
|
+
@thing_id.respond_to?(:verbalise).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should verbalise correctly" do
|
36
|
+
@thing_id.verbalise.should =~ /ThingId '[-0-9a-f]{36}'/i
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should respond to constellation" do
|
40
|
+
@thing_id.respond_to?(:constellation).should be_true
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should respond to its roles" do
|
44
|
+
@thing_id.respond_to?(:thing).should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should allow prevent invalid role assignment" do
|
48
|
+
lambda {
|
49
|
+
@thing.thing_id = "foo"
|
50
|
+
}.should raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should allow an existing guid to be re-used" do
|
54
|
+
@new_thing = Mod::Thing.new(@thing_id)
|
55
|
+
@new_thing.thing_id.should == @thing_id
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return the ValueType in response to .class()" do
|
59
|
+
@thing_id.class.vocabulary.should == Mod
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should allow an existing guid-identified object to be re-used" do
|
63
|
+
thing = @constellation.Thing(:new)
|
64
|
+
facets = []
|
65
|
+
facets << @constellation.ThingFacet(thing, 0)
|
66
|
+
facets << @constellation.ThingFacet(thing, 1)
|
67
|
+
facets[0].thing.should be_eql(facets[1].thing)
|
68
|
+
facets[0].thing.thing_id.should be_eql(facets[1].thing.thing_id)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activefacts-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -59,6 +59,54 @@ dependencies:
|
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 2.6.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: ruby-debug
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: debugger
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: pry
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
62
110
|
- !ruby/object:Gem::Dependency
|
63
111
|
name: rspec
|
64
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +207,7 @@ files:
|
|
159
207
|
- lib/activefacts/api/constellation.rb
|
160
208
|
- lib/activefacts/api/entity.rb
|
161
209
|
- lib/activefacts/api/exceptions.rb
|
210
|
+
- lib/activefacts/api/guid.rb
|
162
211
|
- lib/activefacts/api/instance.rb
|
163
212
|
- lib/activefacts/api/instance_index.rb
|
164
213
|
- lib/activefacts/api/numeric.rb
|
@@ -182,6 +231,8 @@ files:
|
|
182
231
|
- spec/object_type/entity_type/entity_type_spec.rb
|
183
232
|
- spec/object_type/entity_type/multipart_identification_spec.rb
|
184
233
|
- spec/object_type/value_type/autocounter_spec.rb
|
234
|
+
- spec/object_type/value_type/date_time_spec.rb
|
235
|
+
- spec/object_type/value_type/guid_spec.rb
|
185
236
|
- spec/object_type/value_type/numeric_spec.rb
|
186
237
|
- spec/object_type/value_type/value_type_spec.rb
|
187
238
|
- spec/simplecov_helper.rb
|
@@ -202,7 +253,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
202
253
|
version: '0'
|
203
254
|
segments:
|
204
255
|
- 0
|
205
|
-
hash:
|
256
|
+
hash: 1877620921052571193
|
206
257
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
258
|
none: false
|
208
259
|
requirements:
|