rod 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.travis.yml +1 -0
  2. data/README.rdoc +10 -9
  3. data/Rakefile +15 -5
  4. data/changelog.txt +18 -0
  5. data/features/append.feature +0 -2
  6. data/features/basic.feature +7 -7
  7. data/features/collection_proxy.feature +140 -0
  8. data/features/flat_indexing.feature +9 -8
  9. data/features/{fred.feature → persistence.feature} +5 -8
  10. data/features/{assoc_indexing.feature → relationship_indexing.feature} +36 -0
  11. data/features/segmented_indexing.feature +6 -6
  12. data/features/steps/collection_proxy.rb +89 -0
  13. data/features/steps/model.rb +15 -3
  14. data/features/steps/rod.rb +1 -1
  15. data/features/support/mocha.rb +16 -0
  16. data/features/update.feature +263 -0
  17. data/lib/rod.rb +10 -2
  18. data/lib/rod/abstract_database.rb +49 -111
  19. data/lib/rod/abstract_model.rb +26 -6
  20. data/lib/rod/collection_proxy.rb +235 -34
  21. data/lib/rod/constants.rb +1 -1
  22. data/lib/rod/database.rb +5 -6
  23. data/lib/rod/exception.rb +1 -1
  24. data/lib/rod/index/base.rb +97 -0
  25. data/lib/rod/index/flat_index.rb +72 -0
  26. data/lib/rod/index/segmented_index.rb +100 -0
  27. data/lib/rod/model.rb +172 -185
  28. data/lib/rod/reference_updater.rb +85 -0
  29. data/lib/rod/utils.rb +29 -0
  30. data/rod.gemspec +4 -1
  31. data/tests/migration_create.rb +33 -12
  32. data/tests/migration_migrate.rb +24 -7
  33. data/tests/migration_model1.rb +5 -0
  34. data/tests/migration_model2.rb +36 -0
  35. data/tests/migration_verify.rb +49 -42
  36. data/tests/missing_class_create.rb +21 -0
  37. data/tests/missing_class_verify.rb +20 -0
  38. data/tests/properties_order_create.rb +16 -0
  39. data/tests/properties_order_verify.rb +17 -0
  40. data/tests/unit/abstract_database.rb +13 -0
  41. data/tests/unit/model_tests.rb +3 -3
  42. data/utils/convert_index.rb +1 -1
  43. metadata +62 -18
  44. data/lib/rod/segmented_index.rb +0 -85
@@ -18,19 +18,19 @@ Feature: Access to objects with segmented indices.
18
18
  And I create a Caveman
19
19
  And his name is 'Fred'
20
20
  And his age is '25'
21
- And his identifier is '111122223333'
21
+ And his identifier is '111222333'
22
22
  And his height is '1.86'
23
23
  And I store him in the database
24
24
  And I create another Caveman
25
25
  And his name is 'Barney'
26
26
  And his age is '26'
27
- And his identifier is '111122224444'
27
+ And his identifier is '111222444'
28
28
  And his height is '1.67'
29
29
  And I store him in the database
30
30
  And I create another Caveman
31
31
  And his name is 'Wilma'
32
32
  And his age is '25'
33
- And his identifier is '111122225555'
33
+ And his identifier is '111222555'
34
34
  And his height is '1.67'
35
35
  And I store her in the database
36
36
  And I reopen database for reading
@@ -40,9 +40,9 @@ Feature: Access to objects with segmented indices.
40
40
  And there should be 1 Caveman with 'Barney' name
41
41
  And there should be 2 Caveman(s) with '25' age
42
42
  And there should be 1 Caveman with '26' age
43
- And there should be 1 Caveman with '111122223333' identifier
44
- And there should be 1 Caveman with '111122224444' identifier
45
- And there should be 1 Caveman with '111122225555' identifier
43
+ And there should be 1 Caveman with '111222333' identifier
44
+ And there should be 1 Caveman with '111222444' identifier
45
+ And there should be 1 Caveman with '111222555' identifier
46
46
  And there should be 2 Caveman(s) with '1.67' height
47
47
  And there should be 1 Caveman with '1.86' height
48
48
 
