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.
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