datamapper-dm-core 0.9.11 → 0.10.0

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 (192) hide show
  1. data/.autotest +17 -14
  2. data/.gitignore +3 -1
  3. data/FAQ +6 -5
  4. data/History.txt +5 -39
  5. data/Manifest.txt +67 -76
  6. data/QUICKLINKS +1 -1
  7. data/README.txt +21 -15
  8. data/Rakefile +16 -15
  9. data/SPECS +2 -29
  10. data/TODO +1 -1
  11. data/dm-core.gemspec +11 -15
  12. data/lib/dm-core/adapters/abstract_adapter.rb +182 -185
  13. data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
  14. data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
  15. data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
  16. data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
  17. data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
  18. data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
  19. data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
  20. data/lib/dm-core/adapters.rb +135 -16
  21. data/lib/dm-core/associations/many_to_many.rb +372 -90
  22. data/lib/dm-core/associations/many_to_one.rb +220 -73
  23. data/lib/dm-core/associations/one_to_many.rb +319 -255
  24. data/lib/dm-core/associations/one_to_one.rb +66 -53
  25. data/lib/dm-core/associations/relationship.rb +560 -158
  26. data/lib/dm-core/collection.rb +1104 -381
  27. data/lib/dm-core/core_ext/kernel.rb +12 -0
  28. data/lib/dm-core/core_ext/symbol.rb +10 -0
  29. data/lib/dm-core/identity_map.rb +4 -34
  30. data/lib/dm-core/migrations.rb +1283 -0
  31. data/lib/dm-core/model/descendant_set.rb +81 -0
  32. data/lib/dm-core/model/hook.rb +45 -0
  33. data/lib/dm-core/model/is.rb +32 -0
  34. data/lib/dm-core/model/property.rb +248 -0
  35. data/lib/dm-core/model/relationship.rb +335 -0
  36. data/lib/dm-core/model/scope.rb +90 -0
  37. data/lib/dm-core/model.rb +570 -369
  38. data/lib/dm-core/property.rb +753 -280
  39. data/lib/dm-core/property_set.rb +141 -98
  40. data/lib/dm-core/query/conditions/comparison.rb +814 -0
  41. data/lib/dm-core/query/conditions/operation.rb +247 -0
  42. data/lib/dm-core/query/direction.rb +43 -0
  43. data/lib/dm-core/query/operator.rb +42 -0
  44. data/lib/dm-core/query/path.rb +102 -0
  45. data/lib/dm-core/query/sort.rb +45 -0
  46. data/lib/dm-core/query.rb +974 -492
  47. data/lib/dm-core/repository.rb +147 -107
  48. data/lib/dm-core/resource.rb +644 -429
  49. data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
  50. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
  51. data/lib/dm-core/support/chainable.rb +20 -0
  52. data/lib/dm-core/support/deprecate.rb +12 -0
  53. data/lib/dm-core/support/equalizer.rb +23 -0
  54. data/lib/dm-core/support/logger.rb +13 -0
  55. data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
  56. data/lib/dm-core/transaction.rb +333 -92
  57. data/lib/dm-core/type.rb +98 -60
  58. data/lib/dm-core/types/boolean.rb +1 -1
  59. data/lib/dm-core/types/discriminator.rb +34 -20
  60. data/lib/dm-core/types/object.rb +7 -4
  61. data/lib/dm-core/types/paranoid_boolean.rb +11 -9
  62. data/lib/dm-core/types/paranoid_datetime.rb +11 -9
  63. data/lib/dm-core/types/serial.rb +3 -3
  64. data/lib/dm-core/types/text.rb +3 -4
  65. data/lib/dm-core/version.rb +1 -1
  66. data/lib/dm-core.rb +106 -110
  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/model/relationship_spec.rb +924 -0
  80. data/spec/public/model_spec.rb +159 -0
  81. data/spec/public/property_spec.rb +829 -0
  82. data/spec/public/resource_spec.rb +71 -0
  83. data/spec/public/sel_spec.rb +44 -0
  84. data/spec/public/setup_spec.rb +145 -0
  85. data/spec/public/shared/association_collection_shared_spec.rb +317 -0
  86. data/spec/public/shared/collection_shared_spec.rb +1723 -0
  87. data/spec/public/shared/finder_shared_spec.rb +1619 -0
  88. data/spec/public/shared/resource_shared_spec.rb +924 -0
  89. data/spec/public/shared/sel_shared_spec.rb +112 -0
  90. data/spec/public/transaction_spec.rb +129 -0
  91. data/spec/public/types/discriminator_spec.rb +130 -0
  92. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  93. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  94. data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
  95. data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
  96. data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
  97. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
  98. data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
  99. data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
  100. data/spec/semipublic/associations/relationship_spec.rb +194 -0
  101. data/spec/semipublic/associations_spec.rb +177 -0
  102. data/spec/semipublic/collection_spec.rb +142 -0
  103. data/spec/semipublic/property_spec.rb +61 -0
  104. data/spec/semipublic/query/conditions_spec.rb +528 -0
  105. data/spec/semipublic/query/path_spec.rb +443 -0
  106. data/spec/semipublic/query_spec.rb +2626 -0
  107. data/spec/semipublic/resource_spec.rb +47 -0
  108. data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
  109. data/spec/spec.opts +3 -1
  110. data/spec/spec_helper.rb +80 -57
  111. data/tasks/ci.rb +19 -31
  112. data/tasks/dm.rb +43 -48
  113. data/tasks/doc.rb +8 -11
  114. data/tasks/gemspec.rb +5 -5
  115. data/tasks/hoe.rb +15 -16
  116. data/tasks/install.rb +8 -10
  117. metadata +72 -93
  118. data/lib/dm-core/associations/relationship_chain.rb +0 -81
  119. data/lib/dm-core/associations.rb +0 -207
  120. data/lib/dm-core/auto_migrations.rb +0 -105
  121. data/lib/dm-core/dependency_queue.rb +0 -32
  122. data/lib/dm-core/hook.rb +0 -11
  123. data/lib/dm-core/is.rb +0 -16
  124. data/lib/dm-core/logger.rb +0 -232
  125. data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
  126. data/lib/dm-core/migrator.rb +0 -29
  127. data/lib/dm-core/scope.rb +0 -58
  128. data/lib/dm-core/support/array.rb +0 -13
  129. data/lib/dm-core/support/assertions.rb +0 -8
  130. data/lib/dm-core/support/errors.rb +0 -23
  131. data/lib/dm-core/support/kernel.rb +0 -11
  132. data/lib/dm-core/support/symbol.rb +0 -41
  133. data/lib/dm-core/support.rb +0 -7
  134. data/lib/dm-core/type_map.rb +0 -80
  135. data/lib/dm-core/types.rb +0 -19
  136. data/script/all +0 -4
  137. data/spec/integration/association_spec.rb +0 -1382
  138. data/spec/integration/association_through_spec.rb +0 -203
  139. data/spec/integration/associations/many_to_many_spec.rb +0 -449
  140. data/spec/integration/associations/many_to_one_spec.rb +0 -163
  141. data/spec/integration/associations/one_to_many_spec.rb +0 -188
  142. data/spec/integration/auto_migrations_spec.rb +0 -413
  143. data/spec/integration/collection_spec.rb +0 -1073
  144. data/spec/integration/data_objects_adapter_spec.rb +0 -32
  145. data/spec/integration/dependency_queue_spec.rb +0 -46
  146. data/spec/integration/model_spec.rb +0 -197
  147. data/spec/integration/mysql_adapter_spec.rb +0 -85
  148. data/spec/integration/postgres_adapter_spec.rb +0 -731
  149. data/spec/integration/property_spec.rb +0 -253
  150. data/spec/integration/query_spec.rb +0 -514
  151. data/spec/integration/repository_spec.rb +0 -61
  152. data/spec/integration/resource_spec.rb +0 -513
  153. data/spec/integration/sqlite3_adapter_spec.rb +0 -352
  154. data/spec/integration/sti_spec.rb +0 -273
  155. data/spec/integration/strategic_eager_loading_spec.rb +0 -156
  156. data/spec/integration/transaction_spec.rb +0 -75
  157. data/spec/integration/type_spec.rb +0 -275
  158. data/spec/lib/logging_helper.rb +0 -18
  159. data/spec/lib/mock_adapter.rb +0 -27
  160. data/spec/lib/model_loader.rb +0 -100
  161. data/spec/lib/publicize_methods.rb +0 -28
  162. data/spec/models/content.rb +0 -16
  163. data/spec/models/vehicles.rb +0 -34
  164. data/spec/models/zoo.rb +0 -48
  165. data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
  166. data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
  167. data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
  168. data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
  169. data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
  170. data/spec/unit/associations/many_to_many_spec.rb +0 -32
  171. data/spec/unit/associations/many_to_one_spec.rb +0 -159
  172. data/spec/unit/associations/one_to_many_spec.rb +0 -393
  173. data/spec/unit/associations/one_to_one_spec.rb +0 -7
  174. data/spec/unit/associations/relationship_spec.rb +0 -71
  175. data/spec/unit/associations_spec.rb +0 -242
  176. data/spec/unit/auto_migrations_spec.rb +0 -111
  177. data/spec/unit/collection_spec.rb +0 -182
  178. data/spec/unit/data_mapper_spec.rb +0 -35
  179. data/spec/unit/identity_map_spec.rb +0 -126
  180. data/spec/unit/is_spec.rb +0 -80
  181. data/spec/unit/migrator_spec.rb +0 -33
  182. data/spec/unit/model_spec.rb +0 -321
  183. data/spec/unit/naming_conventions_spec.rb +0 -36
  184. data/spec/unit/property_set_spec.rb +0 -90
  185. data/spec/unit/property_spec.rb +0 -753
  186. data/spec/unit/query_spec.rb +0 -571
  187. data/spec/unit/repository_spec.rb +0 -93
  188. data/spec/unit/resource_spec.rb +0 -649
  189. data/spec/unit/scope_spec.rb +0 -142
  190. data/spec/unit/transaction_spec.rb +0 -493
  191. data/spec/unit/type_map_spec.rb +0 -114
  192. 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 a 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 a 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 a 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 a 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 a 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 a 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