rod 0.6.1 → 0.6.2

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.
Files changed (50) hide show
  1. data/.gitignore +7 -0
  2. data/{README → README.rdoc} +33 -2
  3. data/Rakefile +7 -2
  4. data/changelog.txt +13 -0
  5. data/contributors.txt +2 -0
  6. data/features/append.feature +221 -0
  7. data/features/assoc_indexing.feature +66 -0
  8. data/features/basic.feature +199 -0
  9. data/features/collection.feature +171 -0
  10. data/features/flat_indexing.feature +140 -0
  11. data/features/fred.feature +49 -0
  12. data/features/inheritence.feature +211 -0
  13. data/features/muliple_db.feature +113 -0
  14. data/features/relationships.feature +195 -0
  15. data/features/segmented_indexing.feature +172 -0
  16. data/features/steps/model.rb +386 -0
  17. data/features/steps/rod.rb +71 -0
  18. data/features/steps/test_helper.rb +5 -0
  19. data/lib/rod/abstract_database.rb +17 -5
  20. data/lib/rod/constants.rb +1 -1
  21. data/lib/rod/database.rb +95 -74
  22. data/lib/rod/join_element.rb +6 -2
  23. data/lib/rod/model.rb +37 -9
  24. data/rod.gemspec +15 -12
  25. data/tests/check_strings.rb +10 -0
  26. data/tests/class_compatibility_create.rb +14 -0
  27. data/tests/class_compatibility_verify.rb +18 -0
  28. data/tests/eff1_test.rb +60 -0
  29. data/tests/eff2_test.rb +61 -0
  30. data/tests/full_runs.rb +68 -0
  31. data/tests/generate_classes_create.rb +25 -0
  32. data/tests/generate_classes_model.rb +23 -0
  33. data/tests/generate_classes_rewrite.rb +7 -0
  34. data/tests/generate_classes_verify.rb +46 -0
  35. data/tests/load_struct.rb +24 -0
  36. data/tests/migration_create.rb +25 -0
  37. data/tests/migration_migrate.rb +22 -0
  38. data/tests/migration_model1.rb +23 -0
  39. data/tests/migration_model2.rb +27 -0
  40. data/tests/migration_verify.rb +56 -0
  41. data/tests/mock_tests.rb +128 -0
  42. data/tests/read_on_create.rb +45 -0
  43. data/tests/save_struct.rb +49 -0
  44. data/tests/structures.rb +52 -0
  45. data/tests/unit/database.rb +60 -0
  46. data/tests/unit/model.rb +36 -0
  47. data/tests/unit/model_tests.rb +116 -0
  48. data/tests/validate_read_on_create.rb +12 -0
  49. data/utils/convert_index.rb +31 -0
  50. metadata +77 -28
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .*.sw?
2
+ tmp
3
+ work
4
+ *.gem
5
+ Gemfile.lock
6
+ .bundle
7
+ pkg
@@ -7,7 +7,7 @@
7
7
  ROD (Ruby Object Database) is library which aims at providing
8
8
  fast access for data, which rarely changes.
9
9
 
10
- == FEATURES/PROBLEMS:
10
+ == FEATURES:
11
11
 
12
12
  * nice Ruby interface which mimicks Active Record
13
13
  * Ruby-to-C on-the-fly translation based on mmap and RubyInline
@@ -21,8 +21,11 @@ fast access for data, which rarely changes.
21
21
  * append of the database (new objects, new elements in plural associations)
22
22
  * databases interlinking (via direct links or inverted indices)
23
23
 
24
+ == PROBLEMS
25
+
26
+ * tested mostly on 64-bit systems
24
27
  * doesn't work on Windows
25
- * some space is wasted during when database is appended
28
+ * some space is wasted when database is re-opended in read/write mode
26
29
 
27
30
  == SYNOPSIS:
28
31
 
@@ -44,6 +47,7 @@ number of disk reads was designed. The Ruby interface facilitates it's usage.
44
47
 
