activefacts-api 0.8.9 → 0.8.10
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/Rakefile +4 -2
- data/TODO +29 -0
- data/VERSION +1 -1
- data/lib/activefacts/api.rb +2 -2
- data/lib/activefacts/api/constellation.rb +51 -19
- data/lib/activefacts/api/entity.rb +151 -93
- data/lib/activefacts/api/instance.rb +17 -9
- data/lib/activefacts/api/instance_index.rb +36 -35
- data/lib/activefacts/api/numeric.rb +30 -18
- data/lib/activefacts/api/object_type.rb +109 -101
- data/lib/activefacts/api/role.rb +62 -25
- data/lib/activefacts/api/role_values.rb +0 -58
- data/lib/activefacts/api/standard_types.rb +14 -5
- data/lib/activefacts/api/value.rb +22 -19
- data/lib/activefacts/api/vocabulary.rb +12 -9
- data/lib/activefacts/tracer.rb +109 -0
- data/spec/{api/autocounter_spec.rb → autocounter_spec.rb} +9 -4
- data/spec/constellation_spec.rb +434 -0
- data/spec/{api/entity_type_spec.rb → entity_type_spec.rb} +1 -0
- data/spec/identification_spec.rb +401 -0
- data/spec/instance_spec.rb +384 -0
- data/spec/role_values_spec.rb +409 -0
- data/spec/{api/roles_spec.rb → roles_spec.rb} +49 -10
- data/spec/{api/value_type_spec.rb → value_type_spec.rb} +1 -0
- metadata +36 -24
- data/lib/activefacts/api/role_proxy.rb +0 -71
- data/spec/api/constellation_spec.rb +0 -129
- data/spec/api/instance_spec.rb +0 -462
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activefacts-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 43
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 8
|
9
|
-
-
|
10
|
-
version: 0.8.
|
9
|
+
- 10
|
10
|
+
version: 0.8.10
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Clifford Heath
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-06-27 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: rspec
|
@@ -66,6 +65,22 @@ dependencies:
|
|
66
65
|
version: 1.5.2
|
67
66
|
type: :development
|
68
67
|
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rdoc
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 27
|
77
|
+
segments:
|
78
|
+
- 2
|
79
|
+
- 4
|
80
|
+
- 2
|
81
|
+
version: 2.4.2
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
69
84
|
description: |
|
70
85
|
|
71
86
|
The ActiveFacts API is a Ruby DSL for managing constellations of elementary facts.
|
@@ -82,6 +97,7 @@ extensions: []
|
|
82
97
|
extra_rdoc_files:
|
83
98
|
- LICENSE.txt
|
84
99
|
- README.rdoc
|
100
|
+
- TODO
|
85
101
|
files:
|
86
102
|
- .document
|
87
103
|
- .rspec
|
@@ -97,20 +113,22 @@ files:
|
|
97
113
|
- lib/activefacts/api/numeric.rb
|
98
114
|
- lib/activefacts/api/object_type.rb
|
99
115
|
- lib/activefacts/api/role.rb
|
100
|
-
- lib/activefacts/api/role_proxy.rb
|
101
116
|
- lib/activefacts/api/role_values.rb
|
102
117
|
- lib/activefacts/api/standard_types.rb
|
103
118
|
- lib/activefacts/api/support.rb
|
104
119
|
- lib/activefacts/api/value.rb
|
105
120
|
- lib/activefacts/api/vocabulary.rb
|
106
|
-
-
|
107
|
-
- spec/
|
108
|
-
- spec/
|
109
|
-
- spec/
|
110
|
-
- spec/
|
111
|
-
- spec/
|
121
|
+
- lib/activefacts/tracer.rb
|
122
|
+
- spec/autocounter_spec.rb
|
123
|
+
- spec/constellation_spec.rb
|
124
|
+
- spec/entity_type_spec.rb
|
125
|
+
- spec/identification_spec.rb
|
126
|
+
- spec/instance_spec.rb
|
127
|
+
- spec/role_values_spec.rb
|
128
|
+
- spec/roles_spec.rb
|
112
129
|
- spec/spec_helper.rb
|
113
|
-
|
130
|
+
- spec/value_type_spec.rb
|
131
|
+
- TODO
|
114
132
|
homepage: http://github.com/cjheath/activefacts-api
|
115
133
|
licenses:
|
116
134
|
- MIT
|
@@ -140,15 +158,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
158
|
requirements: []
|
141
159
|
|
142
160
|
rubyforge_project:
|
143
|
-
rubygems_version: 1.
|
161
|
+
rubygems_version: 1.8.5
|
144
162
|
signing_key:
|
145
163
|
specification_version: 3
|
146
|
-
summary: A
|
147
|
-
test_files:
|
148
|
-
|
149
|
-
- spec/api/constellation_spec.rb
|
150
|
-
- spec/api/entity_type_spec.rb
|
151
|
-
- spec/api/instance_spec.rb
|
152
|
-
- spec/api/roles_spec.rb
|
153
|
-
- spec/api/value_type_spec.rb
|
154
|
-
- spec/spec_helper.rb
|
164
|
+
summary: A fact-based data model DSL and API
|
165
|
+
test_files: []
|
166
|
+
|
@@ -1,71 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# ActiveFacts Runtime API
|
3
|
-
# RoleProxy class, still somewhat experimental
|
4
|
-
#
|
5
|
-
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
6
|
-
#
|
7
|
-
require 'delegate'
|
8
|
-
|
9
|
-
module ActiveFacts
|
10
|
-
module API
|
11
|
-
#
|
12
|
-
# When you use the accessor method created by has_one, one_to_one, or maybe, you get a RoleProxy for the actual value.
|
13
|
-
# This behaves almost exactly as the value, but it knows through which role you fetched it.
|
14
|
-
# That will allow it to verbalise itself using the correct reading for that role.
|
15
|
-
#
|
16
|
-
# Don't use "SomeClass === role_value" to test the type, use "role_value.is_a?(SomeClass)" instead.
|
17
|
-
#
|
18
|
-
# In future, retrieving a value by indexing into a RoleValues array will do the same thing.
|
19
|
-
#
|
20
|
-
class RoleProxy < SimpleDelegator
|
21
|
-
def initialize(role, o = nil) #:nodoc:
|
22
|
-
@role = role # REVISIT: Use this to implement verbalise()
|
23
|
-
__setobj__(o)
|
24
|
-
end
|
25
|
-
|
26
|
-
def method_missing(m, *a, &b) #:nodoc:
|
27
|
-
begin
|
28
|
-
super # Delegate first
|
29
|
-
rescue NoMethodError => e
|
30
|
-
__getobj__.method_missing(m, *a, &b)
|
31
|
-
rescue => e
|
32
|
-
raise
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def class #:nodoc:
|
37
|
-
__getobj__.class
|
38
|
-
end
|
39
|
-
|
40
|
-
def is_a? klass #:nodoc:
|
41
|
-
__getobj__.is_a? klass
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_s #:nodoc:
|
45
|
-
__getobj__.to_s
|
46
|
-
end
|
47
|
-
|
48
|
-
# This is strongly deprecated, and omitting it doesn't seem to hurt:
|
49
|
-
#def object_id #:nodoc:
|
50
|
-
# __getobj__.object_id
|
51
|
-
#end
|
52
|
-
|
53
|
-
# REVISIT: Should Proxies hash and eql? the same as their wards?
|
54
|
-
def hash #:nodoc:
|
55
|
-
__getobj__.hash ^ self.class.hash
|
56
|
-
end
|
57
|
-
|
58
|
-
def eql?(o) #:nodoc:
|
59
|
-
self.class == o.class and __getobj__.eql?(o)
|
60
|
-
end
|
61
|
-
|
62
|
-
def ==(o) #:nodoc:
|
63
|
-
__getobj__.==(o)
|
64
|
-
end
|
65
|
-
|
66
|
-
def inspect #:nodoc:
|
67
|
-
"Proxy:#{__getobj__.inspect}"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,129 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# ActiveFacts tests: Constellation instances in the Runtime API
|
3
|
-
# Copyright (c) 2008 Clifford Heath. Read the LICENSE file.
|
4
|
-
#
|
5
|
-
|
6
|
-
require 'activefacts/api'
|
7
|
-
|
8
|
-
describe "A Constellation instance" do
|
9
|
-
before :each do
|
10
|
-
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
11
|
-
module Mod
|
12
|
-
@base_types = [
|
13
|
-
Int, Real, AutoCounter, String, Date, DateTime
|
14
|
-
]
|
15
|
-
|
16
|
-
# Create a value type and a subtype of that value type for each base type:
|
17
|
-
@base_types.each do |base_type|
|
18
|
-
eval %Q{
|
19
|
-
class #{base_type.name}Value < #{base_type.name}
|
20
|
-
value_type
|
21
|
-
end
|
22
|
-
|
23
|
-
class #{base_type.name}SubValue < #{base_type.name}Value
|
24
|
-
# Note no new "value_type" is required here, it comes through inheritance
|
25
|
-
end
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
class Name < StringValue
|
30
|
-
value_type
|
31
|
-
#has_one :attr, Name
|
32
|
-
end
|
33
|
-
|
34
|
-
class LegalEntity
|
35
|
-
identified_by :name
|
36
|
-
has_one :name
|
37
|
-
end
|
38
|
-
|
39
|
-
class SurrogateId
|
40
|
-
identified_by :auto_counter_value
|
41
|
-
has_one :auto_counter_value
|
42
|
-
end
|
43
|
-
|
44
|
-
class Company < LegalEntity
|
45
|
-
supertypes SurrogateId
|
46
|
-
end
|
47
|
-
|
48
|
-
class Person < LegalEntity
|
49
|
-
identified_by :name, :family_name # REVISIT: want a way to role_alias :name, :given_name
|
50
|
-
supertypes SurrogateId
|
51
|
-
|
52
|
-
has_one :family_name, :class => Name
|
53
|
-
end
|
54
|
-
end
|
55
|
-
@constellation = ActiveFacts::API::Constellation.new(Mod)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should support fetching its vocabulary" do
|
59
|
-
@constellation.vocabulary.should == Mod
|
60
|
-
end
|
61
|
-
|
62
|
-
# it "should support fetching its query" do
|
63
|
-
# pending
|
64
|
-
# @constellation.query.should == Mod
|
65
|
-
# end
|
66
|
-
|
67
|
-
it "should support methods to construct instances of any object_type" do
|
68
|
-
name = foo = acme = fred_fly = nil
|
69
|
-
lambda {
|
70
|
-
name = @constellation.Name("foo")
|
71
|
-
foo = @constellation.LegalEntity("foo")
|
72
|
-
acme = @constellation.Company("Acme, Inc")
|
73
|
-
fred_fly = @constellation.Person("fred", "fly")
|
74
|
-
}.should_not raise_error
|
75
|
-
name.class.should == Mod::Name
|
76
|
-
name.constellation.should == @constellation
|
77
|
-
foo.class.should == Mod::LegalEntity
|
78
|
-
foo.constellation.should == @constellation
|
79
|
-
acme.class.should == Mod::Company
|
80
|
-
acme.constellation.should == @constellation
|
81
|
-
fred_fly.class.should == Mod::Person
|
82
|
-
fred_fly.constellation.should == @constellation
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should re-use instances constructed the same way" do
|
86
|
-
name1 = @constellation.Name("foo")
|
87
|
-
foo1 = @constellation.LegalEntity("foo")
|
88
|
-
acme1 = @constellation.Company("Acme, Inc")
|
89
|
-
fred_fly1 = @constellation.Person("fred", "fly")
|
90
|
-
|
91
|
-
name2 = @constellation.Name("foo")
|
92
|
-
foo2 = @constellation.LegalEntity("foo")
|
93
|
-
acme2 = @constellation.Company("Acme, Inc")
|
94
|
-
fred_fly2 = @constellation.Person("fred", "fly")
|
95
|
-
|
96
|
-
name1.object_id.should == name2.object_id
|
97
|
-
foo1.object_id.should == foo2.object_id
|
98
|
-
acme1.object_id.should == acme2.object_id
|
99
|
-
fred_fly1.object_id.should == fred_fly2.object_id
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should index value instances, including by its superclasses" do
|
103
|
-
baz = @constellation.Name("baz")
|
104
|
-
@constellation.Name.keys.sort.should == ["baz"]
|
105
|
-
|
106
|
-
@constellation.StringValue.keys.sort.should == ["baz"]
|
107
|
-
end
|
108
|
-
|
109
|
-
it "should index entity instances, including by its superclass and secondary supertypes" do
|
110
|
-
name = "Acme, Inc"
|
111
|
-
fred = "Fred"
|
112
|
-
fly = "Fly"
|
113
|
-
acme = @constellation.Company name, :auto_counter_value => :new
|
114
|
-
fred_fly = @constellation.Person fred, fly, :auto_counter_value => :new
|
115
|
-
|
116
|
-
# REVISIT: This should be illegal:
|
117
|
-
#fred_fly.auto_counter_value = :new
|
118
|
-
|
119
|
-
@constellation.Person.keys.sort.should == [[fred, fly]]
|
120
|
-
@constellation.Company.keys.sort.should == [[name]]
|
121
|
-
|
122
|
-
@constellation.LegalEntity.keys.sort.should be_include([name])
|
123
|
-
@constellation.LegalEntity.keys.sort.should be_include([fred])
|
124
|
-
|
125
|
-
@constellation.SurrogateId.values.should be_include(acme)
|
126
|
-
@constellation.SurrogateId.values.should be_include(fred_fly)
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
data/spec/api/instance_spec.rb
DELETED
@@ -1,462 +0,0 @@
|
|
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 "An instance of every type of ObjectType" do
|
8
|
-
before :each do
|
9
|
-
Object.send :remove_const, :Mod if Object.const_defined?("Mod")
|
10
|
-
module Mod
|
11
|
-
# These are the base value types we're going to test:
|
12
|
-
@base_types = [
|
13
|
-
Int, Real, AutoCounter, String, Date, DateTime, Decimal
|
14
|
-
]
|
15
|
-
|
16
|
-
# Construct the names of the roles they play:
|
17
|
-
@base_type_roles = @base_types.map do |t|
|
18
|
-
t.name.snakecase
|
19
|
-
end
|
20
|
-
@role_names = @base_type_roles.inject([]) {|a, t|
|
21
|
-
a << :"#{t}_value"
|
22
|
-
} +
|
23
|
-
@base_type_roles.inject([]) {|a, t|
|
24
|
-
a << :"#{t}_sub_value"
|
25
|
-
}
|
26
|
-
|
27
|
-
# Create a value type and a subtype of that value type for each base type:
|
28
|
-
@base_types.each do |base_type|
|
29
|
-
eval %Q{
|
30
|
-
class #{base_type.name}Value < #{base_type.name}
|
31
|
-
value_type
|
32
|
-
end
|
33
|
-
|
34
|
-
class #{base_type.name}SubValue < #{base_type.name}Value
|
35
|
-
# Note no new "value_type" is required here, it comes through inheritance
|
36
|
-
end
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
|
-
# Create a TestByX, TestByXSub, and TestSubByX class for all base types X
|
41
|
-
# Each class has a has_one and a one_to_one for all roles.
|
42
|
-
# and is identified by the has_one :x role
|
43
|
-
@base_types.each do |base_type|
|
44
|
-
code = %Q{
|
45
|
-
class TestBy#{base_type.name}
|
46
|
-
identified_by :#{base_type.name.snakecase}_value#{
|
47
|
-
@role_names.map do |role_name|
|
48
|
-
%Q{
|
49
|
-
has_one :#{role_name}
|
50
|
-
one_to_one :one_#{role_name}, :class => #{role_name.to_s.camelcase}}
|
51
|
-
end*""
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
class TestBy#{base_type.name}Sub
|
56
|
-
identified_by :#{base_type.name.snakecase}_sub_value#{
|
57
|
-
@role_names.map do |role_name|
|
58
|
-
%Q{
|
59
|
-
has_one :#{role_name}
|
60
|
-
one_to_one :one_#{role_name}, :class => #{role_name.to_s.camelcase}}
|
61
|
-
end*""
|
62
|
-
}
|
63
|
-
end
|
64
|
-
|
65
|
-
class TestSubBy#{base_type.name} < TestBy#{base_type.name}
|
66
|
-
# Entity subtypes, inherit identification and all roles
|
67
|
-
end
|
68
|
-
|
69
|
-
class TestBy#{base_type.name}Entity
|
70
|
-
identified_by :test_by_#{base_type.name.snakecase}
|
71
|
-
one_to_one :test_by_#{base_type.name.snakecase}
|
72
|
-
end}
|
73
|
-
eval code
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Simple Values
|
78
|
-
@int = 0
|
79
|
-
@real = 0.0
|
80
|
-
@auto_counter = 0
|
81
|
-
@new_auto_counter = :new
|
82
|
-
@string = "zero"
|
83
|
-
@date = [2008, 04, 19]
|
84
|
-
@date_time = [2008, 04, 19, 10, 28, 14]
|
85
|
-
|
86
|
-
# Value Type instances
|
87
|
-
@int_value = Mod::IntValue.new(1)
|
88
|
-
@real_value = Mod::RealValue.new(1.0)
|
89
|
-
@auto_counter_value = Mod::AutoCounterValue.new(1)
|
90
|
-
@new_auto_counter_value = Mod::AutoCounterValue.new(:new)
|
91
|
-
@string_value = Mod::StringValue.new("one")
|
92
|
-
@date_value = Mod::DateValue.new(2008, 04, 20)
|
93
|
-
@date_time_value = Mod::DateTimeValue.new(2008, 04, 20, 10, 28, 14)
|
94
|
-
|
95
|
-
# Value SubType instances
|
96
|
-
@int_sub_value = Mod::IntSubValue.new(4)
|
97
|
-
@real_sub_value = Mod::RealSubValue.new(4.0)
|
98
|
-
@auto_counter_sub_value = Mod::AutoCounterSubValue.new(4)
|
99
|
-
@auto_counter_sub_value_new = Mod::AutoCounterSubValue.new(:new)
|
100
|
-
@string_sub_value = Mod::StringSubValue.new("five")
|
101
|
-
@date_sub_value = Mod::DateSubValue.new(2008, 04, 25)
|
102
|
-
@date_time_sub_value = Mod::DateTimeSubValue.new(2008, 04, 26, 10, 28, 14)
|
103
|
-
|
104
|
-
# Entities identified by Value Type, SubType and Entity-by-value-type instances
|
105
|
-
@test_by_int = Mod::TestByInt.new(2)
|
106
|
-
@test_by_real = Mod::TestByReal.new(2.0)
|
107
|
-
@test_by_auto_counter = Mod::TestByAutoCounter.new(2)
|
108
|
-
@test_by_auto_counter_new = Mod::TestByAutoCounter.new(:new)
|
109
|
-
@test_by_string = Mod::TestByString.new("two")
|
110
|
-
@test_by_date = Mod::TestByDate.new(Date.new(2008,04,28))
|
111
|
-
#@test_by_date = Mod::TestByDate.new(2008,04,28)
|
112
|
-
@test_by_date_time = Mod::TestByDateTime.new(2008,04,28,10,28,15)
|
113
|
-
#@test_by_date_time = Mod::TestByDateTime.new(DateTime.new(2008,04,28,10,28,15))
|
114
|
-
|
115
|
-
@test_by_int_sub = Mod::TestByIntSub.new(2)
|
116
|
-
@test_by_real_sub = Mod::TestByRealSub.new(5.0)
|
117
|
-
@test_by_auto_counter_sub = Mod::TestByAutoCounterSub.new(6)
|
118
|
-
@test_by_auto_counter_new_sub = Mod::TestByAutoCounterSub.new(:new)
|
119
|
-
@test_by_string_sub = Mod::TestByStringSub.new("six")
|
120
|
-
@test_by_date_sub = Mod::TestByDateSub.new(Date.new(2008,04,27))
|
121
|
-
@test_by_date_time_sub = Mod::TestByDateTimeSub.new(2008,04,29,10,28,15)
|
122
|
-
|
123
|
-
@test_by_int_entity = Mod::TestByIntEntity.new(@test_by_int)
|
124
|
-
@test_by_real_entity = Mod::TestByRealEntity.new(@test_by_real)
|
125
|
-
@test_by_auto_counter_entity = Mod::TestByAutoCounterEntity.new(@test_by_auto_counter)
|
126
|
-
@test_by_auto_counter_new_entity = Mod::TestByAutoCounterEntity.new(@test_by_auto_counter_new)
|
127
|
-
@test_by_string_entity = Mod::TestByStringEntity.new(@test_by_string)
|
128
|
-
@test_by_date_entity = Mod::TestByDateEntity.new(@test_by_date)
|
129
|
-
@test_by_date_time_entity = Mod::TestByDateTimeEntity.new(@test_by_date_time)
|
130
|
-
|
131
|
-
# Entity subtypes
|
132
|
-
@test_sub_by_int = Mod::TestSubByInt.new(2)
|
133
|
-
@test_sub_by_real = Mod::TestSubByReal.new(2.0)
|
134
|
-
@test_sub_by_auto_counter = Mod::TestSubByAutoCounter.new(2)
|
135
|
-
@test_sub_by_auto_counter_new = Mod::TestSubByAutoCounter.new(:new)
|
136
|
-
@test_sub_by_string = Mod::TestSubByString.new("two")
|
137
|
-
@test_sub_by_date = Mod::TestSubByDate.new(Date.new(2008,04,28))
|
138
|
-
@test_sub_by_date_time = Mod::TestSubByDateTime.new(2008,04,28,10,28,15)
|
139
|
-
|
140
|
-
# These arrays get zipped together in various ways. Keep them aligned.
|
141
|
-
@values = [
|
142
|
-
@int, @real, @auto_counter, @new_auto_counter,
|
143
|
-
@string, @date, @date_time,
|
144
|
-
]
|
145
|
-
@classes = [
|
146
|
-
Int, Real, AutoCounter, AutoCounter,
|
147
|
-
String, Date, DateTime,
|
148
|
-
]
|
149
|
-
@value_types = [
|
150
|
-
Mod::IntValue, Mod::RealValue, Mod::AutoCounterValue, Mod::AutoCounterValue,
|
151
|
-
Mod::StringValue, Mod::DateValue, Mod::DateTimeValue,
|
152
|
-
Mod::IntSubValue, Mod::RealSubValue, Mod::AutoCounterSubValue, Mod::AutoCounterSubValue,
|
153
|
-
Mod::StringSubValue, Mod::DateSubValue, Mod::DateTimeSubValue,
|
154
|
-
]
|
155
|
-
@value_instances = [
|
156
|
-
@int_value, @real_value, @auto_counter_value, @new_auto_counter_value,
|
157
|
-
@string_value, @date_value, @date_time_value,
|
158
|
-
@int_sub_value, @real_sub_value, @auto_counter_sub_value, @auto_counter_sub_value_new,
|
159
|
-
@string_sub_value, @date_sub_value, @date_time_sub_value,
|
160
|
-
@int_value, @real_value, @auto_counter_value, @new_auto_counter_value,
|
161
|
-
@string_value, @date_value, @date_time_value,
|
162
|
-
]
|
163
|
-
@entity_types = [
|
164
|
-
Mod::TestByInt, Mod::TestByReal, Mod::TestByAutoCounter, Mod::TestByAutoCounter,
|
165
|
-
Mod::TestByString, Mod::TestByDate, Mod::TestByDateTime,
|
166
|
-
Mod::TestByIntSub, Mod::TestByRealSub, Mod::TestByAutoCounterSub, Mod::TestByAutoCounterSub,
|
167
|
-
Mod::TestByStringSub, Mod::TestByDateSub, Mod::TestByDateTimeSub,
|
168
|
-
Mod::TestSubByInt, Mod::TestSubByReal, Mod::TestSubByAutoCounter, Mod::TestSubByAutoCounter,
|
169
|
-
Mod::TestSubByString, Mod::TestSubByDate, Mod::TestSubByDateTime,
|
170
|
-
]
|
171
|
-
@entities = [
|
172
|
-
@test_by_int, @test_by_real, @test_by_auto_counter, @test_by_auto_counter_new,
|
173
|
-
@test_by_string, @test_by_date, @test_by_date_time,
|
174
|
-
@test_by_int_sub, @test_by_real_sub, @test_by_auto_counter_sub, @test_by_auto_counter_new_sub,
|
175
|
-
@test_by_string_sub, @test_by_date_sub, @test_by_date_time_sub,
|
176
|
-
@test_sub_by_int, @test_sub_by_real, @test_sub_by_auto_counter, @test_sub_by_auto_counter_new,
|
177
|
-
@test_sub_by_string, @test_sub_by_date, @test_sub_by_date_time,
|
178
|
-
]
|
179
|
-
@entities_by_entity = [
|
180
|
-
@test_by_int_entity,
|
181
|
-
@test_by_real_entity,
|
182
|
-
@test_by_auto_counter_entity,
|
183
|
-
@test_by_auto_counter_new_entity,
|
184
|
-
@test_by_string_entity,
|
185
|
-
@test_by_date_entity,
|
186
|
-
@test_by_date_time_entity,
|
187
|
-
]
|
188
|
-
@entities_by_entity_types = [
|
189
|
-
Mod::TestByIntEntity, Mod::TestByRealEntity, Mod::TestByAutoCounterEntity, Mod::TestByAutoCounterEntity,
|
190
|
-
Mod::TestByStringEntity, Mod::TestByDateEntity, Mod::TestByDateTimeEntity,
|
191
|
-
]
|
192
|
-
@test_role_names = [
|
193
|
-
:int_value, :real_value, :auto_counter_value, :auto_counter_value,
|
194
|
-
:string_value, :date_value, :date_time_value,
|
195
|
-
:int_sub_value, :real_sub_value, :auto_counter_sub_value, :auto_counter_sub_value,
|
196
|
-
:string_sub_value, :date_sub_value, :date_time_sub_value,
|
197
|
-
:int_value, :real_value, :auto_counter_value, :auto_counter_value,
|
198
|
-
:string_value, :date_value, :date_time_value,
|
199
|
-
]
|
200
|
-
@role_values = [
|
201
|
-
3, 3.0, 6, 7,
|
202
|
-
"three", Date.new(2008,4,21), DateTime.new(2008,4,22,10,28,16),
|
203
|
-
]
|
204
|
-
@subtype_role_instances = [
|
205
|
-
Mod::IntSubValue.new(6), Mod::RealSubValue.new(6.0),
|
206
|
-
Mod::AutoCounterSubValue.new(:new), Mod::AutoCounterSubValue.new(8),
|
207
|
-
Mod::StringSubValue.new("seven"),
|
208
|
-
Mod::DateSubValue.new(2008,4,29), Mod::DateTimeSubValue.new(2008,4,30,10,28,16)
|
209
|
-
]
|
210
|
-
end
|
211
|
-
|
212
|
-
it "if a value type, should verbalise" do
|
213
|
-
@value_types.each do |value_type|
|
214
|
-
#puts "#{value_type} verbalises as #{value_type.verbalise}"
|
215
|
-
value_type.respond_to?(:verbalise).should be_true
|
216
|
-
verbalisation = value_type.verbalise
|
217
|
-
verbalisation.should =~ %r{\b#{value_type.basename}\b}
|
218
|
-
verbalisation.should =~ %r{\b#{value_type.superclass.basename}\b}
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
it "if an entity type, should verbalise" do
|
223
|
-
@entity_types.each do |entity_type|
|
224
|
-
#puts entity_type.verbalise
|
225
|
-
entity_type.respond_to?(:verbalise).should be_true
|
226
|
-
verbalisation = entity_type.verbalise
|
227
|
-
verbalisation.should =~ %r{\b#{entity_type.basename}\b}
|
228
|
-
|
229
|
-
# All identifying roles should be in the verbalisation.
|
230
|
-
# Strictly this should be the role name, but we don't set names here.
|
231
|
-
entity_type.identifying_role_names.each do |ir|
|
232
|
-
role = entity_type.roles(ir)
|
233
|
-
role.should_not be_nil
|
234
|
-
counterpart_object_type = role.counterpart_object_type
|
235
|
-
verbalisation.should =~ %r{\b#{counterpart_object_type.basename}\b}
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
it "if a value, should verbalise" do
|
241
|
-
@value_instances.each do |value|
|
242
|
-
#puts value.verbalise
|
243
|
-
value.respond_to?(:verbalise).should be_true
|
244
|
-
verbalisation = value.verbalise
|
245
|
-
verbalisation.should =~ %r{\b#{value.class.basename}\b}
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
it "if an entity, should respond to verbalise" do
|
250
|
-
(@entities+@entities_by_entity).each do |entity|
|
251
|
-
#puts entity.verbalise
|
252
|
-
entity.respond_to?(:verbalise).should be_true
|
253
|
-
verbalisation = entity.verbalise
|
254
|
-
verbalisation.should =~ %r{\b#{entity.class.basename}\b}
|
255
|
-
entity.class.identifying_role_names.each do |ir|
|
256
|
-
role = entity.class.roles(ir)
|
257
|
-
role.should_not be_nil
|
258
|
-
counterpart_object_type = role.counterpart_object_type
|
259
|
-
verbalisation.should =~ %r{\b#{counterpart_object_type.basename}\b}
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
it "should respond to constellation" do
|
265
|
-
(@value_instances+@entities+@entities_by_entity).each do |instance|
|
266
|
-
instance.respond_to?(:constellation).should be_true
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
it "should respond to all its roles" do
|
271
|
-
@entities.each do |entity|
|
272
|
-
@test_role_names.each do |role_name|
|
273
|
-
entity.respond_to?(role_name).should be_true
|
274
|
-
entity.respond_to?(:"#{role_name}=").should be_true
|
275
|
-
entity.respond_to?(:"one_#{role_name}").should be_true
|
276
|
-
entity.respond_to?(:"one_#{role_name}=").should be_true
|
277
|
-
end
|
278
|
-
end
|
279
|
-
@entities_by_entity.each do |entity|
|
280
|
-
role = entity.class.roles(entity.class.identifying_role_names[0])
|
281
|
-
role_name = role.name
|
282
|
-
entity.respond_to?(role_name).should be_true
|
283
|
-
entity.respond_to?(:"#{role_name}=").should be_true
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
it "should return the ObjectType in response to .class()" do
|
288
|
-
@value_types.zip(@value_instances).each do |object_type, instance|
|
289
|
-
instance.class.should == object_type
|
290
|
-
end
|
291
|
-
@entity_types.zip(@entities).each do |object_type, instance|
|
292
|
-
instance.class.should == object_type
|
293
|
-
end
|
294
|
-
@entities_by_entity_types.zip(@entities_by_entity).each do |object_type, instance|
|
295
|
-
instance.class.should == object_type
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
it "should return the module in response to .vocabulary()" do
|
300
|
-
(@value_types+@entity_types).zip((@value_instances+@entities+@entities_by_entity)).each do |object_type, instance|
|
301
|
-
instance.class.vocabulary.should == Mod
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
it "each entity type should be able to be constructed using simple values" do
|
306
|
-
@entity_types.zip(@values+@values+@values, @classes+@classes+@classes).each do |entity_type, value, klass|
|
307
|
-
# An identifier parameter can be an array containing a simple value too
|
308
|
-
[ value,
|
309
|
-
Array === value ? nil : [value],
|
310
|
-
# entity_type.new(value) # REVISIT: It's not yet the case that an instance of the correct type can be used as a constructor parameter
|
311
|
-
].compact.each do |value|
|
312
|
-
e = nil
|
313
|
-
lambda {
|
314
|
-
#puts "Constructing #{entity_type} using #{value.class} #{value.inspect}:"
|
315
|
-
e = entity_type.new(value)
|
316
|
-
}.should_not raise_error
|
317
|
-
# Verify that the identifying role has a equivalent value (except AutoCounter):
|
318
|
-
role_name = entity_type.identifying_role_names[0]
|
319
|
-
role = entity_type.roles(role_name)
|
320
|
-
counterpart_object_type = role.counterpart_object_type
|
321
|
-
player_superclasses = [ counterpart_object_type.superclass, counterpart_object_type.superclass.superclass ]
|
322
|
-
e.send(role_name).should == klass.new(*value) unless player_superclasses.include?(AutoCounter)
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
it "should allow its non-identifying roles to be assigned values" do
|
328
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
329
|
-
@test_role_names.zip(@role_values).each do |role_name, value|
|
330
|
-
# No roles of ValueType instances are tested in this file:
|
331
|
-
raise hell unless entity.class.included_modules.include?(ActiveFacts::API::Entity)
|
332
|
-
next if entity.class.identifying_role_names.include?(role_name)
|
333
|
-
lambda {
|
334
|
-
begin
|
335
|
-
entity.send(:"#{role_name}=", value)
|
336
|
-
rescue => e
|
337
|
-
raise
|
338
|
-
end
|
339
|
-
}.should_not raise_error
|
340
|
-
lambda {
|
341
|
-
entity.send(:"one_#{role_name}=", value)
|
342
|
-
}.should_not raise_error
|
343
|
-
end
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
it "that is an entity type should not allow its identifying roles to be re-assigned" do
|
348
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
349
|
-
@test_role_names.zip(@role_values).each do |role_name, value|
|
350
|
-
if entity.class.identifying_role_names.include?(role_name) && entity.send(role_name) != nil && value != nil
|
351
|
-
lambda {
|
352
|
-
entity.send(:"#{role_name}=", value)
|
353
|
-
}.should raise_error
|
354
|
-
end
|
355
|
-
one_role = :"one_#{role_name}"
|
356
|
-
if entity.class.identifying_role_names.include?(one_role) && entity.send(one_role) != nil
|
357
|
-
lambda {
|
358
|
-
entity.send(:"one_#{role_name}=", value)
|
359
|
-
}.should raise_error
|
360
|
-
end
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
it "that is an entity type should allow its identifying roles to be assigned to and from nil" do
|
366
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
367
|
-
@test_role_names.zip(@role_values).each do |role_name, value|
|
368
|
-
if entity.class.identifying_role_names.include?(role_name)
|
369
|
-
# Nullify the value first:
|
370
|
-
entity.send(:"#{role_name}=", nil)
|
371
|
-
lambda {
|
372
|
-
entity.send(:"#{role_name}=", value)
|
373
|
-
}.should_not raise_error
|
374
|
-
end
|
375
|
-
one_role = :"one_#{role_name}"
|
376
|
-
if entity.class.identifying_role_names.include?(one_role) && entity.send(one_role) == nil
|
377
|
-
entity.send(one_role, nil)
|
378
|
-
lambda {
|
379
|
-
entity.send(one_role, value)
|
380
|
-
}.should_not raise_error
|
381
|
-
end
|
382
|
-
end
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
it "should allow its non-identifying roles to be assigned instances" do
|
387
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
388
|
-
@test_role_names.zip(@value_types, @role_values).each do |role_name, klass, value|
|
389
|
-
next unless value
|
390
|
-
next if role_name == identifying_role
|
391
|
-
instance = klass.new(value)
|
392
|
-
lambda {
|
393
|
-
entity.send(:"#{role_name}=", instance)
|
394
|
-
}.should_not raise_error
|
395
|
-
entity.send(role_name).class.should == klass
|
396
|
-
lambda {
|
397
|
-
entity.send(:"one_#{role_name}=", instance)
|
398
|
-
}.should_not raise_error
|
399
|
-
entity.send(:"one_#{role_name}").class.should == klass
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
it "should allow its non-identifying roles to be assigned instances of value subtypes, retaining the subtype" do
|
405
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
406
|
-
@test_role_names.zip(@subtype_role_instances).each do |role_name, instance|
|
407
|
-
next unless instance
|
408
|
-
next if role_name == identifying_role
|
409
|
-
lambda {
|
410
|
-
entity.send(:"#{role_name}=", instance)
|
411
|
-
}.should_not raise_error
|
412
|
-
entity.send(role_name).class.should == instance.class
|
413
|
-
lambda {
|
414
|
-
entity.send(:"one_#{role_name}=", instance)
|
415
|
-
}.should_not raise_error
|
416
|
-
entity.send(:"one_#{role_name}").class.should == instance.class
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
it "should add to has_one's counterpart role when non-identifying roles are assigned values" do
|
422
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
423
|
-
@test_role_names.zip(@role_values).each do |role_name, value|
|
424
|
-
next if role_name == identifying_role or !value
|
425
|
-
|
426
|
-
# Test the has_one role:
|
427
|
-
role = entity.class.roles(role_name)
|
428
|
-
old_counterpart = entity.send(:"#{role_name}")
|
429
|
-
entity.send(:"#{role_name}=", value)
|
430
|
-
counterpart = entity.send(:"#{role_name}")
|
431
|
-
old_counterpart.should_not == counterpart
|
432
|
-
counterpart.send(role.counterpart.name).should be_include(entity)
|
433
|
-
old_counterpart.send(role.counterpart.name).should_not be_include(entity) if old_counterpart
|
434
|
-
|
435
|
-
# Test the one_to_one role:
|
436
|
-
role = entity.class.roles(:"one_#{role_name}")
|
437
|
-
old_counterpart = entity.send(:"one_#{role_name}")
|
438
|
-
entity.send(:"one_#{role_name}=", value)
|
439
|
-
counterpart = entity.send(:"one_#{role_name}")
|
440
|
-
old_counterpart.should_not == counterpart # Make sure we changed it!
|
441
|
-
counterpart.send(role.counterpart.name).should == entity
|
442
|
-
old_counterpart.send(role.counterpart.name).should be_nil if old_counterpart
|
443
|
-
end
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
|
-
it "should allow its non-identifying roles to be assigned nil" do
|
448
|
-
@entities.zip(@test_role_names).each do |entity, identifying_role|
|
449
|
-
@test_role_names.zip(@role_values).each do |role_name, value|
|
450
|
-
next if role_name == identifying_role
|
451
|
-
entity.send(:"#{role_name}=", value)
|
452
|
-
lambda {
|
453
|
-
entity.send(:"#{role_name}=", nil)
|
454
|
-
}.should_not raise_error
|
455
|
-
lambda {
|
456
|
-
entity.send(:"one_#{role_name}=", nil)
|
457
|
-
}.should_not raise_error
|
458
|
-
end
|
459
|
-
end
|
460
|
-
end
|
461
|
-
|
462
|
-
end
|