rod 0.7.1 → 0.7.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 (76) hide show
  1. data/.travis.yml +1 -1
  2. data/README.rdoc +38 -10
  3. data/Rakefile +20 -9
  4. data/changelog.txt +25 -0
  5. data/contributors.txt +1 -0
  6. data/data/backward/0.7.0/_join_element.dat +0 -0
  7. data/data/backward/0.7.0/_polymorphic_join_element.dat +0 -0
  8. data/data/backward/0.7.0/char.dat +0 -0
  9. data/data/backward/0.7.0/database.yml +58 -0
  10. data/data/backward/0.7.0/rod_test__automobile.dat +0 -0
  11. data/data/backward/0.7.0/rod_test__caveman.dat +0 -0
  12. data/data/backward/0.7.0/rod_test__dog.dat +0 -0
  13. data/data/backward/0.7.0/rod_test__test_model.dat +0 -0
  14. data/data/portability/_join_element.dat +0 -0
  15. data/data/portability/_polymorphic_join_element.dat +0 -0
  16. data/data/portability/char.dat +0 -0
  17. data/data/portability/database.yml +49 -0
  18. data/data/portability/rod_test__automobile.dat +0 -0
  19. data/data/portability/rod_test__caveman.dat +0 -0
  20. data/data/portability/rod_test__dog.dat +0 -0
  21. data/data/portability/rod_test__test_model.dat +0 -0
  22. data/features/backward.feature +33 -0
  23. data/features/basic.feature +3 -0
  24. data/features/collection_proxy.feature +95 -0
  25. data/features/flat_indexing.feature +44 -2
  26. data/features/hash_indexing.feature +63 -9
  27. data/features/portability.feature +72 -0
  28. data/features/segmented_indexing.feature +45 -2
  29. data/features/steps/collection_proxy.rb +1 -1
  30. data/features/steps/model.rb +48 -5
  31. data/features/steps/rod.rb +15 -16
  32. data/lib/rod.rb +11 -1
  33. data/lib/rod/abstract_database.rb +52 -42
  34. data/lib/rod/berkeley/collection_proxy.rb +96 -0
  35. data/lib/rod/berkeley/database.rb +337 -0
  36. data/lib/rod/berkeley/environment.rb +209 -0
  37. data/lib/rod/berkeley/sequence.rb +222 -0
  38. data/lib/rod/berkeley/transaction.rb +233 -0
  39. data/lib/rod/collection_proxy.rb +76 -1
  40. data/lib/rod/constants.rb +3 -2
  41. data/lib/rod/database.rb +127 -14
  42. data/lib/rod/index/base.rb +12 -3
  43. data/lib/rod/index/hash_index.rb +295 -70
  44. data/lib/rod/index/segmented_index.rb +3 -0
  45. data/lib/rod/model.rb +154 -531
  46. data/lib/rod/property/base.rb +190 -0
  47. data/lib/rod/property/field.rb +258 -0
  48. data/lib/rod/property/plural_association.rb +145 -0
  49. data/lib/rod/property/singular_association.rb +139 -0
  50. data/rod.gemspec +6 -4
  51. data/spec/berkeley/database.rb +83 -0
  52. data/spec/berkeley/environment.rb +58 -0
  53. data/spec/berkeley/sequence.rb +101 -0
  54. data/spec/berkeley/transaction.rb +92 -0
  55. data/spec/collection_proxy.rb +38 -0
  56. data/spec/database.rb +36 -0
  57. data/spec/model.rb +26 -0
  58. data/spec/property/base.rb +73 -0
  59. data/spec/property/field.rb +244 -0
  60. data/spec/property/plural_association.rb +67 -0
  61. data/spec/property/singular_association.rb +65 -0
  62. data/tests/class_compatibility_create.rb +2 -2
  63. data/tests/eff1_test.rb +1 -1
  64. data/tests/eff2_test.rb +1 -1
  65. data/tests/full_runs.rb +1 -1
  66. data/tests/generate_classes_create.rb +14 -14
  67. data/tests/migration_create.rb +47 -47
  68. data/tests/migration_verify.rb +1 -1
  69. data/tests/missing_class_create.rb +6 -6
  70. data/tests/properties_order_create.rb +4 -4
  71. data/tests/read_on_create.rb +33 -34
  72. data/tests/save_struct.rb +40 -39
  73. data/tests/unit/database.rb +1 -1
  74. data/tests/unit/model_tests.rb +73 -65
  75. metadata +71 -15
  76. data/tests/unit/model.rb +0 -36
