rod 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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