@@ -0,0 +1,89 @@
1
+ require 'mocha'
2
+
3
+ def create_item(index)
4
+ rod_id = index + 1
5
+ element = Rod::Model.new
6
+ element.expects(:rod_id).returns(rod_id).at_least(0)
7
+ Rod::Model.expects(:find_by_rod_id).with(rod_id).returns(element).at_least(0)
8
+ element
9
+ end
10
+
11
+ def create_collection(size,offset=0)
12
+ offset.upto(size-1).map do |index|
13
+ create_item(index)
14
+ end
15
+ end
16
+
17
+ # Given the initial size of the collection proxy is 10
18
+ Given /^the initial size of the collection proxy is (\d+)$/ do |size|
19
+ @offset = 0
20
+ size = size.to_i
21
+ @array = create_collection(size,@offset)
22
+ db = Object.new
23
+ @array.each.with_index do |element,index|
24
+ db.expects(:join_index).with(0,index).returns(element).at_least(0)
25
+ end
26
+ @proxy = Rod::CollectionProxy.new(@array.size,db,@offset,Rod::Model)
27
+ @offset += size
28
+ end
29
+
30
+ #When I append a new item 10 times
31
+ When /^I append a new item(?: (\d+) times)?$/ do |count|
32
+ count = count && count.to_i || 1
33
+ count.times do |index|
34
+ item = create_item(@offset)
35
+ @proxy << item
36
+ @array << item
37
+ @offset += 1
38
+ end
39
+ end
40
+
41
+ #When I insert a new item at position 1
42
+ When /^I insert a new item at position (\d+)(?: (\d+) times)?$/ do |position,count|
43
+ (count && count.to_i || 1).times do
44
+ item = create_item(@offset)
45
+ @proxy.insert(position.to_i,item)
46
+ @array.insert(position.to_i,item)
47
+ @offset += 1
48
+ end
49
+ end
50
+
51
+ #When I insert an item with rod_id = 1 at position 1
52
+ When /^I insert an item with rod_id = (\d+) at position (\d+)(?: (\d+) times)?$/ do |rod_id,position,count|
53
+ (count && count.to_i || 1).times do
54
+ item = Rod::Model.find_by_rod_id(rod_id.to_i)
55
+ @proxy.insert(position.to_i,item)
56
+ @array.insert(position.to_i,item)
57
+ end
58
+ end
59
+
60
+ #When I delete an item at position 1
61
+ When /^I delete an item at position (\d+)(?: (\d+) times)?$/ do |position,count|
62
+ (count && count.to_i || 1).times do
63
+ @proxy.delete_at(position.to_i)
64
+ @array.delete_at(position.to_i)
65
+ end
66
+ end
67
+
68
+ #When I delete an item with rod_id = 1
69
+ When /^I delete an item with rod_id = (\d+)$/ do |rod_id|
70
+ item = Rod::Model.find_by_rod_id(rod_id.to_i)
71
+ @proxy.delete(item)
72
+ @array.delete(item)
73
+ end
74
+
75
+ #Then the size of the collection proxy should be 20
76
+ Then /^the size of the collection proxy should be (\d+)$/ do |size|
77
+ @proxy.size.should == size.to_i
78
+ end
79
+
80
+ #Then the collection proxy should be valid
81
+ Then /^the collection proxy should behave like an array$/ do
82
+ @proxy.to_a.should == @array
83
+ end
84
+
85
+ #Then the collection proxy should be empty
86
+ Then /^the collection proxy should be empty$/ do
87
+ @proxy.to_a.should be_empty
88
+ end
89
+
@@ -63,6 +63,10 @@ def get_position(position)
63
63
  1
64
64
  when "third"
65
65
  2
66
+ when "fourth"
67
+ 3
68
+ when "fifth"
69
+ 4
66
70
  when "last"
67
71
  -1
68
72
  when Fixnum
@@ -176,7 +180,7 @@ When /^I create and store the following (\w+)\(s\):$/ do |class_name,table|
176
180
  end
177
181
 
178
182
  # When his name is 'Fred' (multiplied 300 times)
179
- When /^(?:his|her|its) (\w+) is '([^']*)'(?: multiplied (\d+) times)?$/ do |field,value,multiplier|
183
+ When /^(?:his|her|its) (\w+) is '([^']*)'(?: multiplied (\d+) times)?(?: now)?$/ do |field,value,multiplier|
180
184
  value = get_value(value)
181
185
  if multiplier
182
186
  value *= multiplier.to_i
@@ -201,6 +205,7 @@ When /^(his|her|its) (\w+) contain nil$/ do |ignore,field|
201
205
  @instance.send("#{field}".to_sym) << nil
202
206
  end
203
207
 
208
+ # When I store him in the database 10000 times
204
209
  When /^I store (him|her|it) in the database( (\d+) times)?$/ do |ignore,times,count|
205
210
  if times
206
211
  count.to_i.times do |index|