@@ -44,6 +44,12 @@ Feature: Access to objects with indexed fields
44
44
  And there should be 1 Caveman with '111222555' identifier
45
45
  And there should be 2 Caveman(s) with '1.67' height
46
46
  And there should be 1 Caveman with '1.86' height
47
+ And some Caveman with 'Fred' name should be equal to the first Caveman
48
+ And some Caveman with 'Barney' name should be equal to the second Caveman
49
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
50
+ And the first Caveman with 'Fred' name should be equal to the first Caveman
51
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
52
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
47
53
 
48
54
  Scenario: indexing of fields with different DBs for the same model
49
55
  The contents of indices should be fulshed when the database is reopened.
@@ -62,7 +68,7 @@ Feature: Access to objects with indexed fields
62
68
  And I store him in the database
63
69
  And I reopen database for reading
64
70
  And I access the Caveman name index
65
- And database is created in location2
71
+ And database is created in tmp/location2
66
72
  And I create a Caveman
67
73
  And his name is 'Wilma'
68
74
  And I store him in the database
@@ -72,10 +78,11 @@ Feature: Access to objects with indexed fields
72
78
  And I create another Caveman
73
79
  And his name is 'Wilma'
74
80
  And I store him in the database
75
- And I reopen database for reading in location2
81
+ And I reopen database for reading in tmp/location2
76
82
  Then there should be 3 Caveman(s)
77
83
  And there should be 3 Caveman(s) with 'Wilma' name
78
84
  And there should be 0 Caveman(s) with 'Fred' name
85
+ And some Caveman with 'Wilma' name should be equal to the first Caveman
79
86
 
80
87
  Scenario: indexing of particular values
81
88
  Given the class space is cleared
@@ -139,3 +146,38 @@ Feature: Access to objects with indexed fields
139
146
  And I store him in the database
140
147
  Then there should exist a User with 'John' name
141
148
  And there should be 1 User with 'John' name
149
+
150
+ Scenario: iterating over the index key-values pairs
151
+ It should be possible to iterate over the keys of a index.
152
+ Given the class space is cleared
153
+ And the model is connected with the default database
154
+ And a class User has a name field of type string with flat index
155
+ When database is created
156
+ And I create a User
157
+ And his name is 'John'
158
+ And I store him in the database
159
+ And I create a User
160
+ And her name is 'Lara'
161
+ And I store her in the database
162
+ And I create a User
163
+ And her name is 'Lara'
164
+ And I store her in the database
165
+ And I create a User
166
+ And her name is 'Pipi'
167
+ And I store her in the database
168
+ And I reopen the database for reading
169
+ And I iterate over the name index of User
170
+ Then there should be 1 User with 'John' name in the iteration results
171
+ And there should be 2 User(s) with 'Lara' name in the iteration results
172
+ And there should be 1 User with 'Pipi' name in the iteration results
173
+ And there should be 0 User(s) with 'Fred' name in the iteration results
174
+
175
+ Scenario: indexing with empty database
176
+ Rod should behave well when there is an index on a model while
177
+ the database is created and nothing is stored in it.
178
+ Given the class space is cleared
179
+ And the model is connected with the default database
180
+ And a class User has a name field of type string with flat index
181
+ When database is created
182
+ And I reopen the database for reading
183
+ Then there should be 0 User(s)
@@ -18,19 +18,19 @@ Feature: Access to objects with hash 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,11 +40,17 @@ Feature: Access to objects with hash 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
+ And some Caveman with 'Fred' name should be equal to the first Caveman
49
+ And some Caveman with 'Barney' name should be equal to the second Caveman
50
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
51
+ And the first Caveman with 'Fred' name should be equal to the first Caveman
52
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
53
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
48
54
 
49
55
  # Test re-creation of the database
50
56
  When database is created
@@ -62,6 +68,12 @@ Feature: Access to objects with hash indices.
62
68
  And there should be 1 Caveman with 'Fred' name
63
69
  And there should be 1 Caveman with 'Wilma' name
64
70
  And there should be 1 Caveman with 'Barney' name
