activefacts-api 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|