@@ -224,13 +229,20 @@ When /^I remember the (\w+) (\w+)$/ do |position,class_name|
224
229
  @remembered = get_instance(class_name,position)
225
230
  end
226
231
 
232
+ # When I remove the first of his books
233
+ When /^I remove the (\w+) of (?:his|her|its) (\w+)$/ do |position,property|
234
+ @instance.send(property).delete_at(get_position(position))
235
+ end
236
+
227
237
  ################################################################
228
238
  # Then
229
239
  ################################################################
230
- Then /^there should be (\d+) (\w+)(\([^)]*\))?$/ do |count,class_name,ignore|
240
+ # Then there should be 5 User(s)
241
+ Then /^there should be (\d+) (\w+)(?:\([^)]*\))?$/ do |count,class_name|
231
242
  get_class(class_name).count.should == count.to_i
232
243
  end
233
244
 
245
+ # Then the name of the first User should be 'John'
234
246
  Then /^the (\w+) of the (\w+) ([A-Z]\w+) should be '([^']*)'$/ do |field, position, class_name,value|
235
247
  get_instance(class_name,position).send(field.to_sym).should == get_value(value)
236
248
  end
@@ -347,7 +359,7 @@ Then /^there should exist a(?:n)? (\w+) with '([^']*)' (\w+)$/ do |class_name,va
347
359
  end
348
360
 
349
361
  # Then there should be 5 User(s) with the first Dog as dog
350
- Then /^there should be (\d+) (\w+)(?:\([^)]*\))? with the (\w+) (\w+) as (\w+)$/ do |count,class1,position,class2,assoc|
362
+ Then /^there should be (\d+) (\w+)(?:\([^)]*\))? with the (\w+) (\w+) (?:as|(?:in their)) (\w+)$/ do |count,class1,position,class2,assoc|
351
363
  get_class(class1).send("find_all_by_#{assoc}",get_instance(class2,position)).count.should == count.to_i
352
364
  end
353
365
 
@@ -42,7 +42,7 @@ Given /^the class space is cleared$/ do
42
42
  end
43
43
 
44
44
  # Should be split
45
- When /^I reopen (\w+)( for reading)?( in (\w+))?$/ do |db_name,reading,location,location_name|
45
+ When /^I reopen (?:the )?(\w+)( for reading)?( in (\w+))?$/ do |db_name,reading,location,location_name|
46
46
  if location
47
47
  db_location = location_name
48
48
  else