71
+ And some Caveman with 'Fred' name should be equal to the first Caveman
72
+ And some Caveman with 'Barney' name should be equal to the second Caveman
73
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
74
+ And the first Caveman with 'Fred' name should be equal to the first Caveman
75
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
76
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
65
77
 
66
78
  Scenario: extending the DB when hash index is used
67
79
  Rod should allow to extend the DB when the hash index is used.
@@ -88,6 +100,11 @@ Feature: Access to objects with hash indices.
88
100
  And there should be 1 Caveman with 'Wilma' name
89
101
  And there should be 2 Caveman(s) with 'Fred' name
90
102
  And there should be 1 Caveman with 'Barney' name
103
+ And some Caveman with 'Fred' name should be equal to the first Caveman
104
+ And some Caveman with 'Barney' name should be equal to the second Caveman
105
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
106
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
107
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
91
108
 
92
109
  Scenario: indexing of fields with different DBs for the same model with hash index
93
110
  The contents of indices should be fulshed when the database is reopened.
@@ -106,7 +123,7 @@ Feature: Access to objects with hash indices.
106
123
  And I store him in the database
107
124
  And I reopen database for reading
108
125
  And I access the Caveman name index
109
- And database is created in location2
126
+ And database is created in tmp/location2
110
127
  And I create a Caveman
111
128
  And his name is 'Wilma'
112
129
  And I store him in the database
@@ -116,10 +133,11 @@ Feature: Access to objects with hash indices.
116
133
  And I create another Caveman
117
134
  And his name is 'Wilma'
118
135
  And I store him in the database
119
- And I reopen database for reading in location2
136
+ And I reopen database for reading in tmp/location2
120
137
  Then there should be 3 Caveman(s)
121
138
  And there should be 3 Caveman(s) with 'Wilma' name
122
139
  And there should be 0 Caveman(s) with 'Fred' name
140
+ And some Caveman with 'Wilma' name should be equal to the first Caveman
123
141
 
124
142
  Scenario: indexing of particular values with hash index
125
143
  Given the class space is cleared
@@ -146,7 +164,7 @@ Feature: Access to objects with hash indices.
146
164
  And there should be 2 Caveman(s) with '' name
147
165
  And there should be 2 Caveman(s) with '' surname
148
166
 
149
- Scenario: multiple object with indexed fields with hash index
167
+ Scenario: multiple objects with indexed fields with hash index
150
168
  The database should properly store thausands of objects with some indexed fields.
151
169
  Given the class space is cleared
152
170
  And the model is connected with the default database
@@ -170,3 +188,39 @@ Feature: Access to objects with hash indices.
170
188
  Then there should be 1000 User(s) with 'Smith' surname
171
189
  Then there should be 1000 User(s) with 'Lara' name
172
190
  Then there should be 1000 User(s) with 'Croft' surname
