dm-core 0.9.11 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. data/.autotest +17 -14
  2. data/.gitignore +3 -1
  3. data/FAQ +6 -5
  4. data/History.txt +5 -50
  5. data/Manifest.txt +66 -76
  6. data/QUICKLINKS +1 -1
  7. data/README.txt +21 -15
  8. data/Rakefile +6 -7
  9. data/SPECS +2 -29
  10. data/TODO +1 -1
  11. data/deps.rip +2 -0
  12. data/dm-core.gemspec +11 -15
  13. data/lib/dm-core.rb +105 -110
  14. data/lib/dm-core/adapters.rb +135 -16
  15. data/lib/dm-core/adapters/abstract_adapter.rb +251 -181
  16. data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
  17. data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
  18. data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
  19. data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
  20. data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
  21. data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
  22. data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
  23. data/lib/dm-core/associations/many_to_many.rb +372 -90
  24. data/lib/dm-core/associations/many_to_one.rb +220 -73
  25. data/lib/dm-core/associations/one_to_many.rb +319 -255
  26. data/lib/dm-core/associations/one_to_one.rb +66 -53
  27. data/lib/dm-core/associations/relationship.rb +561 -156
  28. data/lib/dm-core/collection.rb +1101 -379
  29. data/lib/dm-core/core_ext/kernel.rb +12 -0
  30. data/lib/dm-core/core_ext/symbol.rb +10 -0
  31. data/lib/dm-core/identity_map.rb +4 -34
  32. data/lib/dm-core/migrations.rb +1283 -0
  33. data/lib/dm-core/model.rb +570 -369
  34. data/lib/dm-core/model/descendant_set.rb +81 -0
  35. data/lib/dm-core/model/hook.rb +45 -0
  36. data/lib/dm-core/model/is.rb +32 -0
  37. data/lib/dm-core/model/property.rb +247 -0
  38. data/lib/dm-core/model/relationship.rb +335 -0
  39. data/lib/dm-core/model/scope.rb +90 -0
  40. data/lib/dm-core/property.rb +808 -273
  41. data/lib/dm-core/property_set.rb +141 -98
  42. data/lib/dm-core/query.rb +1037 -483
  43. data/lib/dm-core/query/conditions/comparison.rb +872 -0
  44. data/lib/dm-core/query/conditions/operation.rb +221 -0
  45. data/lib/dm-core/query/direction.rb +43 -0
  46. data/lib/dm-core/query/operator.rb +84 -0
  47. data/lib/dm-core/query/path.rb +138 -0
  48. data/lib/dm-core/query/sort.rb +45 -0
  49. data/lib/dm-core/repository.rb +210 -94
  50. data/lib/dm-core/resource.rb +641 -421
  51. data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
  52. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
  53. data/lib/dm-core/support/chainable.rb +22 -0
  54. data/lib/dm-core/support/deprecate.rb +12 -0
  55. data/lib/dm-core/support/logger.rb +13 -0
  56. data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
  57. data/lib/dm-core/transaction.rb +333 -92
  58. data/lib/dm-core/type.rb +98 -60
  59. data/lib/dm-core/types/boolean.rb +1 -1
  60. data/lib/dm-core/types/discriminator.rb +34 -20
  61. data/lib/dm-core/types/object.rb +7 -4
  62. data/lib/dm-core/types/paranoid_boolean.rb +11 -9
  63. data/lib/dm-core/types/paranoid_datetime.rb +11 -9
  64. data/lib/dm-core/types/serial.rb +3 -3
  65. data/lib/dm-core/types/text.rb +3 -4
  66. data/lib/dm-core/version.rb +1 -1
  67. data/script/performance.rb +102 -109
  68. data/script/profile.rb +169 -38
  69. data/spec/lib/adapter_helpers.rb +105 -0
  70. data/spec/lib/collection_helpers.rb +18 -0
  71. data/spec/lib/counter_adapter.rb +34 -0
  72. data/spec/lib/pending_helpers.rb +27 -0
  73. data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
  74. data/spec/public/associations/many_to_many_spec.rb +193 -0
  75. data/spec/public/associations/many_to_one_spec.rb +73 -0
  76. data/spec/public/associations/one_to_many_spec.rb +77 -0
  77. data/spec/public/associations/one_to_one_spec.rb +156 -0
  78. data/spec/public/collection_spec.rb +65 -0
  79. data/spec/public/migrations_spec.rb +359 -0
  80. data/spec/public/model/relationship_spec.rb +924 -0
  81. data/spec/public/model_spec.rb +159 -0
  82. data/spec/public/property_spec.rb +829 -0
  83. data/spec/public/resource_spec.rb +71 -0
  84. data/spec/public/sel_spec.rb +44 -0
  85. data/spec/public/setup_spec.rb +145 -0
  86. data/spec/public/shared/association_collection_shared_spec.rb +317 -0
  87. data/spec/public/shared/collection_shared_spec.rb +1670 -0
  88. data/spec/public/shared/finder_shared_spec.rb +1619 -0
  89. data/spec/public/shared/resource_shared_spec.rb +924 -0
  90. data/spec/public/shared/sel_shared_spec.rb +112 -0
  91. data/spec/public/transaction_spec.rb +129 -0
  92. data/spec/public/types/discriminator_spec.rb +130 -0
  93. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  94. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  95. data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
  96. data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
  97. data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
  98. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
  99. data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
  100. data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
  101. data/spec/semipublic/associations/relationship_spec.rb +194 -0
  102. data/spec/semipublic/associations_spec.rb +177 -0
  103. data/spec/semipublic/collection_spec.rb +142 -0
  104. data/spec/semipublic/property_spec.rb +61 -0
  105. data/spec/semipublic/query/conditions_spec.rb +528 -0
  106. data/spec/semipublic/query/path_spec.rb +443 -0
  107. data/spec/semipublic/query_spec.rb +2626 -0
  108. data/spec/semipublic/resource_spec.rb +47 -0
  109. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  110. data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
  111. data/spec/spec.opts +3 -1
  112. data/spec/spec_helper.rb +80 -57
  113. data/tasks/ci.rb +19 -31
  114. data/tasks/dm.rb +43 -48
  115. data/tasks/doc.rb +8 -11
  116. data/tasks/gemspec.rb +5 -5
  117. data/tasks/hoe.rb +15 -16
  118. data/tasks/install.rb +8 -10
  119. metadata +74 -111
  120. data/lib/dm-core/associations.rb +0 -207
  121. data/lib/dm-core/associations/relationship_chain.rb +0 -81
  122. data/lib/dm-core/auto_migrations.rb +0 -105
  123. data/lib/dm-core/dependency_queue.rb +0 -32
  124. data/lib/dm-core/hook.rb +0 -11
  125. data/lib/dm-core/is.rb +0 -16
  126. data/lib/dm-core/logger.rb +0 -232
  127. data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
  128. data/lib/dm-core/migrator.rb +0 -29
  129. data/lib/dm-core/scope.rb +0 -58
  130. data/lib/dm-core/support.rb +0 -7
  131. data/lib/dm-core/support/array.rb +0 -13
  132. data/lib/dm-core/support/assertions.rb +0 -8
  133. data/lib/dm-core/support/errors.rb +0 -23
  134. data/lib/dm-core/support/kernel.rb +0 -11
  135. data/lib/dm-core/support/symbol.rb +0 -41
  136. data/lib/dm-core/type_map.rb +0 -80
  137. data/lib/dm-core/types.rb +0 -19
  138. data/script/all +0 -4
  139. data/spec/integration/association_spec.rb +0 -1382
  140. data/spec/integration/association_through_spec.rb +0 -203
  141. data/spec/integration/associations/many_to_many_spec.rb +0 -449
  142. data/spec/integration/associations/many_to_one_spec.rb +0 -163
  143. data/spec/integration/associations/one_to_many_spec.rb +0 -188
  144. data/spec/integration/auto_migrations_spec.rb +0 -413
  145. data/spec/integration/collection_spec.rb +0 -1073
  146. data/spec/integration/data_objects_adapter_spec.rb +0 -32
  147. data/spec/integration/dependency_queue_spec.rb +0 -46
  148. data/spec/integration/model_spec.rb +0 -197
  149. data/spec/integration/mysql_adapter_spec.rb +0 -85
  150. data/spec/integration/postgres_adapter_spec.rb +0 -731
  151. data/spec/integration/property_spec.rb +0 -253
  152. data/spec/integration/query_spec.rb +0 -514
  153. data/spec/integration/repository_spec.rb +0 -61
  154. data/spec/integration/resource_spec.rb +0 -513
  155. data/spec/integration/sqlite3_adapter_spec.rb +0 -352
  156. data/spec/integration/sti_spec.rb +0 -273
  157. data/spec/integration/strategic_eager_loading_spec.rb +0 -156
  158. data/spec/integration/transaction_spec.rb +0 -75
  159. data/spec/integration/type_spec.rb +0 -275
  160. data/spec/lib/logging_helper.rb +0 -18
  161. data/spec/lib/mock_adapter.rb +0 -27
  162. data/spec/lib/model_loader.rb +0 -100
  163. data/spec/lib/publicize_methods.rb +0 -28
  164. data/spec/models/content.rb +0 -16
  165. data/spec/models/vehicles.rb +0 -34
  166. data/spec/models/zoo.rb +0 -48
  167. data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
  168. data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
  169. data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
  170. data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
  171. data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
  172. data/spec/unit/associations/many_to_many_spec.rb +0 -32
  173. data/spec/unit/associations/many_to_one_spec.rb +0 -159
  174. data/spec/unit/associations/one_to_many_spec.rb +0 -393
  175. data/spec/unit/associations/one_to_one_spec.rb +0 -7
  176. data/spec/unit/associations/relationship_spec.rb +0 -71
  177. data/spec/unit/associations_spec.rb +0 -242
  178. data/spec/unit/auto_migrations_spec.rb +0 -111
  179. data/spec/unit/collection_spec.rb +0 -182
  180. data/spec/unit/data_mapper_spec.rb +0 -35
  181. data/spec/unit/identity_map_spec.rb +0 -126
  182. data/spec/unit/is_spec.rb +0 -80
  183. data/spec/unit/migrator_spec.rb +0 -33
  184. data/spec/unit/model_spec.rb +0 -321
  185. data/spec/unit/naming_conventions_spec.rb +0 -36
  186. data/spec/unit/property_set_spec.rb +0 -90
  187. data/spec/unit/property_spec.rb +0 -753
  188. data/spec/unit/query_spec.rb +0 -571
  189. data/spec/unit/repository_spec.rb +0 -93
  190. data/spec/unit/resource_spec.rb +0 -649
  191. data/spec/unit/scope_spec.rb +0 -142
  192. data/spec/unit/transaction_spec.rb +0 -493
  193. data/spec/unit/type_map_spec.rb +0 -114
  194. data/spec/unit/type_spec.rb +0 -119
