dm-hibernate-adapter 0.1pre-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/lib/dm-hibernate-adapter.rb +471 -0
  2. data/lib/dm-hibernate-adapter/dialects.rb +37 -0
  3. data/lib/dm-hibernate-adapter/hibernate.rb +403 -0
  4. data/lib/dm-hibernate-adapter/spec/setup.rb +27 -0
  5. data/lib/dm-hibernate-adapter/transaction.rb +27 -0
  6. data/lib/dm-hibernate-adapter_ext.jar +0 -0
  7. data/lib/jibernate.rb +2 -0
  8. data/spec/abstract_adapter/adapter_shared_spec.rb +514 -0
  9. data/spec/abstract_adapter/dm-hibernate-adapter_spec.rb +25 -0
  10. data/spec/abstract_adapter/rcov.opts +6 -0
  11. data/spec/abstract_adapter/spec.opts +4 -0
  12. data/spec/abstract_adapter/spec_helper.rb +8 -0
  13. data/spec/dm_core/adapter_spec.rb +12 -0
  14. data/spec/dm_core/rcov.opts +6 -0
  15. data/spec/dm_core/spec.opts +5 -0
  16. data/spec/dm_core/spec_helper.rb +42 -0
  17. data/spec/log4j.properties +11 -0
  18. data/spec/transient/dm-hibernate-adapter_spec.rb +57 -0
  19. data/spec/transient/lib/adapter_helpers.rb +107 -0
  20. data/spec/transient/lib/collection_helpers.rb +18 -0
  21. data/spec/transient/lib/counter_adapter.rb +38 -0
  22. data/spec/transient/lib/pending_helpers.rb +46 -0
  23. data/spec/transient/lib/rspec_immediate_feedback_formatter.rb +54 -0
  24. data/spec/transient/rcov.opts +6 -0
  25. data/spec/transient/shared/adapter_shared_spec.rb +408 -0
  26. data/spec/transient/shared/finder_shared_spec.rb +1513 -0
  27. data/spec/transient/shared/model_spec.rb +165 -0
  28. data/spec/transient/shared/property_spec.rb +412 -0
  29. data/spec/transient/shared/resource_shared_spec.rb +1226 -0
  30. data/spec/transient/shared/resource_spec.rb +133 -0
  31. data/spec/transient/shared/sel_shared_spec.rb +112 -0
  32. data/spec/transient/spec.opts +4 -0
  33. data/spec/transient/spec_helper.rb +14 -0
  34. metadata +210 -0