191
+ And some User with 'John' name should be equal to the first User
192
+
193
+ Scenario: iterating over the index key-values pairs
194
+ It should be possible to iterate over the keys of a index.
195
+ Given the class space is cleared
196
+ And the model is connected with the default database
197
+ And a class User has a name field of type string with hash index
198
+ When database is created
199
+ And I create a User
200
+ And his name is 'John'
201
+ And I store him in the database
202
+ And I create a User
203
+ And her name is 'Lara'
204
+ And I store her in the database
205
+ And I create a User
206
+ And her name is 'Lara'
207
+ And I store her in the database
208
+ And I create a User
209
+ And her name is 'Pipi'
210
+ And I store her in the database
211
+ And I reopen the database for reading
212
+ And I iterate over the name index of User
213
+ Then there should be 1 User with 'John' name in the iteration results
214
+ And there should be 2 User(s) with 'Lara' name in the iteration results
215
+ And there should be 1 User with 'Pipi' name in the iteration results
216
+ And there should be 0 User(s) with 'Fred' name in the iteration results
217
+
218
+ Scenario: indexing with empty database
219
+ Rod should behave well when there is an index on a model while
220
+ the database is created and nothing is stored in it.
221
+ Given the class space is cleared
222
+ And the model is connected with the default database
223
+ And a class User has a name field of type string with hash index
224
+ When database is created
225
+ And I reopen the database for reading
226
+ Then there should be 0 User(s)
@@ -0,0 +1,72 @@
1
+ Feature: Data portability
2
+ The database should be portable across systems with different
3
+ byte order and processor register length.
4
+ Background:
5
+ Given the library works in development mode
6
+
7
+ Scenario: this scenario is used to generate the data used in portability tests
8
+ Given the class space is cleared
9
+ And the model is connected with the default database
10
+ And a class Caveman has a name field of type string
11
+ And a class Caveman has an age field of type integer
12
+ And a class Caveman has an identifier field of type ulong
13
+ And a class Caveman has a height field of type float
14
+ And a class Caveman has a account_balance field of type float
15
+ And a class Automobile has a name field of type string
16
+ And a class Caveman has one automobile
17
+ And a class Dog has a nickname field of type string
18
+ And a class Caveman has many dogs
19
+ When database is created
20
+ And I create an Automobile
21
+ And its name is 'Prehistoric car'
22
+ And I store it in the database
23
+ And I create a Dog
24
+ And its nickname is 'Snoopy'
25
+ And I store it in the database
26
+ And I create a Caveman
27
+ And his name is 'Fred'
28
+ And his age is '25'
29
+ And his identifier is '111222333'
30
+ And his height is '1.86'
31
+ And his account_balance is '-0.00000001'
32
+ And his automobile is the first Automobile created
33
+ And his dogs contain the first Dog created
34
+ And I store him in the database
35
+ And I reopen database for reading
36
+ Then there should be 1 Caveman
37
+ And there should be 1 Dog
38
+ And there should be 1 Automobile
39
+ And the name of the first Caveman should be 'Fred'
40
+ And the age of the first Caveman should be '25'
41
+ And the identifier of the first Caveman should be '111222333'
42
+ And the height of the first Caveman should be '1.86'
43
+ And the account_balance of the first Caveman should be '-0.00000001'
44
+ And the automobile of the first Caveman should be equal to the first Automobile
45
+ And the first of dogs of the first Caveman should be equal to the first Dog
46
+
47
+ # This feature will be turned on when #221 is implemented.
48
+ @ignore
49
+ Scenario: simple check of data portability
50
+ Rod should allow to read data created on a little endian 64-bit system
51
+ Given the class space is cleared
52
+ And the model is connected with the default database
53
+ And a class Caveman has a name field of type string
54
+ And a class Caveman has an age field of type integer
55
+ And a class Caveman has an identifier field of type ulong
56
+ And a class Caveman has a height field of type float
57
+ And a class Caveman has a account_balance field of type float
58
+ And a class Automobile has a name field of type string
59
+ And a class Caveman has one automobile
60
+ And a class Dog has a nickname field of type string
61
+ And a class Caveman has many dogs
62
+ When I open the database for reading in data/portability
63
+ Then there should be 1 Caveman
64
+ And there should be 1 Dog
65
+ And there should be 1 Automobile
66
+ And the name of the first Caveman should be 'Fred'
67
+ And the age of the first Caveman should be '25'
68
+ And the identifier of the first Caveman should be '111222333'
69
+ And the height of the first Caveman should be '1.86'
70
+ And the account_balance of the first Caveman should be '-0.00000001'
71
+ And the automobile of the first Caveman should be equal to the first Automobile persisted
72
+ And the first of dogs of the first Caveman should be equal to the first Dog persisted
@@ -45,6 +45,12 @@ Feature: Access to objects with segmented indices.
45
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
+ And some Caveman with 'Fred' name should be equal to the first Caveman
49
+ And some Caveman with 'Barney' name should be equal to the second Caveman
50
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
51
+ And the first Caveman with 'Fred' name should be equal to the first Caveman
52
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
53
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
48
54
 
49
55
  # Test re-creation of the database
50
56
  When database is created
@@ -62,6 +68,12 @@ Feature: Access to objects with segmented indices.
62
68
  And there should be 1 Caveman with 'Fred' name
63
69
  And there should be 1 Caveman with 'Wilma' name
64
70
  And there should be 1 Caveman with 'Barney' name
71
+ And some Caveman with 'Fred' name should be equal to the first Caveman
72
+ And some Caveman with 'Barney' name should be equal to the second Caveman
73
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
74
+ And the first Caveman with 'Fred' name should be equal to the first Caveman
75
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
76
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
65
77
 
66
78
  Scenario: extending the DB when segmented index is used
67
79
  Rod should allow to extend the DB when the segmented index is used.
