rod 0.6.2 → 0.6.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 -0
- data/README.rdoc +10 -9
- data/Rakefile +15 -5
- data/changelog.txt +18 -0
- data/features/append.feature +0 -2
- data/features/basic.feature +7 -7
- data/features/collection_proxy.feature +140 -0
- data/features/flat_indexing.feature +9 -8
- data/features/{fred.feature → persistence.feature} +5 -8
- data/features/{assoc_indexing.feature → relationship_indexing.feature} +36 -0
- data/features/segmented_indexing.feature +6 -6
- data/features/steps/collection_proxy.rb +89 -0
- data/features/steps/model.rb +15 -3
- data/features/steps/rod.rb +1 -1
- data/features/support/mocha.rb +16 -0
- data/features/update.feature +263 -0
- data/lib/rod.rb +10 -2
- data/lib/rod/abstract_database.rb +49 -111
- data/lib/rod/abstract_model.rb +26 -6
- data/lib/rod/collection_proxy.rb +235 -34
- data/lib/rod/constants.rb +1 -1
- data/lib/rod/database.rb +5 -6
- data/lib/rod/exception.rb +1 -1
- data/lib/rod/index/base.rb +97 -0
- data/lib/rod/index/flat_index.rb +72 -0
- data/lib/rod/index/segmented_index.rb +100 -0
- data/lib/rod/model.rb +172 -185
- data/lib/rod/reference_updater.rb +85 -0
- data/lib/rod/utils.rb +29 -0
- data/rod.gemspec +4 -1
- data/tests/migration_create.rb +33 -12
- data/tests/migration_migrate.rb +24 -7
- data/tests/migration_model1.rb +5 -0
- data/tests/migration_model2.rb +36 -0
- data/tests/migration_verify.rb +49 -42
- data/tests/missing_class_create.rb +21 -0
- data/tests/missing_class_verify.rb +20 -0
- data/tests/properties_order_create.rb +16 -0
- data/tests/properties_order_verify.rb +17 -0
- data/tests/unit/abstract_database.rb +13 -0
- data/tests/unit/model_tests.rb +3 -3
- data/utils/convert_index.rb +1 -1
- metadata +62 -18
- data/lib/rod/segmented_index.rb +0 -85
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm: 1.9.2
|
data/README.rdoc
CHANGED
@@ -18,7 +18,7 @@ fast access for data, which rarely changes.
|
|
18
18
|
* compatibility check of data model
|
19
19
|
* autogeneration of model (based on the database metadata)
|
20
20
|
* automatic model migrations (addition/removal of properties so far)
|
21
|
-
*
|
21
|
+
* full update of the database (removal of objects not available yet)
|
22
22
|
* databases interlinking (via direct links or inverted indices)
|
23
23
|
|
24
24
|
== PROBLEMS
|
@@ -39,9 +39,9 @@ The primary reason for designing it was to create storage facility for
|
|
39
39
|
natural language dictionaries and corpora. The data in a fully fledged dictionary
|
40
40
|
is interconnected in many ways, thus the relational model (joins) introduces
|
41
41
|
unacceptable performance hit. The size of corpora forces them to be kept
|
42
|
-
on disks. The in-memory data bases are unacceptable for larg corpora
|
43
|
-
would require the data to be kept mostly in the
|
44
|
-
which is not needed
|
42
|
+
on disks. The in-memory data bases are unacceptable for larg corpora.
|
43
|
+
They would also require the data of a dictionary to be kept mostly in the
|
44
|
+
operational memory, which is not needed (in most cases only a fraction
|
45
45
|
of the data is used at the same time). That's why a storage facility which minimizes the
|
46
46
|
number of disk reads was designed. The Ruby interface facilitates it's usage.
|
47
47
|
|
@@ -51,6 +51,7 @@ number of disk reads was designed. The Ruby interface facilitates it's usage.
|
|
51
51
|
* RubyInline
|
52
52
|
* english
|
53
53
|
* ActiveModel
|
54
|
+
* bsearch
|
54
55
|
|
55
56
|
== INSTALL
|
56
57
|
|
@@ -69,7 +70,7 @@ Grab from rubygems:
|
|
69
70
|
|
70
71
|
class User < Model
|
71
72
|
field :name, :string
|
72
|
-
field :surname, :string, :index =>
|
73
|
+
field :surname, :string, :index => :flat
|
73
74
|
field :age, :integer
|
74
75
|
has_one :account
|
75
76
|
has_many :files
|
@@ -77,12 +78,12 @@ Grab from rubygems:
|
|
77
78
|
|
78
79
|
class Account < Model
|
79
80
|
field :email, :string
|
80
|
-
field :login, :string, :index =>
|
81
|
+
field :login, :string, :index => :flat
|
81
82
|
field :password, :string
|
82
83
|
end
|
83
84
|
|
84
85
|
class File < Model
|
85
|
-
field :title, :string, :index =>
|
86
|
+
field :title, :string, :index => :flat
|
86
87
|
field :data, :string
|
87
88
|
end
|
88
89
|
|
@@ -113,7 +114,7 @@ Grab from rubygems:
|
|
113
114
|
puts "Name: #{user.name} surname: #{user.surname}"
|
114
115
|
puts "login: #{user.account.login} e-mail: #{user.account.email}"
|
115
116
|
user.files.each do |file|
|
116
|
-
puts "File: #{file.title}
|
117
|
+
puts "File: #{file.title}"
|
117
118
|
end
|
118
119
|
end
|
119
120
|
|
@@ -130,7 +131,7 @@ You'll need bundler installed:
|
|
130
131
|
|
131
132
|
Then you have to fetch all the dependencies:
|
132
133
|
|
133
|
-
|
134
|
+
bundle
|
134
135
|
|
135
136
|
To run all the test simple type rake:
|
136
137
|
|
data/Rakefile
CHANGED
@@ -47,12 +47,17 @@ task :test do
|
|
47
47
|
sh "ruby tests/generate_classes_rewrite.rb"
|
48
48
|
sh "ruby tests/generate_classes_rewrite.rb"
|
49
49
|
sh "ruby tests/generate_classes_verify.rb"
|
50
|
-
sh "ruby tests/migration_create.rb"
|
51
|
-
sh "ruby tests/migration_migrate.rb"
|
52
|
-
sh "ruby tests/migration_verify.rb"
|
50
|
+
sh "ruby tests/migration_create.rb 1000"
|
51
|
+
sh "ruby tests/migration_migrate.rb 1000"
|
52
|
+
sh "ruby tests/migration_verify.rb 1000"
|
53
|
+
sh "ruby tests/missing_class_create.rb"
|
54
|
+
sh "ruby tests/missing_class_verify.rb"
|
55
|
+
sh "ruby tests/properties_order_create.rb"
|
56
|
+
sh "ruby tests/properties_order_verify.rb"
|
53
57
|
sh "ruby tests/unit/model.rb"
|
54
58
|
sh "ruby tests/unit/model_tests.rb"
|
55
59
|
sh "ruby tests/unit/database.rb"
|
60
|
+
sh "ruby tests/unit/abstract_database.rb"
|
56
61
|
end
|
57
62
|
|
58
63
|
# Should be removed some time -- specs should cover all these cases
|
@@ -61,17 +66,22 @@ task :regression_test do
|
|
61
66
|
sh "ruby tests/check_strings.rb"
|
62
67
|
end
|
63
68
|
|
69
|
+
desc "Run all specs without the ignored ones"
|
64
70
|
task :spec do
|
65
71
|
sh "bundle exec cucumber --tags ~@ignore features/*"
|
66
72
|
end
|
67
73
|
|
68
|
-
|
74
|
+
desc "Run only work-in-progress specs"
|
69
75
|
task :wip do
|
70
76
|
sh "bundle exec cucumber --tags @wip features/*"
|
71
77
|
end
|
72
78
|
|
73
|
-
desc "Clean"
|
79
|
+
desc "Clean all gems"
|
74
80
|
task :clean do
|
75
81
|
sh "rm #$gem_name*.gem"
|
76
82
|
end
|
77
83
|
|
84
|
+
desc "Show changelog from the last release"
|
85
|
+
task :changelog do
|
86
|
+
sh "git log v#{Rod::VERSION}.. --pretty=%s | tee"
|
87
|
+
end
|
data/changelog.txt
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
0.6.3
|
2
|
+
- #94 indexing of unstored object in plural assoc
|
3
|
+
- #128 incompatible schema message is more specific
|
4
|
+
- #129 check properties order
|
5
|
+
- #131 check for missing classes
|
6
|
+
- #72 update of objects' state
|
7
|
+
- #117 get rid of signed/unsigned comparison warning
|
8
|
+
- #135 refactoring of indexes
|
9
|
+
- #140 remove key argument from AbstractDatabase#read_index
|
10
|
+
- #149 CollectionProxy insert, delete, delete_at
|
11
|
+
- #154 fix configuration of mocha for cucumber
|
12
|
+
- #153 fix: field values doesn't match
|
13
|
+
- #153 111122223333 is too big for ulong on 32bit systems
|
14
|
+
- #18 use latest RubyInline and fix 'require on ... failed'
|
15
|
+
- #152 travis-ci configuration: ruby 1.9.2
|
16
|
+
- #151 missing rake dependency
|
17
|
+
- #130 fix: canonicalize path
|
18
|
+
- #124 implement empty? for CollectionProxy
|
1
19
|
0.6.2
|
2
20
|
- #127 default implementation of inspect
|
3
21
|
- #123 fix: warning on has_rdoc in gemspec
|
data/features/append.feature
CHANGED
@@ -183,8 +183,6 @@ Feature: database with append
|
|
183
183
|
And there should be 1 Caveman with the first Automobile as automobiles
|
184
184
|
And there should be 1 Caveman with the second Automobile as automobiles
|
185
185
|
|
186
|
-
# Enable for #94
|
187
|
-
@ignore
|
188
186
|
Scenario: append of has many associations with indexing with an unstored object
|
189
187
|
Same as above, but with an object which is appended to the collection
|
190
188
|
while it is not yet stored in the DB.
|
data/features/basic.feature
CHANGED
@@ -45,7 +45,7 @@ Feature: Store and load small amount of data from one class
|
|
45
45
|
And I create a Caveman
|
46
46
|
And his name is 'Fred'
|
47
47
|
And his age is '25'
|
48
|
-
And his identifier is '
|
48
|
+
And his identifier is '111222333'
|
49
49
|
And his height is '1.86'
|
50
50
|
And his symbol is ':fred'
|
51
51
|
# nil is converted to an empty string, consider using object field
|
@@ -59,7 +59,7 @@ Feature: Store and load small amount of data from one class
|
|
59
59
|
Then there should be 1 Caveman
|
60
60
|
And the name of the first Caveman should be 'Fred'
|
61
61
|
And the age of the first Caveman should be '25'
|
62
|
-
And the identifier of the first Caveman should be '
|
62
|
+
And the identifier of the first Caveman should be '111222333'
|
63
63
|
And the height of the first Caveman should be '1.86'
|
64
64
|
And the symbol of the first Caveman should be ':fred'
|
65
65
|
And the empty_string of the first Caveman should be ''
|
@@ -100,11 +100,11 @@ Feature: Store and load small amount of data from one class
|
|
100
100
|
And I create a Caveman
|
101
101
|
And his name is 'Fred'
|
102
102
|
And his age is '25'
|
103
|
-
And his identifier is '
|
103
|
+
And his identifier is '111222333'
|
104
104
|
And his height is '1.86'
|
105
105
|
Then his name should be 'Fred'
|
106
106
|
And his age should be '25'
|
107
|
-
And his identifier should be '
|
107
|
+
And his identifier should be '111222333'
|
108
108
|
And his height should be '1.86'
|
109
109
|
|
110
110
|
When database is created
|
@@ -134,9 +134,9 @@ Feature: Store and load small amount of data from one class
|
|
134
134
|
And I create a Caveman
|
135
135
|
And I fetch the first Caveman created
|
136
136
|
Then his name should be ''
|
137
|
-
And his age should be
|
138
|
-
And his identifier should be
|
139
|
-
And his height should be
|
137
|
+
And his age should be '0'
|
138
|
+
And his identifier should be '0'
|
139
|
+
And his height should be '0'
|
140
140
|
And his symbol should be nil
|
141
141
|
And his item should be nil
|
142
142
|
And his items should be empty
|
@@ -0,0 +1,140 @@
|
|
1
|
+
Feature: collection proxy specification
|
2
|
+
|
3
|
+
Scenario: appending items
|
4
|
+
Given the initial size of the collection proxy is 10
|
5
|
+
When I append a new item 10 times
|
6
|
+
Then the size of the collection proxy should be 20
|
7
|
+
And the collection proxy should behave like an array
|
8
|
+
|
9
|
+
When I append a new item 10 times
|
10
|
+
Then the size of the collection proxy should be 30
|
11
|
+
And the collection proxy should behave like an array
|
12
|
+
|
13
|
+
Scenario: inserting items
|
14
|
+
Given the initial size of the collection proxy is 10
|
15
|
+
When I insert a new item at position 0
|
16
|
+
Then the size of the collection proxy should be 11
|
17
|
+
And the collection proxy should behave like an array
|
18
|
+
When I insert a new item at position 11
|
19
|
+
Then the size of the collection proxy should be 12
|
20
|
+
And the collection proxy should behave like an array
|
21
|
+
When I insert a new item at position 5
|
22
|
+
Then the size of the collection proxy should be 13
|
23
|
+
And the collection proxy should behave like an array
|
24
|
+
When I insert an item with rod_id = 1 at position 5 3 times
|
25
|
+
Then the size of the collection proxy should be 16
|
26
|
+
And the collection proxy should behave like an array
|
27
|
+
|
28
|
+
Scenario: deleting items
|
29
|
+
Given the initial size of the collection proxy is 5
|
30
|
+
When I delete an item at position 0 2 times
|
31
|
+
Then the size of the collection proxy should be 3
|
32
|
+
And the collection proxy should behave like an array
|
33
|
+
When I delete an item with rod_id = 3
|
34
|
+
Then the size of the collection proxy should be 2
|
35
|
+
And the collection proxy should behave like an array
|
36
|
+
When I delete an item with rod_id = 3
|
37
|
+
Then the size of the collection proxy should be 2
|
38
|
+
And the collection proxy should behave like an array
|
39
|
+
When I delete an item with rod_id = 4
|
40
|
+
Then the size of the collection proxy should be 1
|
41
|
+
And the collection proxy should behave like an array
|
42
|
+
When I delete an item at position 1
|
43
|
+
Then the size of the collection proxy should be 1
|
44
|
+
And the collection proxy should behave like an array
|
45
|
+
When I delete an item at position 0
|
46
|
+
Then the collection proxy should be empty
|
47
|
+
And the collection proxy should behave like an array
|
48
|
+
|
49
|
+
Scenario: deleting and inserting items
|
50
|
+
Given the initial size of the collection proxy is 5
|
51
|
+
When I delete an item with rod_id = 1
|
52
|
+
Then the size of the collection proxy should be 4
|
53
|
+
And the collection proxy should behave like an array
|
54
|
+
When I insert a new item at position 0
|
55
|
+
Then the size of the collection proxy should be 5
|
56
|
+
And the collection proxy should behave like an array
|
57
|
+
When I insert an item with rod_id = 6 at position 1
|
58
|
+
Then the size of the collection proxy should be 6
|
59
|
+
And the collection proxy should behave like an array
|
60
|
+
When I delete an item at position 2
|
61
|
+
Then the size of the collection proxy should be 5
|
62
|
+
And the collection proxy should behave like an array
|
63
|
+
When I insert a new item at position 2
|
64
|
+
Then the size of the collection proxy should be 6
|
65
|
+
And the collection proxy should behave like an array
|
66
|
+
When I delete an item with rod_id = 6
|
67
|
+
Then the size of the collection proxy should be 4
|
68
|
+
And the collection proxy should behave like an array
|
69
|
+
When I delete an item at position 1
|
70
|
+
Then the size of the collection proxy should be 3
|
71
|
+
And the collection proxy should behave like an array
|
72
|
+
When I delete an item at position 0
|
73
|
+
Then the size of the collection proxy should be 2
|
74
|
+
And the collection proxy should behave like an array
|
75
|
+
When I delete an item at position 0
|
76
|
+
Then the size of the collection proxy should be 1
|
77
|
+
And the collection proxy should behave like an array
|
78
|
+
When I delete an item at position 0
|
79
|
+
Then the size of the collection proxy should be 0
|
80
|
+
And the collection proxy should behave like an array
|
81
|
+
When I insert a new item at position 0
|
82
|
+
Then the size of the collection proxy should be 1
|
83
|
+
And the collection proxy should behave like an array
|
84
|
+
|
85
|
+
Scenario: deleting and appending items
|
86
|
+
Given the initial size of the collection proxy is 5
|
87
|
+
When I append a new item 5 times
|
88
|
+
Then the size of the collection proxy should be 10
|
89
|
+
And the collection proxy should behave like an array
|
90
|
+
When I delete an item at position 0
|
91
|
+
Then the size of the collection proxy should be 9
|
92
|
+
And the collection proxy should behave like an array
|
93
|
+
When I delete an item with rod_id = 6
|
94
|
+
Then the size of the collection proxy should be 8
|
95
|
+
And the collection proxy should behave like an array
|
96
|
+
When I append a new item
|
97
|
+
Then the size of the collection proxy should be 9
|
98
|
+
And the collection proxy should behave like an array
|
99
|
+
|
100
|
+
Scenario: inserting, deleting and appending items
|
101
|
+
Given the initial size of the collection proxy is 5
|
102
|
+
When I append a new item 5 times
|
103
|
+
Then the size of the collection proxy should be 10
|
104
|
+
And the collection proxy should behave like an array
|
105
|
+
When I insert a new item at position 2 3 times
|
106
|
+
Then the size of the collection proxy should be 13
|
107
|
+
And the collection proxy should behave like an array
|
108
|
+
When I insert an item with rod_id = 6 at position 12
|
109
|
+
Then the size of the collection proxy should be 14
|
110
|
+
And the collection proxy should behave like an array
|
111
|
+
When I insert a new item at position 0
|
112
|
+
Then the size of the collection proxy should be 15
|
113
|
+
And the collection proxy should behave like an array
|
114
|
+
When I delete an item with rod_id = 1
|
115
|
+
Then the size of the collection proxy should be 14
|
116
|
+
And the collection proxy should behave like an array
|
117
|
+
When I delete an item with rod_id = 6
|
118
|
+
Then the size of the collection proxy should be 12
|
119
|
+
And the collection proxy should behave like an array
|
120
|
+
When I delete an item with rod_id = 6
|
121
|
+
Then the size of the collection proxy should be 12
|
122
|
+
And the collection proxy should behave like an array
|
123
|
+
When I delete an item at position 5 2 times
|
124
|
+
Then the size of the collection proxy should be 10
|
125
|
+
And the collection proxy should behave like an array
|
126
|
+
When I insert a new item at position 0 5 times
|
127
|
+
Then the size of the collection proxy should be 15
|
128
|
+
And the collection proxy should behave like an array
|
129
|
+
When I delete an item at position 10 5 times
|
130
|
+
Then the size of the collection proxy should be 10
|
131
|
+
And the collection proxy should behave like an array
|
132
|
+
When I append a new item 5 times
|
133
|
+
Then the size of the collection proxy should be 15
|
134
|
+
And the collection proxy should behave like an array
|
135
|
+
When I delete an item at position 5 15 times
|
136
|
+
Then the size of the collection proxy should be 5
|
137
|
+
And the collection proxy should behave like an array
|
138
|
+
When I delete an item at position 0 5 times
|
139
|
+
Then the collection proxy should be empty
|
140
|
+
And the collection proxy should behave like an array
|
@@ -17,19 +17,19 @@ Feature: Access to objects with indexed fields
|
|
17
17
|
And I create a Caveman
|
18
18
|
And his name is 'Fred'
|
19
19
|
And his age is '25'
|
20
|
-
And his identifier is '
|
20
|
+
And his identifier is '111222333'
|
21
21
|
And his height is '1.86'
|
22
22
|
And I store him in the database
|
23
23
|
And I create another Caveman
|
24
24
|
And his name is 'Barney'
|
25
25
|
And his age is '26'
|
26
|
-
And his identifier is '
|
26
|
+
And his identifier is '111222444'
|
27
27
|
And his height is '1.67'
|
28
28
|
And I store him in the database
|
29
29
|
And I create another Caveman
|
30
30
|
And his name is 'Wilma'
|
31
31
|
And his age is '25'
|
32
|
-
And his identifier is '
|
32
|
+
And his identifier is '111222555'
|
33
33
|
And his height is '1.67'
|
34
34
|
And I store him in the database
|
35
35
|
And I reopen database for reading
|
@@ -39,9 +39,9 @@ Feature: Access to objects with indexed fields
|
|
39
39
|
And there should be 1 Caveman with 'Barney' name
|
40
40
|
And there should be 2 Caveman(s) with '25' age
|
41
41
|
And there should be 1 Caveman with '26' age
|
42
|
-
And there should be 1 Caveman with '
|
43
|
-
And there should be 1 Caveman with '
|
44
|
-
And there should be 1 Caveman with '
|
42
|
+
And there should be 1 Caveman with '111222333' identifier
|
43
|
+
And there should be 1 Caveman with '111222444' identifier
|
44
|
+
And there should be 1 Caveman with '111222555' identifier
|
45
45
|
And there should be 2 Caveman(s) with '1.67' height
|
46
46
|
And there should be 1 Caveman with '1.86' height
|
47
47
|
|
@@ -92,13 +92,14 @@ Feature: Access to objects with indexed fields
|
|
92
92
|
| Adam | Parker | adam | 12 |
|
93
93
|
| Adam | | noob1 | 33 |
|
94
94
|
| | | noob2 | -1 |
|
95
|
+
| | Adam | noob1 | 33 |
|
95
96
|
And I reopen database for reading
|
96
|
-
Then there should be
|
97
|
+
Then there should be 6 Caveman(s)
|
97
98
|
And there should be 1 Caveman with 'John' name
|
98
99
|
And there should be 2 Caveman(s) with 'Adam' name
|
99
100
|
And there should be 2 Caveman(s) with '12' age
|
100
101
|
And there should be 1 Caveman with '-1' age
|
101
|
-
And there should be
|
102
|
+
And there should be 2 Caveman with '' name
|
102
103
|
And there should be 2 Caveman(s) with '' surname
|
103
104
|
|
104
105
|
Scenario: multiple object with indexed fields
|
@@ -1,7 +1,5 @@
|
|
1
|
-
Feature:
|
2
|
-
|
3
|
-
Potential users
|
4
|
-
Must be able to store and load their objects.
|
1
|
+
Feature: Persistence model
|
2
|
+
This feature defines the persistence model of ROD.
|
5
3
|
Background:
|
6
4
|
Given the library works in development mode
|
7
5
|
And the class space is cleared
|
@@ -9,10 +7,9 @@ Feature: ROD Storage
|
|
9
7
|
And a class Fred has an age field of type integer
|
10
8
|
And a class Fred has a sex field of type string with flat index
|
11
9
|
|
12
|
-
Scenario Outline:
|
13
|
-
|
14
|
-
|
15
|
-
all types of data, fields shouldn't be modifiable as well.
|
10
|
+
Scenario Outline: Persistence of unstored changes
|
11
|
+
If there are any changes made to the object after it has
|
12
|
+
been persisted, they are lost when the database is closed.
|
16
13
|
When database is created
|
17
14
|
And I create a Fred
|
18
15
|
And his age is '<init_age>'
|
@@ -64,3 +64,39 @@ Feature: Access to objects with indexed associations
|
|
64
64
|
And there should exist a Caveman with the second Automobile as automobiles
|
65
65
|
And there should be 1 Caveman with the first Automobile as automobiles
|
66
66
|
And there should be 1 Caveman with the second Automobile as automobiles
|
67
|
+
|
68
|
+
Scenario: indexing of plural associations with fresh objects
|
69
|
+
Given the class space is cleared
|
70
|
+
And the model is connected with the default database
|
71
|
+
And a class Automobile has a name field of type string
|
72
|
+
And a class Caveman has a name field of type string
|
73
|
+
And a class Caveman has many automobiles with flat index
|
74
|
+
When database is created
|
75
|
+
And I create an Automobile
|
76
|
+
And its name is 'Prehistoric car'
|
77
|
+
And I create another Automobile
|
78
|
+
And its name is 'Modern car'
|
79
|
+
And I create a Caveman
|
80
|
+
And his name is 'Fred'
|
81
|
+
And his automobiles contain the first Automobile created
|
82
|
+
And his automobiles contain the second Automobile created
|
83
|
+
And I store him in the database
|
84
|
+
And I create another Caveman
|
85
|
+
And his name is 'Allen'
|
86
|
+
And his automobiles contain the second Automobile created
|
87
|
+
And I store him in the database
|
88
|
+
And I fetch the first Automobile created
|
89
|
+
And I store it in the database
|
90
|
+
And I fetch the second Automobile created
|
91
|
+
And I store it in the database
|
92
|
+
And I create another Caveman
|
93
|
+
And her name is 'Linda'
|
94
|
+
And her automobiles contain the first Automobile created
|
95
|
+
And I store her in the database
|
96
|
+
And I reopen database for reading
|
97
|
+
Then there should be 3 Caveman(s)
|
98
|
+
And there should be 2 Automobile(s)
|
99
|
+
And there should exist a Caveman with the first Automobile as automobiles
|
100
|
+
And there should exist a Caveman with the second Automobile as automobiles
|
101
|
+
And there should be 2 Caveman(s) with the first Automobile as automobiles
|
102
|
+
And there should be 2 Caveman(s) with the second Automobile as automobiles
|