@@ -0,0 +1,6 @@
1
+ --exclude "spec"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
@@ -0,0 +1,408 @@
1
+ share_examples_for 'An Adapter' do
2
+
3
+ def self.adapter_supports?(*methods)
4
+ methods.all? do |method|
5
+ # TODO: figure out a way to see if the instance method is only inherited
6
+ # from the Abstract Adapter, and not defined in it's class. If that is
7
+ # the case return false
8
+
9
+ # CRUD methods can be inherited from parent class
10
+ described_type.instance_methods.any? { |instance_method| method.to_s == instance_method.to_s }
11
+ end
12
+ end
13
+
14
+ before(:all) do
15
+
16
+ raise '+@adapter+ should be defined in before block' unless instance_variable_get('@adapter')
17
+
18
+ class ::Heffalump
19
+ include DataMapper::Resource
20
+
21
+ property :id, Serial
22
+ property :color, String
23
+ property :num_spots, Integer
24
+ property :striped, Boolean
25
+
26
+ end
27
+
28
+ # TODO ?
29
+ # if @repository.respond_to?(:auto_migrate!)
30
+ Heffalump.auto_migrate!
31
+ # end
32
+ end
33
+
34
+ if adapter_supports?(:create)
35
+ describe '#create' do
36
+ it 'should not raise any errors' do
37
+ lambda {
38
+ Heffalump.create(:color => 'peach')
39
+ }.should_not raise_error
40
+ end
41
+
42
+ it 'should set the identity field for the resource' do
43
+ heffalump = Heffalump.new(:color => 'peach')
44
+ heffalump.id.should be_nil
45
+ heffalump.save
46
+ heffalump.id.should_not be_nil
47
+ end
48
+ end
49
+ else
50
+ it 'needs to support #create'
51
+ end
52
+
53
+ if adapter_supports?(:read)
54
+
55
+ # <added>
56
+ # XXX this part is added to dm_core's specs
57
+ describe '#read specific object' do
58
+ before :all do
59
+ @heffalump = Heffalump.create(:color => 'brownish hue')
60
+ #just going to borrow this, so I can check the return values
61
+ @query = Heffalump.all.query
62
+ end
63
+
64
+ it 'should not raise any errors' do
65
+ lambda {
66
+ Heffalump.get(@heffalump.id)
67
+ }.should_not raise_error
68
+ end
69
+
70
+ it 'should raise ObjectNotFoundError' do
71
+ lambda {
72
+ id = -600
73
+ Heffalump.get!(id)
74
+ }.should raise_error(DataMapper::ObjectNotFoundError)
75
+ end
76
+
77
+ it 'should return correct result' do
78
+ id = @heffalump.id
79
+ Heffalump.get(id).id.should == id
80
+ end
81
+
82
+ end
83
+ # </added>
84
+
85
+ describe '#read' do
86
+ before :all do
87
+ @heffalump = Heffalump.create(:color => 'brownish hue')
88
+ #just going to borrow this, so I can check the return values
89
+ @query = Heffalump.all.query
90
+ end
91
+
92
+ it 'should not raise any errors' do
93
+ lambda {
94
+ Heffalump.all()
95
+ }.should_not raise_error
96
+ end
97
+
98
+ it 'should return stuff' do
99
+ Heffalump.all.should be_include(@heffalump)
100
+ end
101
+ end
102
+ else
103
+ it 'needs to support #read'
104
+ end
105
+
106
+ if adapter_supports?(:update)
107
+
108
+ # <added>
109
+ # XXX this part is added to dm_core's specs
110
+ describe '#update called directly' do
111
+ before do
112
+ @heffalump = Heffalump.create(:color => 'indigo')
113
+ end
114
+
115
+ it 'should not raise any errors' do
116
+ lambda{
117
+ @heffalump.update(:color => 'violet')
118
+ }.should_not raise_error
119
+ end
120
+
121
+ it 'should not alter the identity field' do
122
+ id = @heffalump.id
123
+ @heffalump.update(:color => 'violet')
124
+ @heffalump.id.should == id
125
+ end
126
+
127
+ it 'should update altered fields' do
128
+ @heffalump.update(:color => 'violet')
129
+ Heffalump.get(*@heffalump.key).color.should == 'violet'
130
+ end
131
+
132
+ it 'should not alter other fields' do
133
+ color = @heffalump.color
134
+ @heffalump.update(:num_spots => 567)
135
+ Heffalump.get(*@heffalump.key).color.should == color
136
+ end
137
+
138
+ end
139
+ # </added>
140
+
141
+ describe '#update' do
142
+ before do
143
+ @heffalump = Heffalump.create(:color => 'indigo')
144
+ end
145
+
146
+ it 'should not raise any errors' do
147
+ lambda {
148
+ @heffalump.color = 'violet'
149
+ @heffalump.save
150
+ }.should_not raise_error
151
+ end
152
+
153
+ it 'should not alter the identity field' do
154
+ id = @heffalump.id
155
+ @heffalump.color = 'violet'
156
+ @heffalump.save
157
+ @heffalump.id.should == id
158
+ end
159
+
160
+ it 'should update altered fields' do
161
+ @heffalump.color = 'violet'
162
+ @heffalump.save
163
+ Heffalump.get(*@heffalump.key).color.should == 'violet'
164
+ end
165
+
166
+ it 'should not alter other fields' do
167
+ color = @heffalump.color
168
+ @heffalump.num_spots = 3
169
+ @heffalump.save
170
+ Heffalump.get(*@heffalump.key).color.should == color
171
+ end
172
+ end
173
+ else
174
+ it 'needs to support #update'
175
+ end
176
+
177
+ if adapter_supports?(:delete)
178
+ describe '#delete' do
179
+ before do
180
+ @heffalump = Heffalump.create(:color => 'forest green')
181
+ end
182
+
183
+ it 'should not raise any errors' do
184
+ lambda {
185
+ @heffalump.destroy
186
+ }.should_not raise_error
187
+ end
188
+
189
+ it 'should delete the requested resource' do
190
+ id = @heffalump.id
191
+ @heffalump.destroy
192
+ Heffalump.get(id).should be_nil
193
+ end
194
+ end
195
+ else
196
+ it 'needs to support #delete'
197
+ end
198
+
199
+ if adapter_supports?(:read, :create)
200
+ describe 'query matching' do
201
+ before :all do
202
+ @red = Heffalump.create(:color => 'red')
203
+ @two = Heffalump.create(:num_spots => 2)
204
+ @five = Heffalump.create(:num_spots => 5)
205
+ end
206
+
207
+ describe 'conditions' do
208
+ describe 'eql' do
209
+ it 'should be able to search for objects included in an inclusive range of values' do
210
+ Heffalump.all(:num_spots => 1..5).should be_include(@five)
211
+ end
212
+
213
+ it 'should be able to search for objects included in an exclusive range of values' do
214
+ Heffalump.all(:num_spots => 1...6).should be_include(@five)
215
+ end
216
+
217
+ it 'should not be able to search for values not included in an inclusive range of values' do
218
+ Heffalump.all(:num_spots => 1..4).should_not be_include(@five)
219
+ end
220
+
221
+ it 'should not be able to search for values not included in an exclusive range of values' do
222
+ Heffalump.all(:num_spots => 1...5).should_not be_include(@five)
223
+ end
224
+ end
225
+
226
+ describe 'not' do
227
+ it 'should be able to search for objects with not equal value' do
228
+ Heffalump.all(:color.not => 'red').should_not be_include(@red)
229
+ end
230
+
231
+ it 'should include objects that are not like the value' do
232
+ Heffalump.all(:color.not => 'black').should be_include(@red)
233
+ end
234
+
235
+ it 'should be able to search for objects with not nil value' do
236
+ Heffalump.all(:color.not => nil).should be_include(@red)
237
+ end
238
+
239
+ it 'should not include objects with a nil value' do
240
+ Heffalump.all(:color.not => nil).should_not be_include(@two)
241
+ end
242
+
243
+ it 'should be able to search for object with a nil value using required properties' do
244
+ Heffalump.all(:id.not => nil).should == [ @red, @two, @five ]
245
+ end
246
+
247
+ # XXX That case generates SICK sql code !
248
+ it 'should be able to search for objects not in an empty list (match all)' do
249
+ Heffalump.all(:color.not => []).should == [ @red, @two, @five ]
250
+ end
251
+
252
+ it 'should be able to search for objects in an empty list and another OR condition (match none on the empty list)' do
253
+ Heffalump.all(:conditions => DataMapper::Query::Conditions::Operation.new(
254
+ :or,
255
+ DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:color], []),
256
+ DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:num_spots], [5]))).should == [ @five ]
257
+ end
258
+
259
+ it 'should be able to search for objects not included in an array of values' do
260
+ Heffalump.all(:num_spots.not => [ 1, 3, 5, 7 ]).should be_include(@two)
261
+ end
262
+
263
+ it 'should be able to search for objects not included in an array of values' do
264
+ Heffalump.all(:num_spots.not => [ 1, 3, 5, 7 ]).should_not be_include(@five)
265
+ end
266
+
267
+ it 'should be able to search for objects not included in an inclusive range of values' do
268
+ Heffalump.all(:num_spots.not => 1..4).should be_include(@five)
269
+ end
270
+
271
+ it 'should be able to search for objects not included in an exclusive range of values' do
272
+ Heffalump.all(:num_spots.not => 1...5).should be_include(@five)
273
+ end
274
+
275
+ it 'should not be able to search for values not included in an inclusive range of values' do
276
+ Heffalump.all(:num_spots.not => 1..5).should_not be_include(@five)
277
+ end
278
+
279
+ it 'should not be able to search for values not included in an exclusive range of values' do
280
+ Heffalump.all(:num_spots.not => 1...6).should_not be_include(@five)
281
+ end
282
+ end
283
+
284
+ describe 'like' do
285
+ it 'should be able to search for objects that match value' do
286
+ Heffalump.all(:color.like => '%ed').should be_include(@red)
287
+ end
288
+
289
+ it 'should not search for objects that do not match the value' do
290
+ Heffalump.all(:color.like => '%blak%').should_not be_include(@red)
291
+ end
292
+ end
293
+
294
+ # <added>
295
+ # XXX this part is added to dm_core's specs
296
+ # XX ie. HSQLDB support "Java" regexps only
297
+ describe 'Java regexp' do
298
+ before do
299
+ if (defined?(DataMapper::Adapters::Sqlite3Adapter) && @adapter.kind_of?(DataMapper::Adapters::Sqlite3Adapter) ||
300
+ defined?(DataMapper::Adapters::SqlserverAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqlserverAdapter))
301
+ pending 'delegate regexp matches to same system that the InMemory and YAML adapters use'
302
+ end
303
+ end
304
+
305
+ it 'should be able to search for objects that match value' do
306
+ Heffalump.all(:color => /.*ed.*/).should be_include(@red)
307
+ end
308
+
309
+ it 'should not be able to search for objects that do not match the value' do
310
+ Heffalump.all(:color => /.*blak.*/).should_not be_include(@red)
311
+ end
312
+
313
+ it 'should be able to do a negated search for objects that match value' do
314
+ Heffalump.all(:color.not => /.*blak.*/).should be_include(@red)
315
+ end
316
+
317
+ it 'should not be able to do a negated search for objects that do not match value' do
318
+ Heffalump.all(:color.not => /.*ed.*/).should_not be_include(@red)
319
+ end
320
+
321
+ end
322
+ # <added>
323
+
324
+ describe 'regexp' do
325
+ before do
326
+ if (defined?(DataMapper::Adapters::Sqlite3Adapter) && @adapter.kind_of?(DataMapper::Adapters::Sqlite3Adapter) ||
327
+ defined?(DataMapper::Adapters::SqlserverAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqlserverAdapter))
328
+ pending 'delegate regexp matches to same system that the InMemory and YAML adapters use'
329
+ end
330
+ end
331
+
332
+ it 'should be able to search for objects that match value' do
333
+ Heffalump.all(:color => /ed/).should be_include(@red)
334
+ end
335
+
336
+ it 'should not be able to search for objects that do not match the value' do
337
+ Heffalump.all(:color => /blak/).should_not be_include(@red)
338
+ end
339
+
340
+ it 'should be able to do a negated search for objects that match value' do
341
+ Heffalump.all(:color.not => /blak/).should be_include(@red)
342
+ end
343
+
344
+ it 'should not be able to do a negated search for objects that do not match value' do
345
+ Heffalump.all(:color.not => /ed/).should_not be_include(@red)
346
+ end
347
+
348
+ end
349
+
350
+ describe 'gt' do
351
+ it 'should be able to search for objects with value greater than' do
352
+ Heffalump.all(:num_spots.gt => 1).should be_include(@two)
353
+ end
354
+
355
+ it 'should not find objects with a value less than' do
356
+ Heffalump.all(:num_spots.gt => 3).should_not be_include(@two)
357
+ end
358
+ end
359
+
360
+ describe 'gte' do
361
+ it 'should be able to search for objects with value greater than' do
362
+ Heffalump.all(:num_spots.gte => 1).should be_include(@two)
363
+ end
364
+
365
+ it 'should be able to search for objects with values equal to' do
366
+ Heffalump.all(:num_spots.gte => 2).should be_include(@two)
367
+ end
368
+
369
+ it 'should not find objects with a value less than' do
370
+ Heffalump.all(:num_spots.gte => 3).should_not be_include(@two)
371
+ end
372
+ end
373
+
374
+ describe 'lt' do
375
+ it 'should be able to search for objects with value less than' do
376
+ Heffalump.all(:num_spots.lt => 3).should be_include(@two)
377
+ end
378
+
379
+ it 'should not find objects with a value less than' do
380
+ Heffalump.all(:num_spots.gt => 2).should_not be_include(@two)
381
+ end
382
+ end
383
+
384
+ describe 'lte' do
385
+ it 'should be able to search for objects with value less than' do
386
+ Heffalump.all(:num_spots.lte => 3).should be_include(@two)
387
+ end
388
+
389
+ it 'should be able to search for objects with values equal to' do
390
+ Heffalump.all(:num_spots.lte => 2).should be_include(@two)
391
+ end
392
+
393
+ it 'should not find objects with a value less than' do
394
+ Heffalump.all(:num_spots.lte => 1).should_not be_include(@two)
395
+ end
396
+ end
397
+ end
398
+
399
+ describe 'limits' do
400
+ it 'should be able to limit the objects' do
401
+ Heffalump.all(:limit => 2).length.should == 2
402
+ end
403
+ end
404
+ end
405
+ else
406
+ it 'needs to support #read and #create to test query matching'
407
+ end
408
+ end
@@ -0,0 +1,1513 @@
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
+ @do_adapter = defined?(DataMapper::Adapters::DataObjectsAdapter) && @adapter.kind_of?(DataMapper::Adapters::DataObjectsAdapter)
14
+
15
+ @many_to_many = @articles.kind_of?(DataMapper::Associations::ManyToMany::Collection)
16
+
17
+ @skip = @no_join && @many_to_many
18
+ end
19
+
20
+ before do
21
+ pending if @skip
22
+ end
23
+
24
+ [ :[], :slice ].each do |method|
25
+ it { @articles.should respond_to(method) }
26
+
27
+ describe "##{method}" do
28
+ before :all do
29
+ 1.upto(10) { |number| @articles.create(:content => "Article #{number}") }
30
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
31
+ end
32
+
33
+ describe 'with a positive offset' do
34
+ before :all do
35
+ unless @skip
36
+ @return = @resource = @articles.send(method, 0)
37
+ end
38
+ end
39
+
40
+ it 'should return a Resource' do
41
+ @return.should be_kind_of(DataMapper::Resource)
42
+ end
43
+
44
+ it 'should return expected Resource' do
45
+ @return.should == @copy.entries.send(method, 0)
46
+ end
47
+ end
48
+
49
+ describe 'with a positive offset and length' do
50
+ before :all do
51
+ @return = @resources = @articles.send(method, 5, 5)
52
+ end
53
+
54
+ it 'should return a Collection' do
55
+ @return.should be_kind_of(DataMapper::Collection)
56
+ end
57
+
58
+ it 'should return the expected Resource' do
59
+ @return.should == @copy.entries.send(method, 5, 5)
60
+ end
61
+
62
+ it 'should scope the Collection' do
63
+ @resources.reload.should == @copy.entries.send(method, 5, 5)
64
+ end
65
+ end
66
+
67
+ describe 'with a positive range' do
68
+ before :all do
69
+ @return = @resources = @articles.send(method, 5..10)
70
+ end
71
+
72
+ it 'should return a Collection' do
73
+ @return.should be_kind_of(DataMapper::Collection)
74
+ end
75
+
76
+ it 'should return the expected Resources' do
77
+ @return.should == @copy.entries.send(method, 5..10)
78
+ end
79
+
80
+ it 'should scope the Collection' do
81
+ @resources.reload.should == @copy.entries.send(method, 5..10)
82
+ end
83
+ end
84
+
85
+ describe 'with a negative offset' do
86
+ before :all do
87
+ unless @skip
88
+ @return = @resource = @articles.send(method, -1)
89
+ end
90
+ end
91
+
92
+ it 'should return a Resource' do
93
+ @return.should be_kind_of(DataMapper::Resource)
94
+ end
95
+
96
+ it 'should return expected Resource' do
97
+ @return.should == @copy.entries.send(method, -1)
98
+ end
99
+ end
100
+
101
+ describe 'with a negative offset and length' do
102
+ before :all do
103
+ @return = @resources = @articles.send(method, -5, 5)
104
+ end
105
+
106
+ it 'should return a Collection' do
107
+ @return.should be_kind_of(DataMapper::Collection)
108
+ end
109
+
110
+ it 'should return the expected Resources' do
111
+ @return.should == @copy.entries.send(method, -5, 5)
112
+ end
113
+
114
+ it 'should scope the Collection' do
115
+ @resources.reload.should == @copy.entries.send(method, -5, 5)
116
+ end
117
+ end
118
+
119
+ describe 'with a negative range' do
120
+ before :all do
121
+ @return = @resources = @articles.send(method, -5..-2)
122
+ end
123
+
124
+ it 'should return a Collection' do
125
+ @return.should be_kind_of(DataMapper::Collection)
126
+ end
127
+
128
+ it 'should return the expected Resources' do
129
+ @return.to_a.should == @copy.entries.send(method, -5..-2)
130
+ end
131
+
132
+ it 'should scope the Collection' do
133
+ @resources.reload.should == @copy.entries.send(method, -5..-2)
134
+ end
135
+ end
136
+
137
+ describe 'with an empty exclusive range' do
138
+ before :all do
139
+ @return = @resources = @articles.send(method, 0...0)
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 value' do
147
+ @return.to_a.should == @copy.entries.send(method, 0...0)
148
+ end
149
+
150
+ it 'should be empty' do
151
+ @return.should be_empty
152
+ end
153
+ end
154
+
155
+ describe 'with an offset not within the Collection' do
156
+ before :all do
157
+ unless @skip
158
+ @return = @articles.send(method, 99)
159
+ end
160
+ end
161
+
162
+ it 'should return nil' do
163
+ @return.should be_nil
164
+ end
165
+ end
166
+
167
+ describe 'with an offset and length not within the Collection' do
168
+ before :all do
169
+ @return = @articles.send(method, 99, 1)
170
+ end
171
+
172
+ it 'should return a Collection' do
173
+ @return.should be_kind_of(DataMapper::Collection)
174
+ end
175
+
176
+ it 'should be empty' do
177
+ @return.should be_empty
178
+ end
179
+ end
180
+
181
+ describe 'with a range not within the Collection' do
182
+ before :all do
183
+ @return = @articles.send(method, 99..100)
184
+ end
185
+
186
+ it 'should return a Collection' do
187
+ @return.should be_kind_of(DataMapper::Collection)
188
+ end
189
+
190
+ it 'should be empty' do
191
+ @return.should be_empty
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ it { @articles.should respond_to(:all) }
198
+
199
+ describe '#all' do
200
+ describe 'with no arguments' do
201
+ before :all do
202
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
203
+
204
+ @return = @collection = @articles.all
205
+ end
206
+
207
+ it 'should return a Collection' do
208
+ @return.should be_kind_of(DataMapper::Collection)
209
+ end
210
+
211
+ it 'should return a new instance' do
212
+ @return.should_not equal(@articles)
213
+ end
214
+
215
+ it 'should be expected Resources' do
216
+ @collection.should == @articles.entries
217
+ end
218
+
219
+ it 'should not have a Query the same as the original' do
220
+ @return.query.should_not equal(@articles.query)
221
+ end
222
+
223
+ it 'should have a Query equal to the original' do
224
+ @return.query.should eql(@articles.query)
225
+ end
226
+
227
+ it 'should scope the Collection' do
228
+ @collection.reload.should == @copy.entries
229
+ end
230
+ end
231
+
232
+ describe 'with a query' do
233
+ before :all do
234
+ @new = @articles.create(:content => 'New Article')
235
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
236
+
237
+ @return = @articles.all(:content => [ 'New Article' ])
238
+ end
239
+
240
+ it 'should return a Collection' do
241
+ @return.should be_kind_of(DataMapper::Collection)
242
+ end
243
+
244
+ it 'should return a new instance' do
245
+ @return.should_not equal(@articles)
246
+ end
247
+
248
+ it 'should be expected Resources' do
249
+ @return.should == [ @new ]
250
+ end
251
+
252
+ it 'should have a different query than original Collection' do
253
+ @return.query.should_not equal(@articles.query)
254
+ end
255
+
256
+ it 'should scope the Collection' do
257
+ @return.reload.should == @copy.entries.select { |resource| resource.content == 'New Article' }
258
+ end
259
+ end
260
+
261
+ describe 'with a query using raw conditions' do
262
+ before do
263
+ pending unless defined?(DataMapper::Adapters::DataObjectsAdapter) && @adapter.kind_of?(DataMapper::Adapters::DataObjectsAdapter)
264
+ end
265
+
266
+ before :all do
267
+ @new = @articles.create(:subtitle => 'New Article')
268
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
269
+
270
+ @return = @articles.all(:conditions => [ 'subtitle = ?', 'New Article' ])
271
+ end
272
+
273
+ it 'should return a Collection' do
274
+ @return.should be_kind_of(DataMapper::Collection)
275
+ end
276
+
277
+ it 'should return a new instance' do
278
+ @return.should_not equal(@articles)
279
+ end
280
+
281
+ it 'should be expected Resources' do
282
+ @return.should == [ @new ]
283
+ end
284
+
285
+ it 'should have a different query than original Collection' do
286
+ @return.query.should_not == @articles.query
287
+ end
288
+
289
+ it 'should scope the Collection' do
290
+ @return.reload.should == @copy.entries.select { |resource| resource.subtitle == 'New Article' }.first(1)
291
+ end
292
+ end
293
+
294
+ describe 'with a query that is out of range' do
295
+ it 'should raise an exception' do
296
+ lambda {
297
+ @articles.all(:limit => 10).all(:offset => 10)
298
+ }.should raise_error(RangeError, 'offset 10 and limit 0 are outside allowed range')
299
+ end
300
+ end
301
+
302
+ describe 'with a query using a m:1 relationship' do
303
+ describe 'with a Hash' do
304
+ before :all do
305
+ @return = @articles.all(:original => @original.attributes)
306
+ end
307
+
308
+ it 'should return a Collection' do
309
+ @return.should be_kind_of(DataMapper::Collection)
310
+ end
311
+
312
+ it 'should be expected Resources' do
313
+ @return.should == [ @article ]
314
+ end
315
+
316
+ it 'should have a valid query' do
317
+ @return.query.should be_valid
318
+ end
319
+ end
320
+
321
+ describe 'with a resource' do
322
+ before :all do
323
+ @return = @articles.all(:original => @original)
324
+ end
325
+
326
+ it 'should return a Collection' do
327
+ @return.should be_kind_of(DataMapper::Collection)
328
+ end
329
+
330
+ it 'should be expected Resources' do
331
+ @return.should == [ @article ]
332
+ end
333
+
334
+ it 'should have a valid query' do
335
+ @return.query.should be_valid
336
+ end
337
+ end
338
+
339
+ describe 'with a collection' do
340
+ before :all do
341
+ @collection = @article_model.all(@article_model.key.zip(@original.key).to_hash)
342
+
343
+ @return = @articles.all(:original => @collection)
344
+ end
345
+
346
+ it 'should return a Collection' do
347
+ @return.should be_kind_of(DataMapper::Collection)
348
+ end
349
+
350
+ it 'should be expected Resources' do
351
+ @return.should == [ @article ]
352
+ end
353
+
354
+ it 'should have a valid query' do
355
+ @return.query.should be_valid
356
+ end
357
+
358
+ end
359
+
360
+ describe 'with an empty Array' do
361
+ before :all do
362
+ @return = @articles.all(:original => [])
363
+ end
364
+
365
+ it 'should return a Collection' do
366
+ @return.should be_kind_of(DataMapper::Collection)
367
+ end
368
+
369
+ it 'should be an empty Collection' do
370
+ @return.should be_empty
371
+ end
372
+
373
+ it 'should not have a valid query' do
374
+ @return.query.should_not be_valid
375
+ end
376
+ end
377
+
378
+ describe 'with a nil value' do
379
+ before :all do
380
+ @return = @articles.all(:original => nil)
381
+ end
382
+
383
+ it 'should return a Collection' do
384
+ @return.should be_kind_of(DataMapper::Collection)
385
+ end
386
+
387
+ if respond_to?(:model?) && model?
388
+ it 'should be expected Resources' do
389
+ @return.should == [ @original, @other ]
390
+ end
391
+ else
392
+ it 'should be an empty Collection' do
393
+ @return.should be_empty
394
+ end
395
+ end
396
+
397
+ it 'should have a valid query' do
398
+ @return.query.should be_valid
399
+ end
400
+
401
+ it 'should be equivalent to negated collection query' do
402
+ pending_if 'Update RDBMS to match ruby behavior', @do_adapter && @articles.kind_of?(DataMapper::Model) do
403
+ # NOTE: the second query will not match any articles where original_id
404
+ # is nil, while the in-memory/yaml adapters will. RDBMS will explicitly
405
+ # filter out NULL matches because we are matching on a non-NULL value,
406
+ # which is not consistent with how DM/Ruby matching behaves.
407
+ @return.should == @articles.all(:original.not => @article_model.all)
408
+ end
409
+ end
410
+ end
411
+
412
+ describe 'with a negated nil value' do
413
+ before :all do
414
+ @return = @articles.all(:original.not => nil)
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
+
429
+ it 'should be equivalent to collection query' do
430
+ @return.should == @articles.all(:original => @article_model.all)
431
+ end
432
+ end
433
+ end
434
+
435
+ describe 'with a query using a 1:1 relationship' do
436
+ before :all do
437
+ @new = @articles.create(:content => 'New Article', :original => @article)
438
+ end
439
+
440
+ describe 'with a Hash' do
441
+ before :all do
442
+ @return = @articles.all(:previous => @new.attributes)
443
+ end
444
+
445
+ it 'should return a Collection' do
446
+ @return.should be_kind_of(DataMapper::Collection)
447
+ end
448
+
449
+ it 'should be expected Resources' do
450
+ @return.should == [ @article ]
451
+ end
452
+
453
+ it 'should have a valid query' do
454
+ @return.query.should be_valid
455
+ end
456
+ end
457
+
458
+ describe 'with a resource' do
459
+ before :all do
460
+ @return = @articles.all(:previous => @new)
461
+ end
462
+
463
+ it 'should return a Collection' do
464
+ @return.should be_kind_of(DataMapper::Collection)
465
+ end
466
+
467
+ it 'should be expected Resources' do
468
+ @return.should == [ @article ]
469
+ end
470
+
471
+ it 'should have a valid query' do
472
+ @return.query.should be_valid
473
+ end
474
+ end
475
+
476
+ describe 'with a collection' do
477
+ before :all do
478
+ @collection = @article_model.all(@article_model.key.zip(@new.key).to_hash)
479
+
480
+ @return = @articles.all(:previous => @collection)
481
+ end
482
+
483
+ it 'should return a Collection' do
484
+ @return.should be_kind_of(DataMapper::Collection)
485
+ end
486
+
487
+ it 'should be expected Resources' do
488
+ @return.should == [ @article ]
489
+ end
490
+
491
+ it 'should have a valid query' do
492
+ @return.query.should be_valid
493
+ end
494
+ end
495
+
496
+ describe 'with an empty Array' do
497
+ before :all do
498
+ @return = @articles.all(:previous => [])
499
+ end
500
+
501
+ it 'should return a Collection' do
502
+ @return.should be_kind_of(DataMapper::Collection)
503
+ end
504
+
505
+ it 'should be an empty Collection' do
506
+ @return.should be_empty
507
+ end
508
+
509
+ it 'should not have a valid query' do
510
+ @return.query.should_not be_valid
511
+ end
512
+ end
513
+
514
+ describe 'with a nil value' do
515
+ before :all do
516
+ @return = @articles.all(:previous => nil)
517
+ end
518
+
519
+ it 'should return a Collection' do
520
+ @return.should be_kind_of(DataMapper::Collection)
521
+ end
522
+
523
+ if respond_to?(:model?) && model?
524
+ it 'should be expected Resources' do
525
+ @return.should == [ @other, @new ]
526
+ end
527
+ else
528
+ it 'should be expected Resources' do
529
+ @return.should == [ @new ]
530
+ end
531
+ end
532
+
533
+ it 'should have a valid query' do
534
+ @return.query.should be_valid
535
+ end
536
+
537
+ it 'should be equivalent to negated collection query' do
538
+ @return.should == @articles.all(:previous.not => @article_model.all(:original.not => nil))
539
+ end
540
+ end
541
+
542
+ describe 'with a negated nil value' do
543
+ before :all do
544
+ @return = @articles.all(:previous.not => nil)
545
+ end
546
+
547
+ it 'should return a Collection' do
548
+ @return.should be_kind_of(DataMapper::Collection)
549
+ end
550
+
551
+ if respond_to?(:model?) && model?
552
+ it 'should be expected Resources' do
553
+ @return.should == [ @original, @article ]
554
+ end
555
+ else
556
+ it 'should be expected Resources' do
557
+ @return.should == [ @article ]
558
+ end
559
+ end
560
+
561
+ it 'should have a valid query' do
562
+ @return.query.should be_valid
563
+ end
564
+
565
+ it 'should be equivalent to collection query' do
566
+ @return.should == @articles.all(:previous => @article_model.all)
567
+ end
568
+ end
569
+ end
570
+
571
+ describe 'with a query using a 1:m relationship' do
572
+ before :all do
573
+ @new = @articles.create(:content => 'New Article', :original => @article)
574
+ end
575
+
576
+ describe 'with a Hash' do
577
+ before :all do
578
+ @return = @articles.all(:revisions => @new.attributes)
579
+ end
580
+
581
+ it 'should return a Collection' do
582
+ @return.should be_kind_of(DataMapper::Collection)
583
+ end
584
+
585
+ it 'should be expected Resources' do
586
+ @return.should == [ @article ]
587
+ end
588
+
589
+ it 'should have a valid query' do
590
+ @return.query.should be_valid
591
+ end
592
+ end
593
+
594
+ describe 'with a resource' do
595
+ before :all do
596
+ @return = @articles.all(:revisions => @new)
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
+ @return.should == [ @article ]
605
+ end
606
+
607
+ it 'should have a valid query' do
608
+ @return.query.should be_valid
609
+ end
610
+ end
611
+
612
+ describe 'with a collection' do
613
+ before :all do
614
+ @collection = @article_model.all(@article_model.key.zip(@new.key).to_hash)
615
+
616
+ @return = @articles.all(:revisions => @collection)
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 expected Resources' do
624
+ @return.should == [ @article ]
625
+ end
626
+
627
+ it 'should have a valid query' do
628
+ @return.query.should be_valid
629
+ end
630
+ end
631
+
632
+ describe 'with an empty Array' do
633
+ before :all do
634
+ @return = @articles.all(:revisions => [])
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 not have a valid query' do
646
+ @return.query.should_not be_valid
647
+ end
648
+ end
649
+
650
+ describe 'with a nil value' do
651
+ before :all do
652
+ @return = @articles.all(:revisions => nil)
653
+ end
654
+
655
+ it 'should return a Collection' do
656
+ @return.should be_kind_of(DataMapper::Collection)
657
+ end
658
+
659
+ if respond_to?(:model?) && model?
660
+ it 'should be expected Resources' do
661
+ @return.should == [ @other, @new ]
662
+ end
663
+ else
664
+ it 'should be expected Resources' do
665
+ @return.should == [ @new ]
666
+ end
667
+ end
668
+
669
+ it 'should have a valid query' do
670
+ @return.query.should be_valid
671
+ end
672
+
673
+ it 'should be equivalent to negated collection query' do
674
+ @return.should == @articles.all(:revisions.not => @article_model.all(:original.not => nil))
675
+ end
676
+ end
677
+
678
+ describe 'with a negated nil value' do
679
+ before :all do
680
+ @return = @articles.all(:revisions.not => nil)
681
+ end
682
+
683
+ it 'should return a Collection' do
684
+ @return.should be_kind_of(DataMapper::Collection)
685
+ end
686
+
687
+ if respond_to?(:model?) && model?
688
+ it 'should be expected Resources' do
689
+ @return.should == [ @original, @article ]
690
+ end
691
+ else
692
+ it 'should be expected Resources' do
693
+ @return.should == [ @article ]
694
+ end
695
+ end
696
+
697
+ it 'should have a valid query' do
698
+ @return.query.should be_valid
699
+ end
700
+
701
+ it 'should be equivalent to collection query' do
702
+ @return.should == @articles.all(:revisions => @article_model.all)
703
+ end
704
+ end
705
+ end
706
+
707
+ describe 'with a query using a m:m relationship' do
708
+ before :all do
709
+ @publication = @article.publications.create(:name => 'DataMapper Now')
710
+ end
711
+
712
+ describe 'with a Hash' do
713
+ before :all do
714
+ @return = @articles.all(:publications => @publication.attributes)
715
+ end
716
+
717
+ it 'should return a Collection' do
718
+ @return.should be_kind_of(DataMapper::Collection)
719
+ end
720
+
721
+ it 'should be expected Resources' do
722
+ pending 'TODO' do
723
+ @return.should == [ @article ]
724
+ end
725
+ end
726
+
727
+ it 'should have a valid query' do
728
+ @return.query.should be_valid
729
+ end
730
+ end
731
+
732
+ describe 'with a resource' do
733
+ before :all do
734
+ @return = @articles.all(:publications => @publication)
735
+ end
736
+
737
+ it 'should return a Collection' do
738
+ @return.should be_kind_of(DataMapper::Collection)
739
+ end
740
+
741
+ it 'should be expected Resources' do
742
+ pending 'TODO' do
743
+ @return.should == [ @article ]
744
+ end
745
+ end
746
+
747
+ it 'should have a valid query' do
748
+ @return.query.should be_valid
749
+ end
750
+ end
751
+
752
+ describe 'with a collection' do
753
+ before :all do
754
+ @collection = @publication_model.all(@publication_model.key.zip(@publication.key).to_hash)
755
+
756
+ @return = @articles.all(:publications => @collection)
757
+ end
758
+
759
+ it 'should return a Collection' do
760
+ @return.should be_kind_of(DataMapper::Collection)
761
+ end
762
+
763
+ it 'should be expected Resources' do
764
+ pending 'TODO' do
765
+ @return.should == [ @article ]
766
+ end
767
+ end
768
+
769
+ it 'should have a valid query' do
770
+ @return.query.should be_valid
771
+ end
772
+ end
773
+
774
+ describe 'with an empty Array' do
775
+ before :all do
776
+ @return = @articles.all(:publications => [])
777
+ end
778
+
779
+ it 'should return a Collection' do
780
+ @return.should be_kind_of(DataMapper::Collection)
781
+ end
782
+
783
+ it 'should be an empty Collection' do
784
+ @return.should be_empty
785
+ end
786
+
787
+ it 'should not have a valid query' do
788
+ @return.query.should_not be_valid
789
+ end
790
+ end
791
+
792
+ describe 'with a nil value' do
793
+ before :all do
794
+ @return = @articles.all(:publications => nil)
795
+ end
796
+
797
+ it 'should return a Collection' do
798
+ @return.should be_kind_of(DataMapper::Collection)
799
+ end
800
+
801
+ it 'should be empty' do
802
+ pending 'TODO' do
803
+ @return.should be_empty
804
+ end
805
+ end
806
+
807
+ it 'should have a valid query' do
808
+ @return.query.should be_valid
809
+ end
810
+
811
+ it 'should be equivalent to negated collection query' do
812
+ @return.should == @articles.all(:publications.not => @publication_model.all)
813
+ end
814
+ end
815
+
816
+ describe 'with a negated nil value' do
817
+ before :all do
818
+ @return = @articles.all(:publications.not => nil)
819
+ end
820
+
821
+ it 'should return a Collection' do
822
+ @return.should be_kind_of(DataMapper::Collection)
823
+ end
824
+
825
+ it 'should be expected Resources' do
826
+ pending 'TODO' do
827
+ @return.should == [ @article ]
828
+ end
829
+ end
830
+
831
+ it 'should have a valid query' do
832
+ @return.query.should be_valid
833
+ end
834
+
835
+ it 'should be equivalent to collection query' do
836
+ @return.should == @articles.all(:publications => @publication_model.all)
837
+ end
838
+ end
839
+ end
840
+ end
841
+
842
+ it { @articles.should respond_to(:at) }
843
+
844
+ describe '#at' do
845
+ before :all do
846
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
847
+ @copy.to_a
848
+ end
849
+
850
+ describe 'with positive offset' do
851
+ before :all do
852
+ @return = @resource = @articles.at(0)
853
+ end
854
+
855
+ should_not_be_a_kicker
856
+
857
+ it 'should return a Resource' do
858
+ @return.should be_kind_of(DataMapper::Resource)
859
+ end
860
+
861
+ it 'should return expected Resource' do
862
+ @resource.should == @copy.entries.at(0)
863
+ end
864
+ end
865
+
866
+ describe 'with negative offset' do
867
+ before :all do
868
+ @return = @resource = @articles.at(-1)
869
+ end
870
+
871
+ should_not_be_a_kicker
872
+
873
+ it 'should return a Resource' do
874
+ @return.should be_kind_of(DataMapper::Resource)
875
+ end
876
+
877
+ it 'should return expected Resource' do
878
+ @resource.should == @copy.entries.at(-1)
879
+ end
880
+ end
881
+ end
882
+
883
+ it { @articles.should respond_to(:first) }
884
+
885
+ describe '#first' do
886
+ before :all do
887
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
888
+
889
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
890
+ @copy.to_a
891
+ end
892
+
893
+ describe 'with no arguments' do
894
+ before :all do
895
+ @return = @resource = @articles.first
896
+ end
897
+
898
+ it 'should return a Resource' do
899
+ @return.should be_kind_of(DataMapper::Resource)
900
+ end
901
+
902
+ it 'should be first Resource in the Collection' do
903
+ @resource.should == @copy.entries.first
904
+ end
905
+ end
906
+
907
+ describe 'with empty query' do
908
+ before :all do
909
+ @return = @resource = @articles.first({})
910
+ end
911
+
912
+ it 'should return a Resource' do
913
+ @return.should be_kind_of(DataMapper::Resource)
914
+ end
915
+
916
+ it 'should be first Resource in the Collection' do
917
+ @resource.should == @copy.entries.first
918
+ end
919
+ end
920
+
921
+ describe 'with a query' do
922
+ before :all do
923
+ @return = @resource = @articles.first(:content => 'Sample')
924
+ end
925
+
926
+ it 'should return a Resource' do
927
+ @return.should be_kind_of(DataMapper::Resource)
928
+ end
929
+
930
+ it 'should should be the first Resource in the Collection matching the query' do
931
+ @resource.should == @article
932
+ end
933
+ end
934
+
935
+ describe 'with a limit specified' do
936
+ before :all do
937
+ @return = @resources = @articles.first(1)
938
+ end
939
+
940
+ it 'should return a Collection' do
941
+ @return.should be_kind_of(DataMapper::Collection)
942
+ end
943
+
944
+ it 'should be the first N Resources in the Collection' do
945
+ @resources.should == @copy.entries.first(1)
946
+ end
947
+ end
948
+
949
+ describe 'on an empty collection' do
950
+ before :all do
951
+ @articles = @articles.all(:id => nil)
952
+ @return = @articles.first
953
+ end
954
+
955
+ it 'should still be an empty collection' do
956
+ @articles.should be_empty
957
+ end
958
+
959
+ it 'should return nil' do
960
+ @return.should be_nil
961
+ end
962
+ end
963
+
964
+ describe 'with offset specified' do
965
+ before :all do
966
+ @return = @resource = @articles.first(:offset => 1)
967
+ end
968
+
969
+ it 'should return a Resource' do
970
+ @return.should be_kind_of(DataMapper::Resource)
971
+ end
972
+
973
+ it 'should be the second Resource in the Collection' do
974
+ @resource.should == @copy.entries[1]
975
+ end
976
+ end
977
+
978
+ describe 'with a limit and query specified' do
979
+ before :all do
980
+ @return = @resources = @articles.first(1, :content => 'Sample')
981
+ end
982
+
983
+ it 'should return a Collection' do
984
+ @return.should be_kind_of(DataMapper::Collection)
985
+ end
986
+
987
+ it 'should be the first N Resources in the Collection matching the query' do
988
+ @resources.should == [ @article ]
989
+ end
990
+ end
991
+ end
992
+
993
+ it { @articles.should respond_to(:first_or_create) }
994
+
995
+ describe '#first_or_create' do
996
+ describe 'with conditions that find an existing Resource' do
997
+ before :all do
998
+ @return = @resource = @articles.first_or_create(@article.attributes)
999
+ end
1000
+
1001
+ it 'should return a Resource' do
1002
+ @return.should be_kind_of(DataMapper::Resource)
1003
+ end
1004
+
1005
+ it 'should be expected Resource' do
1006
+ @resource.should == @article
1007
+ end
1008
+
1009
+ it 'should be a saved Resource' do
1010
+ @resource.should be_saved
1011
+ end
1012
+ end
1013
+
1014
+ describe 'with conditions that do not find an existing Resource' do
1015
+ before :all do
1016
+ @conditions = { :content => 'Unknown Content' }
1017
+ @attributes = {}
1018
+
1019
+ @return = @resource = @articles.first_or_create(@conditions, @attributes)
1020
+ end
1021
+
1022
+ it 'should return a Resource' do
1023
+ @return.should be_kind_of(DataMapper::Resource)
1024
+ end
1025
+
1026
+ it 'should be expected Resource' do
1027
+ @resource.attributes.only(*@conditions.keys).should == @conditions
1028
+ end
1029
+
1030
+ it 'should be a saved Resource' do
1031
+ @resource.should be_saved
1032
+ end
1033
+ end
1034
+ end
1035
+
1036
+ it { @articles.should respond_to(:first_or_new) }
1037
+
1038
+ describe '#first_or_new' do
1039
+ describe 'with conditions that find an existing Resource' do
1040
+ before :all do
1041
+ @return = @resource = @articles.first_or_new(@article.attributes)
1042
+ end
1043
+
1044
+ it 'should return a Resource' do
1045
+ @return.should be_kind_of(DataMapper::Resource)
1046
+ end
1047
+
1048
+ it 'should be expected Resource' do
1049
+ @resource.should == @article
1050
+ end
1051
+
1052
+ it 'should be a saved Resource' do
1053
+ @resource.should be_saved
1054
+ end
1055
+ end
1056
+
1057
+ describe 'with conditions that do not find an existing Resource' do
1058
+ before :all do
1059
+ @conditions = { :content => 'Unknown Content' }
1060
+ @attributes = {}
1061
+
1062
+ @return = @resource = @articles.first_or_new(@conditions, @attributes)
1063
+ end
1064
+
1065
+ it 'should return a Resource' do
1066
+ @return.should be_kind_of(DataMapper::Resource)
1067
+ end
1068
+
1069
+ it 'should be expected Resource' do
1070
+ @resource.attributes.only(*@conditions.keys).should == @conditions
1071
+ end
1072
+
1073
+ it 'should not be a saved Resource' do
1074
+ @resource.should be_new
1075
+ end
1076
+ end
1077
+ end
1078
+
1079
+ [ :get, :get! ].each do |method|
1080
+ it { @articles.should respond_to(method) }
1081
+
1082
+ describe "##{method}" do
1083
+ describe 'with a key to a Resource within the Collection' do
1084
+ before :all do
1085
+ unless @skip
1086
+ @return = @resource = @articles.send(method, *@article.key)
1087
+ end
1088
+ end
1089
+
1090
+ it 'should return a Resource' do
1091
+ @return.should be_kind_of(DataMapper::Resource)
1092
+ end
1093
+
1094
+ it 'should be matching Resource in the Collection' do
1095
+ @resource.should == @article
1096
+ end
1097
+ end
1098
+
1099
+ describe 'with a key not typecast' do
1100
+ before :all do
1101
+ unless @skip
1102
+ @return = @resource = @articles.send(method, *@article.key.map { |value| value.to_s })
1103
+ end
1104
+ end
1105
+
1106
+ it 'should return a Resource' do
1107
+ @return.should be_kind_of(DataMapper::Resource)
1108
+ end
1109
+
1110
+ it 'should be matching Resource in the Collection' do
1111
+ @resource.should == @article
1112
+ end
1113
+ end
1114
+
1115
+ describe 'with a key to a Resource not within the Collection' do
1116
+ if method == :get
1117
+ it 'should return nil' do
1118
+ @articles.get(99).should be_nil
1119
+ end
1120
+ else
1121
+ it 'should raise an exception' do
1122
+ lambda {
1123
+ @articles.get!(99)
1124
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key \[99\]")
1125
+ end
1126
+ end
1127
+ end
1128
+
1129
+ describe 'with a key that is nil' do
1130
+ if method == :get
1131
+ it 'should return nil' do
1132
+ @articles.get(nil).should be_nil
1133
+ end
1134
+ else
1135
+ it 'should raise an exception' do
1136
+ lambda {
1137
+ @articles.get!(nil)
1138
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [nil]")
1139
+ end
1140
+ end
1141
+ end
1142
+
1143
+ describe 'with a key that is an empty String' do
1144
+ if method == :get
1145
+ it 'should return nil' do
1146
+ @articles.get('').should be_nil
1147
+ end
1148
+ else
1149
+ it 'should raise an exception' do
1150
+ lambda {
1151
+ @articles.get!('')
1152
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [\"\"]")
1153
+ end
1154
+ end
1155
+ end
1156
+
1157
+ describe 'with a key that has incorrect number of arguments' do
1158
+ subject { @articles.send(method) }
1159
+
1160
+ it 'should raise an exception' do
1161
+ method(:subject).should raise_error(ArgumentError, 'The number of arguments for the key is invalid, expected 1 but was 0')
1162
+ end
1163
+ end
1164
+ end
1165
+ end
1166
+
1167
+ it { @articles.should respond_to(:last) }
1168
+
1169
+ describe '#last' do
1170
+ before :all do
1171
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
1172
+
1173
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
1174
+ @copy.to_a
1175
+ end
1176
+
1177
+ describe 'with no arguments' do
1178
+ before :all do
1179
+ @return = @resource = @articles.last
1180
+ end
1181
+
1182
+ it 'should return a Resource' do
1183
+ @return.should be_kind_of(DataMapper::Resource)
1184
+ end
1185
+
1186
+ it 'should be last Resource in the Collection' do
1187
+ @resource.should == @copy.entries.last
1188
+ end
1189
+ end
1190
+
1191
+ describe 'with a query' do
1192
+ before :all do
1193
+ @return = @resource = @articles.last(:content => 'Sample')
1194
+ end
1195
+
1196
+ it 'should return a Resource' do
1197
+ @return.should be_kind_of(DataMapper::Resource)
1198
+ end
1199
+
1200
+ it 'should should be the last Resource in the Collection matching the query' do
1201
+ @resource.should == @article
1202
+ end
1203
+ end
1204
+
1205
+ describe 'with a limit specified' do
1206
+ before :all do
1207
+ @return = @resources = @articles.last(1)
1208
+ end
1209
+
1210
+ it 'should return a Collection' do
1211
+ @return.should be_kind_of(DataMapper::Collection)
1212
+ end
1213
+
1214
+ it 'should be the last N Resources in the Collection' do
1215
+ @resources.should == @copy.entries.last(1)
1216
+ end
1217
+ end
1218
+
1219
+ describe 'with offset specified' do
1220
+ before :all do
1221
+ @return = @resource = @articles.last(:offset => 1)
1222
+ end
1223
+
1224
+ it 'should return a Resource' do
1225
+ @return.should be_kind_of(DataMapper::Resource)
1226
+ end
1227
+
1228
+ it 'should be the second Resource in the Collection' do
1229
+ @resource.should == @copy.entries[-2]
1230
+ end
1231
+ end
1232
+
1233
+ describe 'with a limit and query specified' do
1234
+ before :all do
1235
+ @return = @resources = @articles.last(1, :content => 'Sample')
1236
+ end
1237
+
1238
+ it 'should return a Collection' do
1239
+ @return.should be_kind_of(DataMapper::Collection)
1240
+ end
1241
+
1242
+ it 'should be the last N Resources in the Collection matching the query' do
1243
+ @resources.should == [ @article ]
1244
+ end
1245
+ end
1246
+ end
1247
+
1248
+ it { @articles.should respond_to(:reverse) }
1249
+
1250
+ describe '#reverse' do
1251
+ before :all do
1252
+ @query = @articles.query
1253
+
1254
+ @new = @articles.create(:title => 'Sample Article')
1255
+
1256
+ @return = @articles.reverse
1257
+ end
1258
+
1259
+ it 'should return a Collection' do
1260
+ @return.should be_kind_of(DataMapper::Collection)
1261
+ end
1262
+
1263
+ it 'should return a Collection with reversed entries' do
1264
+ @return.should == @articles.entries.reverse
1265
+ end
1266
+
1267
+ it 'should return a Query that is the reverse of the original' do
1268
+ @return.query.should == @query.reverse
1269
+ end
1270
+ end
1271
+
1272
+ it 'should respond to a belongs_to relationship method with #method_missing' do
1273
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1274
+ @articles.should respond_to(:original)
1275
+ end
1276
+ end
1277
+
1278
+ it 'should respond to a has n relationship method with #method_missing' do
1279
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1280
+ @articles.should respond_to(:revisions)
1281
+ end
1282
+ end
1283
+
1284
+ it 'should respond to a has 1 relationship method with #method_missing' do
1285
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1286
+ @articles.should respond_to(:previous)
1287
+ end
1288
+ end
1289
+
1290
+ describe '#method_missing' do
1291
+ before do
1292
+ pending 'Model#method_missing should delegate to relationships' if @articles.kind_of?(Class)
1293
+ end
1294
+
1295
+ describe 'with a belongs_to relationship method' do
1296
+ before :all do
1297
+ rescue_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1298
+ @articles.create(:content => 'Another Article', :original => @original)
1299
+
1300
+ @return = @collection = @articles.originals
1301
+ end
1302
+ end
1303
+
1304
+ should_not_be_a_kicker
1305
+
1306
+ it 'should return a Collection' do
1307
+ @return.should be_kind_of(DataMapper::Collection)
1308
+ end
1309
+
1310
+ it 'should return expected Collection' do
1311
+ @collection.should == [ @original ]
1312
+ end
1313
+
1314
+ it 'should set the association for each Resource' do
1315
+ @articles.map { |resource| resource.original }.should == [ @original, @original ]
1316
+ end
1317
+ end
1318
+
1319
+ describe 'with a has 1 relationship method' do
1320
+ before :all do
1321
+ # FIXME: create is necessary for m:m so that the intermediary
1322
+ # is created properly. This does not occur with @new.save
1323
+ @new = @articles.send(@many_to_many ? :create : :new)
1324
+
1325
+ @article.previous = @new
1326
+ @new.previous = @other
1327
+
1328
+ @article.save
1329
+ @new.save
1330
+ end
1331
+
1332
+ describe 'with no arguments' do
1333
+ before :all do
1334
+ @return = @articles.previous
1335
+ end
1336
+
1337
+ should_not_be_a_kicker
1338
+
1339
+ it 'should return a Collection' do
1340
+ @return.should be_kind_of(DataMapper::Collection)
1341
+ end
1342
+
1343
+ it 'should return expected Collection' do
1344
+ # association is sorted reverse by id
1345
+ @return.should == [ @new, @other ]
1346
+ end
1347
+
1348
+ it 'should set the association for each Resource' do
1349
+ @articles.map { |resource| resource.previous }.should == [ @new, @other ]
1350
+ end
1351
+ end
1352
+
1353
+ describe 'with arguments' do
1354
+ before :all do
1355
+ @return = @articles.previous(:fields => [ :id ])
1356
+ end
1357
+
1358
+ should_not_be_a_kicker
1359
+
1360
+ it 'should return a Collection' do
1361
+ @return.should be_kind_of(DataMapper::Collection)
1362
+ end
1363
+
1364
+ it 'should return expected Collection' do
1365
+ # association is sorted reverse by id
1366
+ @return.should == [ @new, @other ]
1367
+ end
1368
+
1369
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1370
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1371
+ @return.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1372
+ end
1373
+ end
1374
+
1375
+ it 'should set the association for each Resource' do
1376
+ @articles.map { |resource| resource.previous }.should == [ @new, @other ]
1377
+ end
1378
+ end
1379
+ end
1380
+
1381
+ describe 'with a has n relationship method' do
1382
+ before :all do
1383
+ # FIXME: create is necessary for m:m so that the intermediary
1384
+ # is created properly. This does not occur with @new.save
1385
+ @new = @articles.send(@many_to_many ? :create : :new)
1386
+
1387
+ # associate the article with children
1388
+ @article.revisions << @new
1389
+ @new.revisions << @other
1390
+
1391
+ @article.save
1392
+ @new.save
1393
+ end
1394
+
1395
+ describe 'with no arguments' do
1396
+ before :all do
1397
+ @return = @collection = @articles.revisions
1398
+ end
1399
+
1400
+ should_not_be_a_kicker
1401
+
1402
+ it 'should return a Collection' do
1403
+ @return.should be_kind_of(DataMapper::Collection)
1404
+ end
1405
+
1406
+ it 'should return expected Collection' do
1407
+ @collection.should == [ @other, @new ]
1408
+ end
1409
+
1410
+ it 'should set the association for each Resource' do
1411
+ @articles.map { |resource| resource.revisions }.should == [ [ @new ], [ @other ] ]
1412
+ end
1413
+ end
1414
+
1415
+ describe 'with arguments' do
1416
+ before :all do
1417
+ @return = @collection = @articles.revisions(:fields => [ :id ])
1418
+ end
1419
+
1420
+ should_not_be_a_kicker
1421
+
1422
+ it 'should return a Collection' do
1423
+ @return.should be_kind_of(DataMapper::Collection)
1424
+ end
1425
+
1426
+ it 'should return expected Collection' do
1427
+ @collection.should == [ @other, @new ]
1428
+ end
1429
+
1430
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1431
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1432
+ @collection.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1433
+ end
1434
+ end
1435
+
1436
+ it 'should set the association for each Resource' do
1437
+ @articles.map { |resource| resource.revisions }.should == [ [ @new ], [ @other ] ]
1438
+ end
1439
+ end
1440
+ end
1441
+
1442
+ describe 'with a has n :through relationship method' do
1443
+ before :all do
1444
+ @new = @articles.create
1445
+
1446
+ @publication1 = @article.publications.create(:name => 'Ruby Today')
1447
+ @publication2 = @new.publications.create(:name => 'Inside DataMapper')
1448
+ end
1449
+
1450
+ describe 'with no arguments' do
1451
+ before :all do
1452
+ @return = @collection = @articles.publications
1453
+ end
1454
+
1455
+ should_not_be_a_kicker
1456
+
1457
+ it 'should return a Collection' do
1458
+ @return.should be_kind_of(DataMapper::Collection)
1459
+ end
1460
+
1461
+ it 'should return expected Collection' do
1462
+ pending_if @no_join do
1463
+ @collection.should == [ @publication1, @publication2 ]
1464
+ end
1465
+ end
1466
+
1467
+ it 'should set the association for each Resource' do
1468
+ pending_if @no_join do
1469
+ @articles.map { |resource| resource.publications }.should == [ [ @publication1 ], [ @publication2 ] ]
1470
+ end
1471
+ end
1472
+ end
1473
+
1474
+ describe 'with arguments' do
1475
+ before :all do
1476
+ @return = @collection = @articles.publications(:fields => [ :id ])
1477
+ end
1478
+
1479
+ should_not_be_a_kicker
1480
+
1481
+ it 'should return a Collection' do
1482
+ @return.should be_kind_of(DataMapper::Collection)
1483
+ end
1484
+
1485
+ it 'should return expected Collection' do
1486
+ pending_if @no_join do
1487
+ @collection.should == [ @publication1, @publication2 ]
1488
+ end
1489
+ end
1490
+
1491
+ { :id => true, :name => false }.each do |attribute, expected|
1492
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1493
+ @collection.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1494
+ end
1495
+ end
1496
+
1497
+ it 'should set the association for each Resource' do
1498
+ pending_if @no_join do
1499
+ @articles.map { |resource| resource.publications }.should == [ [ @publication1 ], [ @publication2 ] ]
1500
+ end
1501
+ end
1502
+ end
1503
+ end
1504
+
1505
+ describe 'with an unknown method' do
1506
+ it 'should raise an exception' do
1507
+ lambda {
1508
+ @articles.unknown
1509
+ }.should raise_error(NoMethodError)
1510
+ end
1511
+ end
1512
+ end
1513
+ end