45
48
  == REQUIREMENTS:
46
49
 
50
+ * Ruby 1.9
47
51
  * RubyInline
48
52
  * english
49
53
  * ActiveModel
@@ -118,6 +122,33 @@ Grab from rubygems:
118
122
  User.find_all_by_surname("Smith") # gives [Fred]
119
123
  File[0].user # won't work - the data is not normalized
120
124
 
125
+ == DEVELOPMENT
126
+
127
+ You'll need bundler installed:
128
+
129
+ gem install bundler
130
+
131
+ Then you have to fetch all the dependencies:
132
+
133
+ bunlde
134
+
135
+ To run all the test simple type rake:
136
+
137
+ rake
138
+
139
+ This might take several minutes, since for each scenario a whole set of C files
140
+ have to compiled and linked.
141
+
142
+ During development you should watch your ~/.ruby_inline directory. If there
143
+ are thousands of files there, you should fill a bug, since most of them should
144
+ be automatically destroyed.
145
+
146
+ If you want to implement a feature/fix a bug, first be sure that it is
147
+ documented on the bug tracker: https://github.com/apohllo/rod/issues.
148
+ Then be sure to write tests covering the added feature/fixed bug.
149
+ Include the tests in Rakefile, run the tests and if everything is fine
150
+ send me a pull request.
151
+
121
152
  == LICENSE:
122
153
 
123
154
  (The MIT License)
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ task :default => [:all_tests]
6
6
  $gem_name = "rod"
7
7
 
8
8
  desc "Build the gem"
9
- task :build => :all_tests do
9
+ task :build do
10
10
  sh "gem build #$gem_name.gemspec"
11
11
  FileUtils.mkdir("pkg") unless File.exist?("pkg")
12
12
  sh "mv '#$gem_name-#{Rod::VERSION}.gem' pkg"
@@ -14,7 +14,12 @@ end
14
14
 
15
15
  desc "Install the library at local machnie"
16
16
  task :install => :build do
17
- sh "sudo gem install pkg/#$gem_name-#{Rod::VERSION}.gem"
17
+ sh "gem install pkg/#$gem_name-#{Rod::VERSION}.gem"
18
+ end
19
+
20
+ desc "Push gem to rubygems"
21
+ task :push => :build do
22
+ sh "gem push pkg/#$gem_name-#{Rod::VERSION}.gem"
18
23
  end
19
24
 
20
25
  desc "Uninstall the library from local machnie"
data/changelog.txt CHANGED
@@ -1,3 +1,16 @@
1
+ 0.6.2
2
+ - #127 default implementation of inspect
3
+ - #123 fix: warning on has_rdoc in gemspec
4
+ - #116 missing tmp directory for a fresh project
5
+ - Slightly complicate the append feature
6
+ - #120 fix: removal of database so file
7
+ - #119 fix: segfault when accessing fresh object's properties
8
+ - Some clean-up of gemspec
9
+ - #118 fix: ISO C90 forbids mixed declarations and code
10
+ - Fix gemspec - only year-moth-day is preserved
11
+ - Update cuke to 1.0 & change README to rdoc
12
+ - #115 fix: UINT -> ULONG
13
+ - #114 fix: encoding of marshalled values
1
14
  0.6.1
2
15
  - Change order of tests in all_tests
3
16
  - Update DB 'created_at' if empty