@@ -0,0 +1,16 @@
1
+ require 'mocha'
2
+
3
+ World(Mocha::API)
4
+
5
+ Before do
6
+ mocha_setup
7
+ end
8
+
9
+ After do
10
+ begin
11
+ mocha_verify
12
+ ensure
13
+ mocha_teardown
14
+ end
15
+ end
16
+
@@ -0,0 +1,263 @@
1
+ Feature: Update of the database
2
+ This feature defines the update model of ROD.
3
+ Background:
4
+ Given the library works in development mode
5
+ And the class space is cleared
6
+ And the model is connected with the default database
7
+ And a class Book has a title field of type string with flat index
8
+ And a class Automobile has a name field of type string
9
+ And a class User has a name field of type string with flat index
10
+ And a class User has a surname field of type string with flat index
11
+ And a class User has a login field of type string with flat index
12
+ And a class User has an age field of type integer with flat index
13
+ And a class User has an height field of type float with flat index
14
+ And a class User has a sex field of type object with flat index
15
+ And a class User has one automobile with flat index
16
+ And a class User has many books with flat index
17
+ And a class User has one polymorphic item with flat index
18
+ And a class User has many polymorphic tools with flat index
19
+
20
+ Scenario: update of fields
21
+ When database is created
22
+ And I create and store the following User(s):
23
+ | name | surname | login | age | sex | height |
24
+ | John | Smith | john | 12 | :male | 1.30 |
25
+ | Lara | Croft | lara | 23 | :female | 2.00 |
26
+ | Adam | Parker | adam | 17 | :male | -1.00 |
27
+ | Adam | | noob1 | 33 | :male | 1.50 |
28
+ | | | noob2 | -1 | | 0 |
29
+ And I reopen database
30
+ And I fetch the first User
31
+ And his name is 'Jonhy' now
32
+ And his name is 'Johnny' now
33
+ And his login is 'johnny' now
34
+ And his age is '13' now
35
+ And his height is '1.50' now
36
+ And I store him in the database
37
+ And I fetch the third User
38
+ And his name is 'Alen' now
39
+ And his login is 'alen' now
40
+ And his height is '1.51' now
41
+ And I store him in the database
42
+ And I fetch the fourth User
43
+ And her name is 'Anna' now
44
+ And her name is 'Nina' now
45
+ And her login is 'nina' now
46
+ And her age is '34' now
47
+ And her sex is ':female' now
48
+ And I store her in the database
49
+ And I fetch the fifth User
50
+ And her name is 'Anna' now
51
+ And her login is 'anna' now
52
+ And her age is '1' now
53
+ And her sex is ':female' now
54
+ And her height is '-1.51' now
55
+ And I store her in the database
56
+ And I reopen the database for reading
57
+ Then there should be 5 User(s)
58
+ And the name of the first User should be 'Johnny'
59
+ And the surname of the first User should be 'Smith'
60
+ And the login of the first User should be 'johnny'
61
+ And the age of the first User should be '13'
62
+ And the sex of the first User should be ':male'
63
+ And the height of the first User should be '1.50'
64
+ And the name of the second User should be 'Lara'
65
+ And the surname of the second User should be 'Croft'
66
+ And the login of the second User should be 'lara'
67
+ And the age of the second User should be '23'
68
+ And the sex of the second User should be ':female'
69
+ And the height of the second User should be '2.00'
70
+ And the name of the third User should be 'Alen'
71
+ And the login of the third User should be 'alen'
72
+ And the age of the third User should be '17'
73
+ And the sex of the third User should be ':male'
74
+ And the height of the third User should be '1.51'
75
+ And the name of the fourth User should be 'Nina'
76
+ And the surname of the fourth User should be ''
77
+ And the login of the fourth User should be 'nina'
78
+ And the age of the fourth User should be '34'
79
+ And the sex of the fourth User should be ':female'
80
+ And the height of the fourth User should be '1.50'
81
+ And the name of the fifth User should be 'Anna'
82
+ And the surname of the fifth User should be ''
83
+ And the login of the fifth User should be 'anna'
84
+ And the age of the fifth User should be '1'
85
+ And the sex of the fifth User should be ':female'
86
+ And the height of the fifth User should be '-1.51'
87
+
88
+ Scenario: update of has one relatinships
89
+ When database is created
90
+ And I create a Book
91
+ And its title is 'Gonne with the wind'
92
+ And I store it in the database
93
+ And I create another Book
94
+ And its title is 'Thus Spoke Zarathustra'
95
+ And I store it in the database
96
+ And I create another Book
97
+ And its title is 'Encyclopedia'
98
+ And I store it in the database
99
+ And I create an Automobile
100
+ And its name is 'BMW 330'
101
+ And I store it in the database
102
+ And I create another Automobile
103
+ And its name is 'Daewoo Tico'
104
+ And I store it in the database
105
+ And I create a User
106
+ And his automobile is the first Automobile created
107
+ And his item is the second Book created
108
+ And I store him in the database
109
+ And I create another User
110
+ And his automobile is the second Automobile created
111
+ And his item is the first Book created
112
+ And I store him in the database
113
+ # reopen
114
+ And I reopen the database
115
+ And I fetch the first User
116
+ And his automobile is the second Automobile created
117
+ And his item is the first Book created
118
+ And his item is the third Book created
119
+ And I store him in the database
120
+ And I fetch the second User
121
+ And his item is the second Book created
122
+ And his item is the first Book created
123
+ And I store him in the database
124
+ And I reopen the database for reading
125
+ Then there should be 2 User(s)
126
+ And the automobile of the first User should be equal to the second Automobile
127
+ And the item of the first User should be equal to the third Book
128
+ And the automobile of the second User should be equal to the second Automobile
129
+ And the item of the second User should be equal to the first Book
130
+
131
+ Scenario: update of has many relatinships
132
+ When database is created
133
+ And I create a Book
134
+ And its title is 'Gonne with the wind'
135
+ And I store it in the database
136
+ And I create another Book
137
+ And its title is 'Thus Spoke Zarathustra'
138
+ And I store it in the database
139
+ And I create another Book
140
+ And its title is 'Encyclopedia'
141
+ And I store it in the database
142
+ And I create an Automobile
143
+ And its name is 'BMW 330'
144
+ And I store it in the database
145
+ And I create another Automobile
146
+ And its name is 'Daewoo Tico'
147
+ And I store it in the database
148
+ And I create a User
149
+ And his books contain the first Book created
150
+ And his books contain the second Book created
151
+ And his books contain the third Book created
152
+ And his tools contain the third Book created
153
+ And his tools contain the first Automobile created
154
+ And I store him in the database
155
+ And I create another User
156
+ And I store him in the database
157
+ # reopen
158
+ And I reopen the database
159
+ And I fetch the first User
160
+ And I remove the first of his books
161
+ And I remove the second of his books
162
+ And I remove the second of his tools
163
+ And I store him in the database
164
+ And I fetch the second User
165
+ And his books contain the first Book created
166
+ And his tools contain the second Automobile created
167
+ And his tools contain the first Automobile created
168
+ And I remove the second of his tools
169
+ And I store him in the database
170
+ And I reopen the database for reading
171
+ Then there should be 2 User(s)
172
+ And the first User should have 1 books
173
+ And the first of books of the first User should be equal to the second Book
174
+ And the first User should have 1 tools
175
+ And the first of tools of the first User should be equal to the third Book
176
+ And the second User should have 1 books
177
+ And the first of books of the second User should be equal to the first Book
178
+ And the second User should have 1 tools
179
+ And the first of tools of the second User should be equal to the second Automobile
180
+
181
+ Scenario: update with indexing
182
+ When database is created
183
+ And I create a Book
184
+ And its title is 'Gonne with the wind'
185
+ And I store it in the database
186
+ And I create another Book
187
+ And its title is 'Thus Spoke Zarathustra'
188
+ And I store it in the database
189
+ And I create another Book
190
+ And its title is 'Encyclopedia'
191
+ And I store it in the database
192
+ And I create an Automobile
193
+ And its name is 'BMW 330'
194
+ And I store it in the database
195
+ And I create another Automobile
196
+ And its name is 'Daewoo Tico'
197
+ And I store it in the database
198
+ And I create a User
199
+ And his name is 'Johnny'
200
+ And his login is 'johnny'
201
+ And his age is '13'
202
+ And his height is '1.50'
203
+ And his sex is ':male'
204
+ And his automobile is the first Automobile created
205
+ And his item is the first Book created
206
+ And his books contain the first Book created
207
+ And his tools contain the first Automobile created
208
+ And I store him in the database
209
+ And I create another User
210
+ And her name is 'Anna'
211
+ And her login is 'anna'
212
+ And her age is '23'
213
+ And her height is '1.70'
214
+ And her sex is ':female'
215
+ And her automobile is the second Automobile created
216
+ And her item is the second Book created
217
+ And her books contain the second Book created
218
+ And her books contain the third Book created
219
+ And her tools contain the second Automobile created
220
+ And I store her in the database
221
+ # reopen
222
+ And I reopen the database
223
+ And I fetch the first User
224
+ And her sex is ':female' now
225
+ And her name is 'Joanna' now
226
+ And her login is 'joanna' now
227
+ And her age is '23' now
228
+ And her height is '1.80' now
229
+ And her automobile is the second Automobile created
230
+ And her item is the second Book created
231
+ And I remove the first of her books
232
+ And I remove the first of her tools
233
+ And her books contain the second Book created
234
+ And her tools contain the second Automobile created
235
+ And I store her in the database
236
+ And I fetch the second User
237
+ And her automobile is the first Automobile created
238
+ And I remove the first of her books
239
+ And I store her in the database
240
+ And I reopen the database for reading
241
+ Then there should be 2 User(s)
242
+ And there should be 1 User(s) with 'Joanna' name
243
+ And there should be 0 User(s) with 'Johnny' name
244
+ And there should be 1 User(s) with 'Anna' name
245
+ And there should be 1 User(s) with 'joanna' login
246
+ And there should be 0 User(s) with 'johnny' login
247
+ And there should be 1 User(s) with 'anna' login
248
+ And there should be 2 User(s) with '23' age
249
+ And there should be 0 User(s) with '13' age
250
+ And there should be 1 User(s) with '1.80' height
251
+ And there should be 0 User(s) with '1.50' height
252
+ And there should be 1 User(s) with '1.70' height
253
+ And there should be 2 User(s) with ':female' sex
254
+ And there should be 0 User(s) with ':male' sex
255
+ And there should be 1 User with the first Automobile as automobile
256
+ And there should be 1 User with the second Automobile as automobile
257
+ And there should be 0 User(s) with the first Book as item
258
+ And there should be 2 User(s) with the second Book as item
259
+ And there should be 0 User(s) with the first Automobile in their tools
260
+ And there should be 2 User(s) with the second Automobile in their tools
261
+ And there should be 0 User with the first Book in their books
262
+ And there should be 1 User with the second Book in their books
263
+ And there should be 1 User with the third Book in their books