@@ -0,0 +1,1619 @@
1
+ share_examples_for 'Finder Interface' do
2
+ before :all do
3
+ %w[ @article_model @article @other @articles ].each do |ivar|
4
+ raise "+#{ivar}+ should be defined in before block" unless instance_variable_defined?(ivar)
5
+ raise "+#{ivar}+ should not be nil in before block" unless instance_variable_get(ivar)
6
+ end
7
+ end
8
+
9
+ before :all do
10
+ @no_join = defined?(DataMapper::Adapters::InMemoryAdapter) && @adapter.kind_of?(DataMapper::Adapters::InMemoryAdapter) ||
11
+ defined?(DataMapper::Adapters::YamlAdapter) && @adapter.kind_of?(DataMapper::Adapters::YamlAdapter)
12
+
13
+ @many_to_many = @articles.kind_of?(DataMapper::Associations::ManyToMany::Collection)
14
+
15
+ @skip = @no_join && @many_to_many
16
+ end
17
+
18
+ before do
19
+ pending if @skip
20
+ end
21
+
22
+ [ :[], :slice ].each do |method|
23
+ it { @articles.should respond_to(method) }
24
+
25
+ describe "##{method}" do
26
+ before :all do
27
+ 1.upto(10) { |number| @articles.create(:content => "Article #{number}") }
28
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
29
+ end
30
+
31
+ describe 'with a positive offset' do
32
+ before :all do
33
+ unless @skip
34
+ @return = @resource = @articles.send(method, 0)
35
+ end
36
+ end
37
+
38
+ it 'should return a Resource' do
39
+ @return.should be_kind_of(DataMapper::Resource)
40
+ end
41
+
42
+ it 'should return expected Resource' do
43
+ @return.should == @copy.entries.send(method, 0)
44
+ end
45
+
46
+ it 'should orphan the Resource' do
47
+ @resource.collection.should_not equal(@articles)
48
+ end
49
+ end
50
+
51
+ describe 'with a positive offset and length' do
52
+ before :all do
53
+ @return = @resources = @articles.send(method, 5, 5)
54
+ end
55
+
56
+ it 'should return a Collection' do
57
+ @return.should be_kind_of(DataMapper::Collection)
58
+ end
59
+
60
+ it 'should return the expected Resource' do
61
+ @return.should == @copy.entries.send(method, 5, 5)
62
+ end
63
+
64
+ it 'should orphan the Resources' do
65
+ @resources.each { |resource| resource.collection.should_not equal(@articles) }
66
+ end
67
+
68
+ it 'should scope the Collection' do
69
+ @resources.reload.should == @copy.entries.send(method, 5, 5)
70
+ end
71
+ end
72
+
73
+ describe 'with a positive range' do
74
+ before :all do
75
+ @return = @resources = @articles.send(method, 5..10)
76
+ end
77
+
78
+ it 'should return a Collection' do
79
+ @return.should be_kind_of(DataMapper::Collection)
80
+ end
81
+
82
+ it 'should return the expected Resources' do
83
+ @return.should == @copy.entries.send(method, 5..10)
84
+ end
85
+
86
+ it 'should orphan the Resources' do
87
+ @resources.each { |resource| resource.collection.should_not equal(@articles) }
88
+ end
89
+
90
+ it 'should scope the Collection' do
91
+ @resources.reload.should == @copy.entries.send(method, 5..10)
92
+ end
93
+ end
94
+
95
+ describe 'with a negative offset' do
96
+ before :all do
97
+ unless @skip
98
+ @return = @resource = @articles.send(method, -1)
99
+ end
100
+ end
101
+
102
+ it 'should return a Resource' do
103
+ @return.should be_kind_of(DataMapper::Resource)
104
+ end
105
+
106
+ it 'should return expected Resource' do
107
+ @return.should == @copy.entries.send(method, -1)
108
+ end
109
+
110
+ it 'should orphan the Resource' do
111
+ @resource.collection.should_not equal(@articles)
112
+ end
113
+ end
114
+
115
+ describe 'with a negative offset and length' do
116
+ before :all do
117
+ @return = @resources = @articles.send(method, -5, 5)
118
+ end
119
+
120
+ it 'should return a Collection' do
121
+ @return.should be_kind_of(DataMapper::Collection)
122
+ end
123
+
124
+ it 'should return the expected Resources' do
125
+ @return.should == @copy.entries.send(method, -5, 5)
126
+ end
127
+
128
+ it 'should orphan the Resources' do
129
+ @resources.each { |resource| resource.collection.should_not equal(@articles) }
130
+ end
131
+
132
+ it 'should scope the Collection' do
133
+ @resources.reload.should == @copy.entries.send(method, -5, 5)
134
+ end
135
+ end
136
+
137
+ describe 'with a negative range' do
138
+ before :all do
139
+ @return = @resources = @articles.send(method, -5..-2)
140
+ end
141
+
142
+ it 'should return a Collection' do
143
+ @return.should be_kind_of(DataMapper::Collection)
144
+ end
145
+
146
+ it 'should return the expected Resources' do
147
+ @return.to_a.should == @copy.entries.send(method, -5..-2)
148
+ end
149
+
150
+ it 'should orphan the Resources' do
151
+ @resources.each { |resource| resource.collection.should_not equal(@articles) }
152
+ end
153
+
154
+ it 'should scope the Collection' do
155
+ @resources.reload.should == @copy.entries.send(method, -5..-2)
156
+ end
157
+ end
158
+
159
+ describe 'with an empty exclusive range' do
160
+ before :all do
161
+ @return = @resources = @articles.send(method, 0...0)
162
+ end
163
+
164
+ it 'should return a Collection' do
165
+ @return.should be_kind_of(DataMapper::Collection)
166
+ end
167
+
168
+ it 'should return the expected value' do
169
+ @return.to_a.should == @copy.entries.send(method, 0...0)
170
+ end
171
+
172
+ it 'should be empty' do
173
+ @return.should be_empty
174
+ end
175
+ end
176
+
177
+ describe 'with an offset not within the Collection' do
178
+ before :all do
179
+ unless @skip
180
+ @return = @articles.send(method, 99)
181
+ end
182
+ end
183
+
184
+ it 'should return nil' do
185
+ @return.should be_nil
186
+ end
187
+ end
188
+
189
+ describe 'with an offset and length not within the Collection' do
190
+ before :all do
191
+ @return = @articles.send(method, 99, 1)
192
+ end
193
+
194
+ it 'should return a Collection' do
195
+ @return.should be_kind_of(DataMapper::Collection)
196
+ end
197
+
198
+ it 'should be empty' do
199
+ @return.should be_empty
200
+ end
201
+ end
202
+
203
+ describe 'with a range not within the Collection' do
204
+ before :all do
205
+ @return = @articles.send(method, 99..100)
206
+ end
207
+
208
+ it 'should return a Collection' do
209
+ @return.should be_kind_of(DataMapper::Collection)
210
+ end
211
+
212
+ it 'should be empty' do
213
+ @return.should be_empty
214
+ end
215
+ end
216
+ end
217
+ end
218
+
219
+ it { @articles.should respond_to(:all) }
220
+
221
+ describe '#all' do
222
+ describe 'with no arguments' do
223
+ before :all do
224
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
225
+
226
+ @return = @collection = @articles.all
227
+ end
228
+
229
+ it 'should return a Collection' do
230
+ @return.should be_kind_of(DataMapper::Collection)
231
+ end
232
+
233
+ it 'should return a new instance' do
234
+ @return.should_not equal(@articles)
235
+ end
236
+
237
+ it 'should be expected Resources' do
238
+ @collection.should == @articles.entries
239
+ end
240
+
241
+ it 'should not have a Query the same as the original' do
242
+ @return.query.should_not equal(@articles.query)
243
+ end
244
+
245
+ it 'should have a Query equal to the original' do
246
+ @return.query.should eql(@articles.query)
247
+ end
248
+
249
+ it 'should scope the Collection' do
250
+ @collection.reload.should == @copy.entries
251
+ end
252
+ end
253
+
254
+ describe 'with a query' do
255
+ before :all do
256
+ @new = @articles.create(:content => 'New Article')
257
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
258
+
259
+ @return = @articles.all(:content => [ 'New Article' ])
260
+ end
261
+
262
+ it 'should return a Collection' do
263
+ @return.should be_kind_of(DataMapper::Collection)
264
+ end
265
+
266
+ it 'should return a new instance' do
267
+ @return.should_not equal(@articles)
268
+ end
269
+
270
+ it 'should be expected Resources' do
271
+ @return.should == [ @new ]
272
+ end
273
+
274
+ it 'should have a different query than original Collection' do
275
+ @return.query.should_not equal(@articles.query)
276
+ end
277
+
278
+ it 'should scope the Collection' do
279
+ @return.reload.should == @copy.entries.select { |resource| resource.content == 'New Article' }
280
+ end
281
+ end
282
+
283
+ describe 'with a query using raw conditions' do
284
+ before do
285
+ pending unless defined?(DataMapper::Adapters::DataObjectsAdapter) && @adapter.kind_of?(DataMapper::Adapters::DataObjectsAdapter)
286
+ end
287
+
288
+ before :all do
289
+ @new = @articles.create(:subtitle => 'New Article')
290
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
291
+
292
+ @return = @articles.all(:conditions => [ 'subtitle = ?', 'New Article' ])
293
+ end
294
+
295
+ it 'should return a Collection' do
296
+ @return.should be_kind_of(DataMapper::Collection)
297
+ end
298
+
299
+ it 'should return a new instance' do
300
+ @return.should_not equal(@articles)
301
+ end
302
+
303
+ it 'should be expected Resources' do
304
+ @return.should == [ @new ]
305
+ end
306
+
307
+ it 'should have a different query than original Collection' do
308
+ @return.query.should_not == @articles.query
309
+ end
310
+
311
+ it 'should scope the Collection' do
312
+ @return.reload.should == @copy.entries.select { |resource| resource.subtitle == 'New Article' }.first(1)
313
+ end
314
+ end
315
+
316
+ describe 'with a query that is out of range' do
317
+ it 'should raise an exception' do
318
+ lambda {
319
+ @articles.all(:limit => 10).all(:offset => 10)
320
+ }.should raise_error(RangeError, 'offset 10 and limit 0 are outside allowed range')
321
+ end
322
+ end
323
+
324
+ describe 'with a query using a m:1 relationship' do
325
+ describe 'with a resource' do
326
+ before :all do
327
+ @return = @articles.all(:original => @original)
328
+ end
329
+
330
+ it 'should return a Collection' do
331
+ @return.should be_kind_of(DataMapper::Collection)
332
+ end
333
+
334
+ it 'should be expected Resources' do
335
+ @return.should == [ @article ]
336
+ end
337
+
338
+ it 'should have a valid query' do
339
+ @return.query.should be_valid
340
+ end
341
+ end
342
+
343
+ describe 'with a collection' do
344
+ before :all do
345
+ @collection = @article_model.all(@article_model.key.zip(@original.key).to_hash)
346
+
347
+ @return = @articles.all(:original => @collection)
348
+ end
349
+
350
+ it 'should return a Collection' do
351
+ @return.should be_kind_of(DataMapper::Collection)
352
+ end
353
+
354
+ it 'should be expected Resources' do
355
+ @return.should == [ @article ]
356
+ end
357
+
358
+ it 'should have a valid query' do
359
+ @return.query.should be_valid
360
+ end
361
+
362
+ end
363
+
364
+ describe 'with an empty Array' do
365
+ before :all do
366
+ @return = @articles.all(:original => [])
367
+ end
368
+
369
+ it 'should return a Collection' do
370
+ @return.should be_kind_of(DataMapper::Collection)
371
+ end
372
+
373
+ it 'should be an empty Collection' do
374
+ @return.should be_empty
375
+ end
376
+
377
+ it 'should not have a valid query' do
378
+ @return.query.should_not be_valid
379
+ end
380
+ end
381
+
382
+ describe 'with a nil value' do
383
+ before :all do
384
+ @return = @articles.all(:original => nil)
385
+ end
386
+
387
+ it 'should return a Collection' do
388
+ @return.should be_kind_of(DataMapper::Collection)
389
+ end
390
+
391
+ if respond_to?(:model?) && model?
392
+ it 'should be expected Resources' do
393
+ @return.should == [ @original, @other ]
394
+ end
395
+ else
396
+ it 'should be an empty Collection' do
397
+ @return.should be_empty
398
+ end
399
+ end
400
+
401
+ it 'should have a valid query' do
402
+ @return.query.should be_valid
403
+ end
404
+ end
405
+ end
406
+
407
+ describe 'with a query using a 1:1 relationship' do
408
+ before :all do
409
+ @new = @articles.create(:content => 'New Article', :original => @article)
410
+ end
411
+
412
+ describe 'with a resource' do
413
+ before :all do
414
+ @return = @articles.all(:previous => @new)
415
+ end
416
+
417
+ it 'should return a Collection' do
418
+ @return.should be_kind_of(DataMapper::Collection)
419
+ end
420
+
421
+ it 'should be expected Resources' do
422
+ @return.should == [ @article ]
423
+ end
424
+
425
+ it 'should have a valid query' do
426
+ @return.query.should be_valid
427
+ end
428
+ end
429
+
430
+ describe 'with a collection' do
431
+ before :all do
432
+ @collection = @article_model.all(@article_model.key.zip(@new.key).to_hash)
433
+
434
+ @return = @articles.all(:previous => @collection)
435
+ end
436
+
437
+ it 'should return a Collection' do
438
+ @return.should be_kind_of(DataMapper::Collection)
439
+ end
440
+
441
+ it 'should be expected Resources' do
442
+ @return.should == [ @article ]
443
+ end
444
+
445
+ it 'should have a valid query' do
446
+ @return.query.should be_valid
447
+ end
448
+ end
449
+
450
+ describe 'with an empty Array' do
451
+ before :all do
452
+ @return = @articles.all(:previous => [])
453
+ end
454
+
455
+ it 'should return a Collection' do
456
+ @return.should be_kind_of(DataMapper::Collection)
457
+ end
458
+
459
+ it 'should be an empty Collection' do
460
+ @return.should be_empty
461
+ end
462
+
463
+ it 'should not have a valid query' do
464
+ @return.query.should_not be_valid
465
+ end
466
+ end
467
+
468
+ describe 'with a nil value' do
469
+ before :all do
470
+ @return = @articles.all(:previous => nil)
471
+ end
472
+
473
+ it 'should return a Collection' do
474
+ @return.should be_kind_of(DataMapper::Collection)
475
+ end
476
+
477
+ it 'should be an empty Collection' do
478
+ @return.should be_empty
479
+ end
480
+
481
+ it 'should have a valid query' do
482
+ @return.query.should be_valid
483
+ end
484
+ end
485
+ end
486
+
487
+ describe 'with a query using a 1:m relationship' do
488
+ before :all do
489
+ @new = @articles.create(:content => 'New Article', :original => @article)
490
+ end
491
+
492
+ describe 'with a resource' do
493
+ before :all do
494
+ @return = @articles.all(:revisions => @new)
495
+ end
496
+
497
+ it 'should return a Collection' do
498
+ @return.should be_kind_of(DataMapper::Collection)
499
+ end
500
+
501
+ it 'should be expected Resources' do
502
+ @return.should == [ @article ]
503
+ end
504
+
505
+ it 'should have a valid query' do
506
+ @return.query.should be_valid
507
+ end
508
+ end
509
+
510
+ describe 'with a collection' do
511
+ before :all do
512
+ @collection = @article_model.all(@article_model.key.zip(@new.key).to_hash)
513
+
514
+ @return = @articles.all(:revisions => @collection)
515
+ end
516
+
517
+ it 'should return a Collection' do
518
+ @return.should be_kind_of(DataMapper::Collection)
519
+ end
520
+
521
+ it 'should be expected Resources' do
522
+ @return.should == [ @article ]
523
+ end
524
+
525
+ it 'should have a valid query' do
526
+ @return.query.should be_valid
527
+ end
528
+ end
529
+
530
+ describe 'with an empty Array' do
531
+ before :all do
532
+ @return = @articles.all(:revisions => [])
533
+ end
534
+
535
+ it 'should return a Collection' do
536
+ @return.should be_kind_of(DataMapper::Collection)
537
+ end
538
+
539
+ it 'should be an empty Collection' do
540
+ @return.should be_empty
541
+ end
542
+
543
+ it 'should not have a valid query' do
544
+ @return.query.should_not be_valid
545
+ end
546
+ end
547
+
548
+ describe 'with a nil value' do
549
+ before :all do
550
+ @return = @articles.all(:revisions => nil)
551
+ end
552
+
553
+ it 'should return a Collection' do
554
+ @return.should be_kind_of(DataMapper::Collection)
555
+ end
556
+
557
+ it 'should be an empty Collection' do
558
+ @return.should be_empty
559
+ end
560
+
561
+ it 'should have a valid query' do
562
+ @return.query.should be_valid
563
+ end
564
+ end
565
+ end
566
+
567
+ describe 'with a query using a m:m relationship' do
568
+ before :all do
569
+ @publication = @article.publications.create(:name => 'DataMapper Now')
570
+ end
571
+
572
+ describe 'with a resource' do
573
+ before :all do
574
+ @return = @articles.all(:publications => @publication)
575
+ end
576
+
577
+ it 'should return a Collection' do
578
+ @return.should be_kind_of(DataMapper::Collection)
579
+ end
580
+
581
+ it 'should be expected Resources' do
582
+ pending 'TODO' do
583
+ @return.should == [ @article ]
584
+ end
585
+ end
586
+
587
+ it 'should have a valid query' do
588
+ @return.query.should be_valid
589
+ end
590
+ end
591
+
592
+ describe 'with a collection' do
593
+ before :all do
594
+ @collection = @publication_model.all(@publication_model.key.zip(@publication.key).to_hash)
595
+
596
+ @return = @articles.all(:publications => @collection)
597
+ end
598
+
599
+ it 'should return a Collection' do
600
+ @return.should be_kind_of(DataMapper::Collection)
601
+ end
602
+
603
+ it 'should be expected Resources' do
604
+ pending 'TODO' do
605
+ @return.should == [ @article ]
606
+ end
607
+ end
608
+
609
+ it 'should have a valid query' do
610
+ @return.query.should be_valid
611
+ end
612
+ end
613
+
614
+ describe 'with an empty Array' do
615
+ before :all do
616
+ @return = @articles.all(:publications => [])
617
+ end
618
+
619
+ it 'should return a Collection' do
620
+ @return.should be_kind_of(DataMapper::Collection)
621
+ end
622
+
623
+ it 'should be an empty Collection' do
624
+ @return.should be_empty
625
+ end
626
+
627
+ it 'should not have a valid query' do
628
+ @return.query.should_not be_valid
629
+ end
630
+ end
631
+
632
+ describe 'with a nil value' do
633
+ before :all do
634
+ @return = @articles.all(:publications => nil)
635
+ end
636
+
637
+ it 'should return a Collection' do
638
+ @return.should be_kind_of(DataMapper::Collection)
639
+ end
640
+
641
+ it 'should be an empty Collection' do
642
+ @return.should be_empty
643
+ end
644
+
645
+ it 'should have a valid query' do
646
+ @return.query.should be_valid
647
+ end
648
+ end
649
+ end
650
+ end
651
+
652
+ it { @articles.should respond_to(:at) }
653
+
654
+ describe '#at' do
655
+ before :all do
656
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
657
+ @copy.to_a
658
+ end
659
+
660
+ describe 'with positive offset' do
661
+ before :all do
662
+ @return = @resource = @articles.at(0)
663
+ end
664
+
665
+ should_not_be_a_kicker
666
+
667
+ it 'should return a Resource' do
668
+ @return.should be_kind_of(DataMapper::Resource)
669
+ end
670
+
671
+ it 'should return expected Resource' do
672
+ @resource.should == @copy.entries.at(0)
673
+ end
674
+
675
+ it 'should orphan the Resource' do
676
+ @resource.collection.should_not equal(@articles)
677
+ end
678
+ end
679
+
680
+ # describe 'with positive offset', 'after prepending to the collection' do
681
+ # before :all do
682
+ # @return = @resource = @articles.unshift(@other).at(0)
683
+ # end
684
+ #
685
+ # should_not_be_a_kicker
686
+ #
687
+ # it 'should return a Resource' do
688
+ # @return.should be_kind_of(DataMapper::Resource)
689
+ # end
690
+ #
691
+ # it 'should return expected Resource' do
692
+ # @resource.should equal(@other)
693
+ # end
694
+ #
695
+ # it 'should relate the Resource to the Collection' do
696
+ # @resource.collection.should equal(@articles)
697
+ # end
698
+ # end
699
+
700
+ describe 'with negative offset' do
701
+ before :all do
702
+ @return = @resource = @articles.at(-1)
703
+ end
704
+
705
+ should_not_be_a_kicker
706
+
707
+ it 'should return a Resource' do
708
+ @return.should be_kind_of(DataMapper::Resource)
709
+ end
710
+
711
+ it 'should return expected Resource' do
712
+ @resource.should == @copy.entries.at(-1)
713
+ end
714
+
715
+ it 'should orphan the Resource' do
716
+ @resource.collection.should_not equal(@articles)
717
+ end
718
+ end
719
+
720
+ # describe 'with negative offset', 'after appending to the collection' do
721
+ # before :all do
722
+ # @return = @resource = @articles.push(@other).at(-1)
723
+ # end
724
+ #
725
+ # should_not_be_a_kicker
726
+ #
727
+ # it 'should return a Resource' do
728
+ # @return.should be_kind_of(DataMapper::Resource)
729
+ # end
730
+ #
731
+ # it 'should return expected Resource' do
732
+ # @resource.should equal(@other)
733
+ # end
734
+ #
735
+ # it 'should relate the Resource to the Collection' do
736
+ # @resource.collection.should equal(@articles)
737
+ # end
738
+ # end
739
+ end
740
+
741
+ it { @articles.should respond_to(:first) }
742
+
743
+ describe '#first' do
744
+ before :all do
745
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
746
+
747
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
748
+ @copy.to_a
749
+ end
750
+
751
+ describe 'with no arguments' do
752
+ before :all do
753
+ @return = @resource = @articles.first
754
+ end
755
+
756
+ it 'should return a Resource' do
757
+ @return.should be_kind_of(DataMapper::Resource)
758
+ end
759
+
760
+ it 'should be first Resource in the Collection' do
761
+ @resource.should == @copy.entries.first
762
+ end
763
+
764
+ it 'should orphan the Resource' do
765
+ @resource.collection.should_not equal(@articles)
766
+ end
767
+ end
768
+
769
+ # describe 'with no arguments', 'after prepending to the collection' do
770
+ # before :all do
771
+ # @return = @resource = @articles.unshift(@other).first
772
+ # end
773
+ #
774
+ # it 'should return a Resource' do
775
+ # @return.should be_kind_of(DataMapper::Resource)
776
+ # end
777
+ #
778
+ # it 'should return expected Resource' do
779
+ # @resource.should equal(@other)
780
+ # end
781
+ #
782
+ # it 'should be first Resource in the Collection' do
783
+ # @resource.should equal(@copy.entries.unshift(@other).first)
784
+ # end
785
+ #
786
+ # it 'should not relate the Resource to the Collection' do
787
+ # @resource.collection.should_not equal(@articles)
788
+ # end
789
+ # end
790
+
791
+ describe 'with empty query' do
792
+ before :all do
793
+ @return = @resource = @articles.first({})
794
+ end
795
+
796
+ it 'should return a Resource' do
797
+ @return.should be_kind_of(DataMapper::Resource)
798
+ end
799
+
800
+ it 'should be first Resource in the Collection' do
801
+ @resource.should == @copy.entries.first
802
+ end
803
+
804
+ it 'should orphan the Resource' do
805
+ @resource.collection.should_not equal(@articles)
806
+ end
807
+ end
808
+
809
+ # describe 'with empty query', 'after prepending to the collection' do
810
+ # before :all do
811
+ # @return = @resource = @articles.unshift(@other).first({})
812
+ # end
813
+ #
814
+ # it 'should return a Resource' do
815
+ # @return.should be_kind_of(DataMapper::Resource)
816
+ # end
817
+ #
818
+ # it 'should return expected Resource' do
819
+ # @resource.should equal(@other)
820
+ # end
821
+ #
822
+ # it 'should be first Resource in the Collection' do
823
+ # @resource.should equal(@copy.entries.unshift(@other).first)
824
+ # end
825
+ #
826
+ # it 'should not relate the Resource to the Collection' do
827
+ # @resource.collection.should_not equal(@articles)
828
+ # end
829
+ # end
830
+
831
+ describe 'with a query' do
832
+ before :all do
833
+ @return = @resource = @articles.first(:content => 'Sample')
834
+ end
835
+
836
+ it 'should return a Resource' do
837
+ @return.should be_kind_of(DataMapper::Resource)
838
+ end
839
+
840
+ it 'should should be the first Resource in the Collection matching the query' do
841
+ @resource.should == @article
842
+ end
843
+
844
+ it 'should orphan the Resource' do
845
+ @resource.collection.should_not equal(@articles)
846
+ end
847
+ end
848
+
849
+ describe 'with limit specified' do
850
+ before :all do
851
+ @return = @resources = @articles.first(1)
852
+ end
853
+
854
+ it 'should return a Collection' do
855
+ @return.should be_kind_of(DataMapper::Collection)
856
+ end
857
+
858
+ it 'should be the first N Resources in the Collection' do
859
+ @resources.should == @copy.entries.first(1)
860
+ end
861
+
862
+ it 'should orphan the Resources' do
863
+ @resources.each { |resource| resource.collection.should_not equal(@articles) }
864
+ end
865
+ end
866
+
867
+ describe 'with offset specified' do
868
+ before :all do
869
+ @return = @resource = @articles.first(:offset => 1)
870
+ end
871
+
872
+ it 'should return a Resource' do
873
+ @return.should be_kind_of(DataMapper::Resource)
874
+ end
875
+
876
+ it 'should be the second Resource in the Collection' do
877
+ @resource.should == @copy.entries[1]
878
+ end
879
+
880
+ it 'should orphan the Resource' do
881
+ @resource.collection.should_not equal(@articles)
882
+ end
883
+ end
884
+
885
+ # describe 'with limit specified', 'after prepending to the collection' do
886
+ # before :all do
887
+ # @return = @resources = @articles.unshift(@other).first(1)
888
+ # end
889
+ #
890
+ # it 'should return a Collection' do
891
+ # @return.should be_kind_of(DataMapper::Collection)
892
+ # end
893
+ #
894
+ # it 'should be the expected Collection' do
895
+ # @resources.should == [ @other ]
896
+ # end
897
+ #
898
+ # it 'should be the first N Resources in the Collection' do
899
+ # @resources.should == @copy.entries.unshift(@other).first(1)
900
+ # end
901
+ #
902
+ # it 'should orphan the Resources' do
903
+ # @resources.each { |resource| resource.collection.should_not equal(@articles) }
904
+ # end
905
+ # end
906
+
907
+ describe 'with limit and query specified' do
908
+ before :all do
909
+ @return = @resources = @articles.first(1, :content => 'Sample')
910
+ end
911
+
912
+ it 'should return a Collection' do
913
+ @return.should be_kind_of(DataMapper::Collection)
914
+ end
915
+
916
+ it 'should be the first N Resources in the Collection matching the query' do
917
+ @resources.should == [ @article ]
918
+ end
919
+
920
+ it 'should orphan the Resources' do
921
+ @resources.each { |resource| resource.collection.should_not equal(@articles) }
922
+ end
923
+ end
924
+ end
925
+
926
+ it { @articles.should respond_to(:first_or_create) }
927
+
928
+ describe '#first_or_create' do
929
+ describe 'with conditions that find an existing Resource' do
930
+ before :all do
931
+ @return = @resource = @articles.first_or_create(@article.attributes)
932
+ end
933
+
934
+ it 'should return a Resource' do
935
+ @return.should be_kind_of(DataMapper::Resource)
936
+ end
937
+
938
+ it 'should be expected Resource' do
939
+ @resource.should == @article
940
+ end
941
+
942
+ it 'should be a saved Resource' do
943
+ @resource.should be_saved
944
+ end
945
+
946
+ it 'should orphan the Resource' do
947
+ @resource.collection.should_not equal(@articles)
948
+ end
949
+ end
950
+
951
+ describe 'with conditions that do not find an existing Resource' do
952
+ before :all do
953
+ @conditions = { :content => 'Unknown Content' }
954
+ @attributes = {}
955
+
956
+ @return = @resource = @articles.first_or_create(@conditions, @attributes)
957
+ end
958
+
959
+ it 'should return a Resource' do
960
+ @return.should be_kind_of(DataMapper::Resource)
961
+ end
962
+
963
+ it 'should be expected Resource' do
964
+ @resource.attributes.only(*@conditions.keys).should == @conditions
965
+ end
966
+
967
+ it 'should be a saved Resource' do
968
+ @resource.should be_saved
969
+ end
970
+
971
+ # it 'should relate the Resource' do
972
+ # @resource.collection.should equal(@articles)
973
+ # end
974
+ end
975
+ end
976
+
977
+ it { @articles.should respond_to(:first_or_new) }
978
+
979
+ describe '#first_or_new' do
980
+ describe 'with conditions that find an existing Resource' do
981
+ before :all do
982
+ @return = @resource = @articles.first_or_new(@article.attributes)
983
+ end
984
+
985
+ it 'should return a Resource' do
986
+ @return.should be_kind_of(DataMapper::Resource)
987
+ end
988
+
989
+ it 'should be expected Resource' do
990
+ @resource.should == @article
991
+ end
992
+
993
+ it 'should be a saved Resource' do
994
+ @resource.should be_saved
995
+ end
996
+
997
+ it 'should orphan the Resource' do
998
+ @resource.collection.should_not equal(@articles)
999
+ end
1000
+ end
1001
+
1002
+ describe 'with conditions that do not find an existing Resource' do
1003
+ before :all do
1004
+ @conditions = { :content => 'Unknown Content' }
1005
+ @attributes = {}
1006
+
1007
+ @return = @resource = @articles.first_or_new(@conditions, @attributes)
1008
+ end
1009
+
1010
+ it 'should return a Resource' do
1011
+ @return.should be_kind_of(DataMapper::Resource)
1012
+ end
1013
+
1014
+ it 'should be expected Resource' do
1015
+ @resource.attributes.only(*@conditions.keys).should == @conditions
1016
+ end
1017
+
1018
+ it 'should not be a saved Resource' do
1019
+ @resource.should be_new
1020
+ end
1021
+
1022
+ # it 'should relate the Resource' do
1023
+ # @resource.collection.should equal(@articles)
1024
+ # end
1025
+ end
1026
+ end
1027
+
1028
+ [ :get, :get! ].each do |method|
1029
+ it { @articles.should respond_to(method) }
1030
+
1031
+ describe "##{method}" do
1032
+ describe 'with a key to a Resource within the Collection' do
1033
+ before :all do
1034
+ unless @skip
1035
+ @return = @resource = @articles.send(method, *@article.key)
1036
+ end
1037
+ end
1038
+
1039
+ it 'should return a Resource' do
1040
+ @return.should be_kind_of(DataMapper::Resource)
1041
+ end
1042
+
1043
+ it 'should be matching Resource in the Collection' do
1044
+ @resource.should == @article
1045
+ end
1046
+
1047
+ it 'should orphan the Resource' do
1048
+ @resource.collection.should_not equal(@articles)
1049
+ end
1050
+ end
1051
+
1052
+ describe 'with a key not typecast' do
1053
+ before :all do
1054
+ unless @skip
1055
+ @return = @resource = @articles.send(method, *@article.key.map { |value| value.to_s })
1056
+ end
1057
+ end
1058
+
1059
+ it 'should return a Resource' do
1060
+ @return.should be_kind_of(DataMapper::Resource)
1061
+ end
1062
+
1063
+ it 'should be matching Resource in the Collection' do
1064
+ @resource.should == @article
1065
+ end
1066
+
1067
+ it 'should orphan the Resource' do
1068
+ @resource.collection.should_not equal(@articles)
1069
+ end
1070
+ end
1071
+
1072
+ # describe 'with a key to a Resource within a Collection using a limit' do
1073
+ # before :all do
1074
+ # @articles = @articles.all(:limit => 1)
1075
+ #
1076
+ # @return = @resource = @articles.send(method, *@article.key)
1077
+ # end
1078
+ #
1079
+ # it 'should return a Resource' do
1080
+ # @return.should be_kind_of(DataMapper::Resource)
1081
+ # end
1082
+ #
1083
+ # it 'should be matching Resource in the Collection' do
1084
+ # @resource.should == @article
1085
+ # end
1086
+ #
1087
+ # it 'should orphan the Resource' do
1088
+ # @resource.collection.should_not equal(@articles)
1089
+ # end
1090
+ # end
1091
+ #
1092
+ # describe 'with a key to a Resource within a Collection using an offset' do
1093
+ # before :all do
1094
+ # @new = @articles.create(:content => 'New Article') # TODO: freeze @new
1095
+ # @articles = @articles.all(:offset => 1, :limit => 1)
1096
+ #
1097
+ # @return = @resource = @articles.send(method, *@new.key)
1098
+ # end
1099
+ #
1100
+ # it 'should return a Resource' do
1101
+ # @return.should be_kind_of(DataMapper::Resource)
1102
+ # end
1103
+ #
1104
+ # it 'should be matching Resource in the Collection' do
1105
+ # @resource.should equal(@new)
1106
+ # end
1107
+ #
1108
+ # it 'should orphan the Resource' do
1109
+ # @resource.collection.should_not equal(@articles)
1110
+ # end
1111
+ # end
1112
+
1113
+ describe 'with a key to a Resource not within the Collection' do
1114
+ if method == :get
1115
+ it 'should return nil' do
1116
+ @articles.get(99).should be_nil
1117
+ end
1118
+ else
1119
+ it 'should raise an exception' do
1120
+ lambda {
1121
+ @articles.get!(99)
1122
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key \[99\]")
1123
+ end
1124
+ end
1125
+ end
1126
+
1127
+ describe 'with a key that is nil' do
1128
+ if method == :get
1129
+ it 'should return nil' do
1130
+ @articles.get(nil).should be_nil
1131
+ end
1132
+ else
1133
+ it 'should raise an exception' do
1134
+ lambda {
1135
+ @articles.get!(nil)
1136
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [nil]")
1137
+ end
1138
+ end
1139
+ end
1140
+
1141
+ describe 'with a key that is an empty String' do
1142
+ if method == :get
1143
+ it 'should return nil' do
1144
+ @articles.get('').should be_nil
1145
+ end
1146
+ else
1147
+ it 'should raise an exception' do
1148
+ lambda {
1149
+ @articles.get!('')
1150
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [\"\"]")
1151
+ end
1152
+ end
1153
+ end
1154
+ end
1155
+ end
1156
+
1157
+ it { @articles.should respond_to(:last) }
1158
+
1159
+ describe '#last' do
1160
+ before :all do
1161
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
1162
+
1163
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
1164
+ @copy.to_a
1165
+ end
1166
+
1167
+ describe 'with no arguments' do
1168
+ before :all do
1169
+ @return = @resource = @articles.last
1170
+ end
1171
+
1172
+ it 'should return a Resource' do
1173
+ @return.should be_kind_of(DataMapper::Resource)
1174
+ end
1175
+
1176
+ it 'should be last Resource in the Collection' do
1177
+ @resource.should == @copy.entries.last
1178
+ end
1179
+
1180
+ # it 'should not relate the Resource to the Collection' do
1181
+ # @resource.collection.should_not equal(@articles)
1182
+ # end
1183
+ end
1184
+
1185
+ # describe 'with no arguments', 'after appending to the collection' do
1186
+ # before :all do
1187
+ # @return = @resource = @articles.push(@other).last
1188
+ # end
1189
+ #
1190
+ # it 'should return a Resource' do
1191
+ # @return.should be_kind_of(DataMapper::Resource)
1192
+ # end
1193
+ #
1194
+ # it 'should return expected Resource' do
1195
+ # @resource.should equal(@other)
1196
+ # end
1197
+ #
1198
+ # it 'should be last Resource in the Collection' do
1199
+ # @resource.should equal(@copy.entries.push(@other).last)
1200
+ # end
1201
+ #
1202
+ # it 'should not relate the Resource to the Collection' do
1203
+ # @resource.collection.should_not equal(@articles)
1204
+ # end
1205
+ # end
1206
+
1207
+ describe 'with a query' do
1208
+ before :all do
1209
+ @return = @resource = @articles.last(:content => 'Sample')
1210
+ end
1211
+
1212
+ it 'should return a Resource' do
1213
+ @return.should be_kind_of(DataMapper::Resource)
1214
+ end
1215
+
1216
+ it 'should should be the last Resource in the Collection matching the query' do
1217
+ @resource.should == @article
1218
+ end
1219
+
1220
+ # it 'should not relate the Resource to the Collection' do
1221
+ # @resource.collection.should_not equal(@articles)
1222
+ # end
1223
+ end
1224
+
1225
+ describe 'with limit specified' do
1226
+ before :all do
1227
+ @return = @resources = @articles.last(1)
1228
+ end
1229
+
1230
+ it 'should return a Collection' do
1231
+ @return.should be_kind_of(DataMapper::Collection)
1232
+ end
1233
+
1234
+ it 'should be the last N Resources in the Collection' do
1235
+ @resources.should == @copy.entries.last(1)
1236
+ end
1237
+
1238
+ # it 'should orphan the Resources' do
1239
+ # @resources.each { |resource| resource.collection.should_not equal(@articles) }
1240
+ # end
1241
+ end
1242
+
1243
+ describe 'with offset specified' do
1244
+ before :all do
1245
+ @return = @resource = @articles.last(:offset => 1)
1246
+ end
1247
+
1248
+ it 'should return a Resource' do
1249
+ @return.should be_kind_of(DataMapper::Resource)
1250
+ end
1251
+
1252
+ it 'should be the second Resource in the Collection' do
1253
+ @resource.should == @copy.entries[-2]
1254
+ end
1255
+
1256
+ it 'should orphan the Resource' do
1257
+ @resource.collection.should_not equal(@articles)
1258
+ end
1259
+ end
1260
+
1261
+ # describe 'with limit specified', 'after appending to the collection' do
1262
+ # before :all do
1263
+ # @return = @resources = @articles.push(@other).last(1)
1264
+ # end
1265
+ #
1266
+ # it 'should return a Collection' do
1267
+ # @return.should be_kind_of(DataMapper::Collection)
1268
+ # end
1269
+ #
1270
+ # it 'should be the expected Collection' do
1271
+ # @resources.should == [ @other ]
1272
+ # end
1273
+ #
1274
+ # it 'should be the last N Resources in the Collection' do
1275
+ # @resources.should == @copy.entries.push(@other).last(1)
1276
+ # end
1277
+ #
1278
+ # it 'should orphan the Resources' do
1279
+ # @resources.each { |resource| resource.collection.should_not equal(@articles) }
1280
+ # end
1281
+ # end
1282
+
1283
+ describe 'with limit and query specified' do
1284
+ before :all do
1285
+ @return = @resources = @articles.last(1, :content => 'Sample')
1286
+ end
1287
+
1288
+ it 'should return a Collection' do
1289
+ @return.should be_kind_of(DataMapper::Collection)
1290
+ end
1291
+
1292
+ it 'should be the last N Resources in the Collection matching the query' do
1293
+ @resources.should == [ @article ]
1294
+ end
1295
+
1296
+ # it 'should orphan the Resources' do
1297
+ # @resources.each { |resource| resource.collection.should_not equal(@articles) }
1298
+ # end
1299
+ end
1300
+ end
1301
+
1302
+ it { @articles.should respond_to(:reverse) }
1303
+
1304
+ describe '#reverse' do
1305
+ before :all do
1306
+ @query = @articles.query
1307
+
1308
+ @new = @articles.create(:title => 'Sample Article')
1309
+
1310
+ @return = @articles.reverse
1311
+ end
1312
+
1313
+ it 'should return a Collection' do
1314
+ @return.should be_kind_of(DataMapper::Collection)
1315
+ end
1316
+
1317
+ it 'should return a Collection with reversed entries' do
1318
+ @return.should == @articles.entries.reverse
1319
+ end
1320
+
1321
+ it 'should return a Query that is the reverse of the original' do
1322
+ @return.query.should == @query.reverse
1323
+ end
1324
+ end
1325
+
1326
+ it 'should respond to a belongs_to relationship method with #method_missing' do
1327
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1328
+ @articles.should respond_to(:original)
1329
+ end
1330
+ end
1331
+
1332
+ it 'should respond to a has n relationship method with #method_missing' do
1333
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1334
+ @articles.should respond_to(:revisions)
1335
+ end
1336
+ end
1337
+
1338
+ it 'should respond to a has 1 relationship method with #method_missing' do
1339
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1340
+ @articles.should respond_to(:previous)
1341
+ end
1342
+ end
1343
+
1344
+ describe '#method_missing' do
1345
+ before do
1346
+ pending 'Model#method_missing should delegate to relationships' if @articles.kind_of?(Class)
1347
+ end
1348
+
1349
+ describe 'with a belongs_to relationship method' do
1350
+ before :all do
1351
+ rescue_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1352
+ @articles.create(:content => 'Another Article', :original => @original)
1353
+
1354
+ @return = @collection = @articles.originals
1355
+ end
1356
+ end
1357
+
1358
+ # FIXME: this is spec order dependent, move this into a helper method
1359
+ # and execute in the before :all block
1360
+ unless loaded
1361
+ it 'should not be a kicker' do
1362
+ pending do
1363
+ @articles.should_not be_loaded
1364
+ end
1365
+ end
1366
+ end
1367
+
1368
+ it 'should return a Collection' do
1369
+ @return.should be_kind_of(DataMapper::Collection)
1370
+ end
1371
+
1372
+ it 'should return expected Collection' do
1373
+ @collection.should == [ @original ]
1374
+ end
1375
+
1376
+ it 'should set the association for each Resource' do
1377
+ @articles.map { |resource| resource.original }.should == [ @original, @original ]
1378
+ end
1379
+ end
1380
+
1381
+ describe 'with a has 1 relationship method' do
1382
+ before :all do
1383
+ @new = @articles.new
1384
+
1385
+ @article.previous = @new
1386
+ @new.previous = @other
1387
+
1388
+ @article.save
1389
+ @new.save
1390
+ end
1391
+
1392
+ describe 'with no arguments' do
1393
+ before :all do
1394
+ @return = @articles.previous
1395
+ end
1396
+
1397
+ # FIXME: this is spec order dependent, move this into a helper method
1398
+ # and execute in the before :all block
1399
+ unless loaded
1400
+ it 'should not be a kicker' do
1401
+ pending do
1402
+ @articles.should_not be_loaded
1403
+ end
1404
+ end
1405
+ end
1406
+
1407
+ it 'should return a Collection' do
1408
+ @return.should be_kind_of(DataMapper::Collection)
1409
+ end
1410
+
1411
+ it 'should return expected Collection' do
1412
+ # association is sorted reverse by id
1413
+ @return.should == [ @new, @other ]
1414
+ end
1415
+
1416
+ it 'should set the association for each Resource' do
1417
+ @articles.map { |resource| resource.previous }.should == [ @new, @other ]
1418
+ end
1419
+ end
1420
+
1421
+ describe 'with arguments' do
1422
+ before :all do
1423
+ @return = @articles.previous(:fields => [ :id ])
1424
+ end
1425
+
1426
+ # FIXME: this is spec order dependent, move this into a helper method
1427
+ # and execute in the before :all block
1428
+ unless loaded
1429
+ it 'should not be a kicker' do
1430
+ pending do
1431
+ @articles.should_not be_loaded
1432
+ end
1433
+ end
1434
+ end
1435
+
1436
+ it 'should return a Collection' do
1437
+ @return.should be_kind_of(DataMapper::Collection)
1438
+ end
1439
+
1440
+ it 'should return expected Collection' do
1441
+ # association is sorted reverse by id
1442
+ @return.should == [ @new, @other ]
1443
+ end
1444
+
1445
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1446
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1447
+ @return.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1448
+ end
1449
+ end
1450
+
1451
+ it 'should set the association for each Resource' do
1452
+ @articles.map { |resource| resource.previous }.should == [ @new, @other ]
1453
+ end
1454
+ end
1455
+ end
1456
+
1457
+ describe 'with a has n relationship method' do
1458
+ before :all do
1459
+ @new = @articles.new
1460
+
1461
+ # associate the article with children
1462
+ @article.revisions << @new
1463
+ @new.revisions << @other
1464
+
1465
+ @article.save
1466
+ @new.save
1467
+ end
1468
+
1469
+ describe 'with no arguments' do
1470
+ before :all do
1471
+ @return = @collection = @articles.revisions
1472
+ end
1473
+
1474
+ # FIXME: this is spec order dependent, move this into a helper method
1475
+ # and execute in the before :all block
1476
+ unless loaded
1477
+ it 'should not be a kicker' do
1478
+ pending do
1479
+ @articles.should_not be_loaded
1480
+ end
1481
+ end
1482
+ end
1483
+
1484
+ it 'should return a Collection' do
1485
+ @return.should be_kind_of(DataMapper::Collection)
1486
+ end
1487
+
1488
+ it 'should return expected Collection' do
1489
+ @collection.should == [ @other, @new ]
1490
+ end
1491
+
1492
+ it 'should set the association for each Resource' do
1493
+ @articles.map { |resource| resource.revisions }.should == [ [ @new ], [ @other ] ]
1494
+ end
1495
+ end
1496
+
1497
+ describe 'with arguments' do
1498
+ before :all do
1499
+ @return = @collection = @articles.revisions(:fields => [ :id ])
1500
+ end
1501
+
1502
+ # FIXME: this is spec order dependent, move this into a helper method
1503
+ # and execute in the before :all block
1504
+ unless loaded
1505
+ it 'should not be a kicker' do
1506
+ pending do
1507
+ @articles.should_not be_loaded
1508
+ end
1509
+ end
1510
+ end
1511
+
1512
+ it 'should return a Collection' do
1513
+ @return.should be_kind_of(DataMapper::Collection)
1514
+ end
1515
+
1516
+ it 'should return expected Collection' do
1517
+ @collection.should == [ @other, @new ]
1518
+ end
1519
+
1520
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1521
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1522
+ @collection.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1523
+ end
1524
+ end
1525
+
1526
+ it 'should set the association for each Resource' do
1527
+ @articles.map { |resource| resource.revisions }.should == [ [ @new ], [ @other ] ]
1528
+ end
1529
+ end
1530
+ end
1531
+
1532
+ describe 'with a has n :through relationship method' do
1533
+ before :all do
1534
+ @new = @articles.create
1535
+
1536
+ @publication1 = @article.publications.create(:name => 'Ruby Today')
1537
+ @publication2 = @new.publications.create(:name => 'Inside DataMapper')
1538
+ end
1539
+
1540
+ describe 'with no arguments' do
1541
+ before :all do
1542
+ @return = @collection = @articles.publications
1543
+ end
1544
+
1545
+ # FIXME: this is spec order dependent, move this into a helper method
1546
+ # and execute in the before :all block
1547
+ unless loaded
1548
+ it 'should not be a kicker' do
1549
+ pending do
1550
+ @articles.should_not be_loaded
1551
+ end
1552
+ end
1553
+ end
1554
+
1555
+ it 'should return a Collection' do
1556
+ @return.should be_kind_of(DataMapper::Collection)
1557
+ end
1558
+
1559
+ it 'should return expected Collection' do
1560
+ pending_if 'TODO', @no_join do
1561
+ @collection.should == [ @publication1, @publication2 ]
1562
+ end
1563
+ end
1564
+
1565
+ it 'should set the association for each Resource' do
1566
+ pending_if 'TODO', @no_join do
1567
+ @articles.map { |resource| resource.publications }.should == [ [ @publication1 ], [ @publication2 ] ]
1568
+ end
1569
+ end
1570
+ end
1571
+
1572
+ describe 'with arguments' do
1573
+ before :all do
1574
+ @return = @collection = @articles.publications(:fields => [ :id ])
1575
+ end
1576
+
1577
+ # FIXME: this is spec order dependent, move this into a helper method
1578
+ # and execute in the before :all block
1579
+ unless loaded
1580
+ it 'should not be a kicker' do
1581
+ pending do
1582
+ @articles.should_not be_loaded
1583
+ end
1584
+ end
1585
+ end
1586
+
1587
+ it 'should return a Collection' do
1588
+ @return.should be_kind_of(DataMapper::Collection)
1589
+ end
1590
+
1591
+ it 'should return expected Collection' do
1592
+ pending_if 'TODO', @no_join do
1593
+ @collection.should == [ @publication1, @publication2 ]
1594
+ end
1595
+ end
1596
+
1597
+ { :id => true, :name => false }.each do |attribute, expected|
1598
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1599
+ @collection.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1600
+ end
1601
+ end
1602
+
1603
+ it 'should set the association for each Resource' do
1604
+ pending_if 'TODO', @no_join do
1605
+ @articles.map { |resource| resource.publications }.should == [ [ @publication1 ], [ @publication2 ] ]
1606
+ end
1607
+ end
1608
+ end
1609
+ end
1610
+
1611
+ describe 'with an unknown method' do
1612
+ it 'should raise an exception' do
1613
+ lambda {
1614
+ @articles.unknown
1615
+ }.should raise_error(NoMethodError)
1616
+ end
1617
+ end
1618
+ end
1619
+ end