@@ -88,6 +100,11 @@ Feature: Access to objects with segmented indices.
88
100
  And there should be 1 Caveman with 'Wilma' name
89
101
  And there should be 2 Caveman(s) with 'Fred' name
90
102
  And there should be 1 Caveman with 'Barney' name
103
+ And some Caveman with 'Fred' name should be equal to the first Caveman
104
+ And some Caveman with 'Barney' name should be equal to the second Caveman
105
+ And some Caveman with 'Wilma' name should be equal to the third Caveman
106
+ And the first Caveman with 'Barney' name should be equal to the second Caveman
107
+ And the first Caveman with 'Wilma' name should be equal to the third Caveman
91
108
 
92
109
  Scenario: indexing of fields with different DBs for the same model with segmented index
93
110
  The contents of indices should be fulshed when the database is reopened.
@@ -106,7 +123,7 @@ Feature: Access to objects with segmented indices.
106
123
  And I store him in the database
107
124
  And I reopen database for reading
108
125
  And I access the Caveman name index
109
- And database is created in location2
126
+ And database is created in tmp/location2
110
127
  And I create a Caveman
111
128
  And his name is 'Wilma'
112
129
  And I store him in the database
@@ -116,10 +133,11 @@ Feature: Access to objects with segmented indices.
116
133
  And I create another Caveman
117
134
  And his name is 'Wilma'
118
135
  And I store him in the database
119
- And I reopen database for reading in location2
136
+ And I reopen database for reading in tmp/location2
120
137
  Then there should be 3 Caveman(s)
121
138
  And there should be 3 Caveman(s) with 'Wilma' name
122
139
  And there should be 0 Caveman(s) with 'Fred' name
140
+ And some Caveman with 'Wilma' name should be equal to the first Caveman
123
141
 
124
142
  Scenario: indexing of particular values with segmented index
125
143
  Given the class space is cleared
@@ -170,3 +188,28 @@ Feature: Access to objects with segmented indices.
170
188
  Then there should be 1000 User(s) with 'Smith' surname
171
189
  Then there should be 1000 User(s) with 'Lara' name
172
190
  Then there should be 1000 User(s) with 'Croft' surname
191
+
192
+ Scenario: iterating over the index key-values pairs
193
+ It should be possible to iterate over the keys of a index.
194
+ Given the class space is cleared
195
+ And the model is connected with the default database
196
+ And a class User has a name field of type string with segmented index
197
+ When database is created
198
+ And I create a User
199
+ And his name is 'John'
200
+ And I store him in the database
201
+ And I create a User
202
+ And her name is 'Lara'
203
+ And I store her in the database
204
+ And I create a User
205
+ And her name is 'Lara'
206
+ And I store her in the database
207
+ And I create a User
208
+ And her name is 'Pipi'
209
+ And I store her in the database
210
+ And I reopen the database for reading
211
+ And I iterate over the name index of User
212
+ Then there should be 1 User with 'John' name in the iteration results
213
+ And there should be 2 User(s) with 'Lara' name in the iteration results
214
+ And there should be 1 User with 'Pipi' name in the iteration results
215
+ And there should be 0 User(s) with 'Fred' name in the iteration results
@@ -23,7 +23,7 @@ Given /^the initial size of the collection proxy is (\d+)$/ do |size|
23
23
  @array.each.with_index do |element,index|
24
24
  db.expects(:join_index).with(0,index).returns(element).at_least(0)
25
25
  end
26
- @proxy = Rod::CollectionProxy.new(@array.size,db,@offset,Rod::Model)
26
+ @proxy = Rod::CollectionProxy.new(@array.size,db,@offset,Rod::Model)
27
27
  @offset += size
28
28
  end
29
29
 
@@ -67,6 +67,10 @@ def get_position(position)
67
67
  3
68
68
  when "fifth"
69
69
  4
70
+ when "sixth"
71
+ 5
72
+ when "seventh"
73
+ 6
70
74
  when "last"
71
75
  -1
72
76
  when Fixnum
@@ -234,6 +238,18 @@ When /^I remove the (\w+) of (?:his|her|its) (\w+)$/ do |position,property|
234
238
  @instance.send(property).delete_at(get_position(position))
235
239
  end
236
240
 