data/contributors.txt ADDED
@@ -0,0 +1,2 @@
1
+ People who contributed to Ruby Object Database:
2
+ * qadro
@@ -0,0 +1,221 @@
1
+ Feature: database with append
2
+ The database should allow storage of new objects after the database
3
+ was created and closed.
4
+
5
+ Background:
6
+ Given the library works in development mode
7
+
8
+ Scenario: simple append
9
+ Given the class space is cleared
10
+ And the model is connected with the default database
11
+ And a class User has a name field of type string
12
+ When database is created
13
+ And I create a User
14
+ And his name is 'Fred'
15
+ And I store him in the database 1000 times
16
+ And I reopen database
17
+ And I store him in the database 1000 times
18
+ And I reopen database
19
+ Then there should be 2000 User(s)
20
+
21
+ Scenario: append with indexing
22
+ Given the class space is cleared
23
+ And the model is connected with the default database
24
+ And a class User has a name field of type string with flat index
25
+ And a class User has a surname field of type string with flat index
26
+ And a class User has a login field of type string
27
+ And a class User has an age field of type integer
28
+ When database is created
29
+ And I create and store the following User(s):
30
+ | name | surname | login | age |
31
+ | John | Smith | john | 12 |
32
+ | Lara | Croft | lara | 23 |
33
+ | Adam | Parker | adam | 17 |
34
+ And I reopen database
35
+ And I create and store the following User(s):
36
+ | name | surname | login | age |
37
+ | Mike | Spike | mike | 60 |
38
+ | Lara | Cook | larac | 61 |
39
+ | Adam | Smith | adams | 17 |
40
+ And I reopen database
41
+ Then there should be 6 User(s)
42
+ And there should be 1 User with 'Mike' name
43
+ And there should be 1 User with 'John' name
44
+ And there should be 2 User(s) with 'Lara' name
45
+ And there should be 2 User(s) with 'Adam' name
46
+
47
+ And there should be 2 User(s) with 'Smith' surname
48
+ And there should be 1 User with 'Croft' surname
49
+ And there should be 1 User with 'Parker' surname
50
+ And there should be 1 User with 'Spike' surname
51
+ And there should be 1 User with 'Cook' surname
52
+
53
+ Scenario: append with has one
54
+ Given the class space is cleared
55
+ And the model is connected with the default database
56
+ And a class Automobile has a name field of type string
57
+ And a class Caveman has a name field of type string
58
+ And a class Caveman has one automobile
59
+ When the database is created
60
+ And I create an Automobile
61
+ And its name is 'Prehistoric car'
62
+ And I store it in the database
63
+ And I create a Caveman
64
+ And his name is 'Fred'
65
+ And his automobile is the first Automobile created
66
+ And I store him in the database
67
+ And I reopen database
68
+ And I create an Automobile
69
+ And its name is 'Modern car'
70
+ And I store it in the database
71
+ And I create a Caveman
72
+ And her name is 'Willma'
73
+ And her automobile is the second Automobile created
74
+ And I store her in the database
75
+ And I reopen database
76
+ Then there should be 2 Caveman(s)
77
+ And there should be 2 Automobile(s)
78
+ And the name of the first Caveman should be 'Fred'
79
+ And the name of the first Automobile should be 'Prehistoric car'
80
+ And the name of the second Caveman should be 'Willma'
81
+ And the name of the second Automobile should be 'Modern car'
82
+ And the automobile of the first Caveman should be equal to the first Automobile
83
+ And the automobile of the second Caveman should be equal to the second Automobile
84
+
85
+ Scenario: append with has many
86
+ Given the class space is cleared
87
+ And the model is connected with the default database
88
+ And a class Automobile has a name field of type string
89
+ And a class Caveman has a name field of type string
90
+ And a class Caveman has many automobiles
91
+ When the database is created
92
+ And I create an Automobile
93
+ And its name is 'Prehistoric car'
94
+ And I store it in the database
95
+ And I create another Automobile
96
+ And its name is 'Modern car'
97
+ And I store it in the database
98
+ And I create a Caveman
99
+ And his name is 'Fred'
100
+ And his automobiles contain the first Automobile created
101
+ And his automobiles contain the second Automobile created
102
+ And I store him in the database
103
+ And I reopen database
104
+ And I create an Automobile
105
+ And its name is 'Super car'
106
+ And I store it in the database
107
+ And I create a Caveman
108
+ And her name is 'Willma'
109
+ And her automobiles contain the first Automobile created
110
+ And her automobiles contain the second Automobile created
111
+ And her automobiles contain the third Automobile created
112
+ And I store her in the database
113
+ And I reopen database for reading
114
+ Then there should be 2 Caveman(s)
115
+ And there should be 3 Automobile(s)
116
+ And the name of the first Caveman should be 'Fred'
117
+ And the name of the first Automobile should be 'Prehistoric car'
118
+ And the name of the second Automobile should be 'Modern car'
119
+ And the first Caveman should have 2 automobiles
120
+ And the first of automobiles of the first Caveman should be equal to the first Automobile
121
+ And the second of automobiles of the first Caveman should be equal to the second Automobile
122
+ And the name of the second Caveman should be 'Willma'
123
+ And the second Caveman should have 3 automobiles
124
+ And the first of automobiles of the second Caveman should be equal to the first Automobile
125
+ And the second of automobiles of the second Caveman should be equal to the second Automobile
126
+ And the third of automobiles of the second Caveman should be equal to the third Automobile
127
+
128
+ Scenario: append with a new class
129
+ Given the class space is cleared
130
+ And the model is connected with the default database
131
+ And a class Automobile has a name field of type string
132
+ When database is created
133
+ And I create an Automobile
134
+ And his name is 'Prehistoric car'
135
+ And I store him in the database
136
+ And I reopen database
137
+ Then there should be 1 Automobile
138
+
139
+ Given the class space is cleared
140
+ And the model is connected with the default database
141
+ And a class Automobile has a name field of type string
142
+ And a class Caveman has a name field of type string
143
+ When I open database
144
+ And I create a Caveman
145
+ And his name is 'Fred'
146
+ And I store him in the database
147
+ Then there should be 1 Automobile
148
+ And the name of the first Automobile should be 'Prehistoric car'
149
+ And there should be 1 Caveman
150
+ And the name of the first Caveman should be 'Fred'
151
+
152
+ Scenario: append of has many associations with indexing
153
+ It should be possible to append elements to has many association.
154
+ Given the class space is cleared
155
+ And the model is connected with the default database
156
+ And a class Automobile has a name field of type string
157
+ And a class Caveman has a name field of type string
158
+ And a class Caveman has many automobiles with flat index
159
+ When the database is created
160
+ And I create an Automobile
161
+ And its name is 'Prehistoric car'
162
+ And I store it in the database
163
+ And I create a Caveman
164
+ And his name is 'Fred'
165
+ And his automobiles contain the first Automobile created
166
+ And I store him in the database
167
+ And I reopen database
168
+ And I create an Automobile
169
+ And its name is 'Modern car'
170
+ And I store it in the database
171
+ And I fetch the first Caveman
172
+ And his automobiles contain the second Automobile created
173
+ And I store him in the database
174
+ And I reopen database for reading
175
+ Then there should be 1 Caveman
176
+ And there should be 2 Automobile(s)
177
+ And the name of the first Caveman should be 'Fred'
178
+ And the name of the first Automobile should be 'Prehistoric car'
179
+ And the name of the second Automobile should be 'Modern car'
180
+ And the first Caveman should have 2 automobiles
181
+ And the first of automobiles of the first Caveman should be equal to the first Automobile
182
+ And the second of automobiles of the first Caveman should be equal to the second Automobile
183
+ And there should be 1 Caveman with the first Automobile as automobiles
184
+ And there should be 1 Caveman with the second Automobile as automobiles
185
+
186
+ # Enable for #94
187
+ @ignore
188
+ Scenario: append of has many associations with indexing with an unstored object
189
+ Same as above, but with an object which is appended to the collection
190
+ while it is not yet stored in the DB.
191
+ Given the class space is cleared
192
+ And the model is connected with the default database
193
+ And a class Automobile has a name field of type string
194
+ And a class Caveman has a name field of type string
195
+ And a class Caveman has many automobiles with flat index
196
+ When the database is created
197
+ And I create an Automobile
198
+ And its name is 'Prehistoric car'
199
+ And I store it in the database
200
+ And I create a Caveman
201
+ And his name is 'Fred'
202
+ And his automobiles contain the first Automobile created
203
+ And I store him in the database
204
+ And I create an Automobile
205
+ And its name is 'Modern car'
206
+ And I fetch the first Caveman
207
+ And his automobiles contain the second Automobile created
208
+ And I store him in the database
209
+ And I fetch the second Automobile created
210
+ And I store it in the database
211
+ And I reopen database for reading
212
+ Then there should be 1 Caveman
213
+ And there should be 2 Automobile(s)
214
+ And the name of the first Caveman should be 'Fred'
215
+ And the name of the first Automobile should be 'Prehistoric car'
216
+ And the name of the second Automobile should be 'Modern car'
217
+ And the first Caveman should have 2 automobiles
218
+ And the first of automobiles of the first Caveman should be equal to the first Automobile
219
+ And the second of automobiles of the first Caveman should be equal to the second Automobile
220
+ And there should be 1 Caveman with the first Automobile as automobiles
221
+ And there should be 1 Caveman with the second Automobile as automobiles
@@ -0,0 +1,66 @@
1
+ Feature: Access to objects with indexed associations
2
+ ROD allows for accessing objects via associations with indices.
3
+
4
+ Background:
5
+ Given the library works in development mode
6
+
7
+ Scenario: indexing of singular associations
8
+ It should be possible to index singular associations. This is
9
+ useful when there are two databases and the other references
10
+ objects from the first, but the first cannot directly reference
11
+ objects from the second. In such a case, the second DB can have
12
+ indices for the associations to speed-up object look-up.
13
+ Given the class space is cleared
14
+ And a class Caveman inherits from Rod::Model
15
+ And a class Caveman has a name field of type string
16
+ And a class Caveman is connected to Database1
17
+ And a class Automobile inherits from Rod::Model
18
+ And a class Automobile has a name field of type string
19
+ And a class Automobile is connected to Database2
20
+ And a class Caveman has one automobile with flat index
21
+ When the Database1 is created
22
+ And the Database2 is created
23
+ And I create an Automobile
24
+ And its name is 'Prehistoric car'
25
+ And I store it in the database
26
+ And I create a Caveman
27
+ And his name is 'Fred'
28
+ And his automobile is the first Automobile created
29
+ And I store him in the database
30
+ And I reopen Database1 for reading
31
+ And I reopen Database2 for reading
32
+ Then there should be 1 Caveman
33
+ And there should be 1 Automobile
34
+ And there should exist a Caveman with the first Automobile as automobile
35
+ And there should be 1 Caveman with the first Automobile as automobile
36
+
37
+ Scenario: indexing of plural associations
38
+ Given the class space is cleared
39
+ And a class Caveman inherits from Rod::Model
40
+ And a class Caveman has a name field of type string
41
+ And a class Caveman is connected to Database1
42
+ And a class Automobile inherits from Rod::Model
43
+ And a class Automobile has a name field of type string
44
+ And a class Automobile is connected to Database2
45
+ And a class Caveman has many automobiles with flat index
46
+ When the Database1 is created
47
+ And the Database2 is created
48
+ And I create an Automobile
49
+ And its name is 'Prehistoric car'
50
+ And I store it in the database
51
+ And I create another Automobile
52
+ And its name is 'Modern car'
53
+ And I store it in the database
54
+ And I create a Caveman
55
+ And his name is 'Fred'
56
+ And his automobiles contain the first Automobile created
57
+ And his automobiles contain the second Automobile created
58
+ And I store him in the database
59
+ And I reopen Database1 for reading
60
+ And I reopen Database2 for reading
61
+ Then there should be 1 Caveman
62
+ And there should be 2 Automobile(s)
63
+ And there should exist a Caveman with the first Automobile as automobiles
64
+ And there should exist a Caveman with the second Automobile as automobiles
65
+ And there should be 1 Caveman with the first Automobile as automobiles
66
+ And there should be 1 Caveman with the second Automobile as automobiles
@@ -0,0 +1,199 @@
1
+ Feature: Store and load small amount of data from one class
2
+ In order to ensure basic functionality, ROD should
3
+ allow to store and load data for one simple class.
4
+ Background:
5
+ Given the library works in development mode
6
+
7
+ Scenario: class with one field
8
+ Rod should allow to store in the DB instances of a class with one field
9
+ Given the class space is cleared
10
+ And the model is connected with the default database
11
+ And a class Caveman has a name field of type string
12
+ When database is created
13
+ And I create a Caveman
14
+ And his name is 'Fred'
15
+ And I store him in the database
16
+ And I reopen database for reading
17
+ Then there should be 1 Caveman
18
+ And the name of the first Caveman should be 'Fred'
19
+
20
+ When database is created
21
+ And I create a Caveman
22
+ And her name is 'Wilma'
23
+ And I store her in the database
24
+ And I create another Caveman
25
+ And his name is 'Barney'
26
+ And I store him in the database
27
+ Then there should be 2 Caveman(s)
28
+ And the name of the first Caveman should be 'Wilma'
29
+ And the name of the second Caveman should be 'Barney'
30
+ And the third Caveman should not exist
31
+
32
+ Scenario: class with every type of field
33
+ Rod should allow to store in the DB instances of a class
34
+ having fields of each type
35
+ Given the class space is cleared
36
+ And the model is connected with the default database
37
+ And a class Caveman has a name field of type string
38
+ And a class Caveman has an age field of type integer
39
+ And a class Caveman has an identifier field of type ulong
40
+ And a class Caveman has a height field of type float
41
+ And a class Caveman has a symbol field of type object
42
+ And a class Caveman has a empty_string field of type string
43
+ And a class Caveman has a empty_object field of type object
44
+ When database is created
45
+ And I create a Caveman
46
+ And his name is 'Fred'
47
+ And his age is '25'
48
+ And his identifier is '111122223333'
49
+ And his height is '1.86'
50
+ And his symbol is ':fred'
51
+ # nil is converted to an empty string, consider using object field
52
+ # if you wish to store nil for string fields
53
+ And his empty_string is nil
54
+ # The field is not set to nil, but we assume that not set fields of
55
+ # type object are nils.
56
+ #And his empty_object is nil
57
+ And I store him in the database
58
+ And I reopen database for reading
59
+ Then there should be 1 Caveman
60
+ And the name of the first Caveman should be 'Fred'
61
+ And the age of the first Caveman should be '25'
62
+ And the identifier of the first Caveman should be '111122223333'
63
+ And the height of the first Caveman should be '1.86'
64
+ And the symbol of the first Caveman should be ':fred'
65
+ And the empty_string of the first Caveman should be ''
66
+ And the empty_object of the first Caveman should be nil
67
+
68
+ Scenario: instance with string containing 0
69
+ Rod should allow to store in the DB string values
70
+ containing characters equal to 0 (not the number but value)
71
+ Given the class space is cleared
72
+ And the model is connected with the default database
73
+ And a class Caveman has a name field of type string
74
+ When database is created
75
+ And I create a Caveman
76
+ And his name is 'Fred\0Fred'
77
+ And I store him in the database
78
+ And I reopen database for reading
79
+ Then there should be 1 Caveman
80
+ And the name of the first Caveman should be 'Fred\0Fred'
81
+
82
+ When database is created
83
+ And I create a Caveman
84
+ And his name is 'Fred\0' multiplied 30000 times
85
+ And I store him in the database
86
+ And I reopen database for reading
87
+ Then there should be 1 Caveman
88
+ And the name of the first Caveman should be 'Fred\0' multiplied 30000 times
89
+
90
+ Scenario: reading fields while objects are created
91
+ Rod should allow to read values of initialized fields of instances, before and after
92
+ the instance is stored to the DB.
93
+ Given the class space is cleared
94
+ And the model is connected with the default database
95
+ And a class Caveman has a name field of type string
96
+ And a class Caveman has an age field of type integer
97
+ And a class Caveman has an identifier field of type ulong
98
+ And a class Caveman has a height field of type float
99
+ When database is created
100
+ And I create a Caveman
101
+ And his name is 'Fred'
102
+ And his age is '25'
103
+ And his identifier is '111122223333'
104
+ And his height is '1.86'
105
+ Then his name should be 'Fred'
106
+ And his age should be '25'
107
+ And his identifier should be '111122223333'
108
+ And his height should be '1.86'
109
+
110
+ When database is created
111
+ And I create a Caveman
112
+ And his name is 'Fred'
113
+ And I store him in the database
114
+ And I remember the first Caveman
115
+ And I create another Caveman
116
+ And his name is 'Fred'
117
+ And I store him in the database 4000 times
118
+ Then the name of the remembered instance should be 'Fred'
119
+
120
+ Scenario: reading properties of fresh object
121
+ Rod should allow to read values of uninitialized fields of instances,
122
+ before the instance is stored to the DB.
123
+ Given the class space is cleared
124
+ And the model is connected with the default database
125
+ And a class Item has an name field of type string
126
+ And a class Caveman has a name field of type string
127
+ And a class Caveman has an age field of type integer
128
+ And a class Caveman has an identifier field of type ulong
129
+ And a class Caveman has a height field of type float
130
+ And a class Caveman has a symbol field of type object
131
+ And a class Caveman has one item
132
+ And a class Caveman has many items
133
+ When database is created
134
+ And I create a Caveman
135
+ And I fetch the first Caveman created
136
+ Then his name should be ''
137
+ And his age should be nil
138
+ And his identifier should be nil
139
+ And his height should be nil
140
+ And his symbol should be nil
141
+ And his item should be nil
142
+ And his items should be empty
143
+
144
+ Scenario: referential integrity and simple indexing
145
+ Rod should allow to access objects via simple indexing
146
+ (i.e. Model[index]).
147
+ It should also impose referential integrity for objects
148
+ which are accessed via their indices.
149
+ Given the class space is cleared
150
+ And the model is connected with the default database
151
+ And a class Caveman has a name field of type string
152
+ When database is created
153
+ And I create a Caveman
154
+ And his name is 'Fred'
155
+ And I store him in the database
156
+ And I reopen database for reading
157
+ Then the first Caveman should be identical with the first Caveman
158
+ And the first Caveman should be equal with the instance
159
+
160
+ Scenario: model without instances
161
+ A model without instances should be treated fine.
162
+ Given the class space is cleared
163
+ And the model is connected with the default database
164
+ And a class Caveman has a name field of type string with flat index
165
+ When database is created
166
+ And I reopen database for reading
167
+ Then there should be 0 Caveman(s)
168
+
169
+ Scenario: model without instances with indexed field
170
+ A model without instances but with indexed field should be treated fine.
171
+ Given the class space is cleared
172
+ And the model is connected with the default database
173
+ And a class Caveman has a name field of type string with flat index
174
+ And a class Automobile has a name field of type string with flat index
175
+ When database is created
176
+ And I create a Caveman
177
+ And his name is 'Fred'
178
+ And I store him in the database
179
+ And I reopen database for reading
180
+ Then there should be 1 Caveman
181
+ And there should be 0 Automobile(s)
182
+
183
+ Scenario: ActiveRecord-style initialization
184
+ A new instance of a model should accept hash of key-value pairs,
185
+ used to initialize its fields.
186
+ Given the class space is cleared
187
+ And the model is connected with the default database
188
+ And a class Caveman has a name field of type string
189
+ And a class Caveman has a surname field of type string
190
+ When database is created
191
+ And I create a Caveman with 'Fred' name and 'Flintstone' surname
192
+ And I store him in the database
193
+ Then there should be 1 Caveman
194
+ And his name should be 'Fred'
195
+ And his surname should be 'Flintstone'
196
+
197
+ When database is created
198
+ And I create a Caveman with 'Fred' name and 'Flintstone' age
199
+ Then Rod::RodException should be raised