241
+ # When I iterate over the name index of User
242
+ When /^I iterate over the (\w+) index of (\w+)$/ do |field,class_name|
243
+ klass = get_class(class_name)
244
+ index = klass.property(field.to_sym).index
245
+ @results = []
246
+ index.each do |key,values|
247
+ values.each do |value|
248
+ @results << [key,value]
249
+ end
250
+ end
251
+ end
252
+
237
253
  ################################################################
238
254
  # Then
239
255
  ################################################################
@@ -272,12 +288,13 @@ Then /^the (\w+) (\w+) should not have (a|an )?(\w+)$/ do |position, class_name,
272
288
  end
273
289
 
274
290
  Then /^the (\w+) (\w+) should not exist$/ do |position,class_name|
275
- (lambda {get_instance(class_name,position)}).should raise_error(IndexError)
291
+ get_instance(class_name,position).should == nil
276
292
  end
277
293
 
278
- Then /^the (\w+) of the (\w+) (\w+) should be equal to the (\w+) (\w+)$/ do |field, position1,class1,position2,class2|
294
+ Then /^the (\w+) of the (\w+) (\w+) should be equal to the (\w+) (\w+)( persisted)?$/ do |field, position1,class1,position2,class2,persisted|
295
+ created = !persisted
279
296
  get_instance(class1,position1).send(field.to_sym).should ==
280
- get_instance(class2,position2,true)
297
+ get_instance(class2,position2,created)
281
298
  end
282
299
 
283
300
  Then /^the (\w+) of the (\w+) (\w+) should be nil$/ do |field,position1,class1|
@@ -313,9 +330,10 @@ Then /^(\w+)(\([^)]*\))? from (\d+) to (\d+) should have (\w+) of (\w+) equal to
313
330
  end
314
331
  end
315
332
 
316
- Then /^the (\w+) of (\w+) of the (\w+) (\w+) should be equal to the (\w+) (\w+)$/ do |position0,field,position1,class1,position2,class2|
333
+ Then /^the (\w+) of (\w+) of the (\w+) (\w+) should be equal to the (\w+) (\w+)( persisted)?$/ do |position0,field,position1,class1,position2,class2,persisted|
334
+ created = !persisted
317
335
  get_instance(class1,position1).send(field.to_sym)[get_position(position0)].should ==
318
- get_instance(class2,position2,true)
336
+ get_instance(class2,position2,created)
319
337
  end
320
338
 
321
339
  Then /^the (\w+) of (\w+) of the (\w+) (\w+) should be nil$/ do |position0,field,position1,class1|
@@ -396,3 +414,28 @@ end
396
414
  Then /^([\w:]+) should be raised$/ do |exception|
397
415
  @error.class.to_s.should == exception
398
416
  end
417
+
418
+ # Then some User with 'Fred' name should be equal to the first User
419
+ Then /^some (\w+) with '([^']*)' (\w+) should be equal to the (\w+) (\w+)$/ do |class1,value,field,position2,class2|
420
+ objects = get_class(class1).send("find_all_by_#{field}",get_value(value))
421
+ expected = get_instance(class2,position2)
422
+ objects.any?{|o| o == expected }.should == true
423
+ end
424
+
425
+ # Then the first User with 'Fred' name should be equal to the first User
426
+ Then /^the first (\w+) with '([^']*)' (\w+) should be equal to the (\w+) (\w+)$/ do |class1,value,field,position2,class2|
427
+ get_class(class1).send("find_by_#{field}",get_value(value)).should ==
428
+ get_instance(class2,position2)
429
+ end
430
+
431
+ # Then there should be 1 User with 'John' name in the iteration results
432
+ Then /^there should be (\d) (\w+)(?:\([^)]*\))? with '([^']*)' (\w+) in the iteration results$/ do |count,class_name,value,field|
433
+ @results.select{|k,v| k == value && v.send(field.to_sym) == value}.size.should == count.to_i
434
+ end
435
+
436
+ #Then the intersection size of automobiles of the first and the second Caveman should equal 2
437
+ Then /^the intersection size of (\w+) of the (\w+) and the (\w+) (\w+) should equal (\d+)$/ do |field,position1,position2,klass,count|
438
+ elements1 = get_instance(klass,position1).send(field.to_sym)
439
+ elements2 = get_instance(klass,position2).send(field.to_sym)
440
+ elements1.intersection_size(elements2).should == count.to_i
441
+ end