dm-mongo-adapter 0.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.gitignore +9 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +130 -0
  4. data/Rakefile +36 -0
  5. data/TODO +33 -0
  6. data/VERSION.yml +5 -0
  7. data/bin/console +31 -0
  8. data/dm-mongo-adapter.gemspec +154 -0
  9. data/lib/mongo_adapter.rb +71 -0
  10. data/lib/mongo_adapter/adapter.rb +255 -0
  11. data/lib/mongo_adapter/aggregates.rb +21 -0
  12. data/lib/mongo_adapter/conditions.rb +100 -0
  13. data/lib/mongo_adapter/embedded_model.rb +187 -0
  14. data/lib/mongo_adapter/embedded_resource.rb +134 -0
  15. data/lib/mongo_adapter/embedments/one_to_many.rb +139 -0
  16. data/lib/mongo_adapter/embedments/one_to_one.rb +53 -0
  17. data/lib/mongo_adapter/embedments/relationship.rb +258 -0
  18. data/lib/mongo_adapter/migrations.rb +45 -0
  19. data/lib/mongo_adapter/model.rb +89 -0
  20. data/lib/mongo_adapter/model/embedment.rb +215 -0
  21. data/lib/mongo_adapter/modifier.rb +85 -0
  22. data/lib/mongo_adapter/query.rb +252 -0
  23. data/lib/mongo_adapter/query/java_script.rb +145 -0
  24. data/lib/mongo_adapter/resource.rb +147 -0
  25. data/lib/mongo_adapter/types/date.rb +28 -0
  26. data/lib/mongo_adapter/types/date_time.rb +28 -0
  27. data/lib/mongo_adapter/types/db_ref.rb +65 -0
  28. data/lib/mongo_adapter/types/discriminator.rb +32 -0
  29. data/lib/mongo_adapter/types/object_id.rb +72 -0
  30. data/lib/mongo_adapter/types/objects.rb +31 -0
  31. data/script/performance.rb +260 -0
  32. data/spec/legacy/README +6 -0
  33. data/spec/legacy/adapter_shared_spec.rb +299 -0
  34. data/spec/legacy/adapter_spec.rb +174 -0
  35. data/spec/legacy/associations_spec.rb +140 -0
  36. data/spec/legacy/embedded_resource_spec.rb +157 -0
  37. data/spec/legacy/embedments_spec.rb +177 -0
  38. data/spec/legacy/modifier_spec.rb +81 -0
  39. data/spec/legacy/property_spec.rb +51 -0
  40. data/spec/legacy/spec_helper.rb +3 -0
  41. data/spec/legacy/sti_spec.rb +53 -0
  42. data/spec/lib/cleanup_models.rb +32 -0
  43. data/spec/lib/raw_connections.rb +11 -0
  44. data/spec/public/embedded_collection_spec.rb +61 -0
  45. data/spec/public/embedded_resource_spec.rb +220 -0
  46. data/spec/public/model/embedment_spec.rb +186 -0
  47. data/spec/public/model_spec.rb +37 -0
  48. data/spec/public/resource_spec.rb +564 -0
  49. data/spec/public/shared/model_embedments_spec.rb +338 -0
  50. data/spec/public/shared/object_id_shared_spec.rb +56 -0
  51. data/spec/public/types/df_ref_spec.rb +6 -0
  52. data/spec/public/types/discriminator_spec.rb +118 -0
  53. data/spec/public/types/embedded_array_spec.rb +55 -0
  54. data/spec/public/types/embedded_hash_spec.rb +83 -0
  55. data/spec/public/types/object_id_spec.rb +6 -0
  56. data/spec/rcov.opts +6 -0
  57. data/spec/semipublic/embedded_model_spec.rb +43 -0
  58. data/spec/semipublic/model/embedment_spec.rb +42 -0
  59. data/spec/semipublic/resource_spec.rb +70 -0
  60. data/spec/spec.opts +4 -0
  61. data/spec/spec_helper.rb +45 -0
  62. data/tasks/spec.rake +37 -0
  63. data/tasks/yard.rake +9 -0
  64. data/tasks/yardstick.rake +21 -0
  65. metadata +215 -0
@@ -0,0 +1,338 @@
1
+ # The share specs contained herein are very slightly modified versions of
2
+ # those found in dm-core/spec/public/model/relationship_spec.rb
3
+
4
+ share_examples_for 'A singular embedment reader' do
5
+ it { @car.should respond_to(@name) }
6
+
7
+ describe 'reader' do
8
+ describe 'when there is no associated resource' do
9
+ it 'should return nil when there is no query' do
10
+ @car.__send__(@name).should be_nil
11
+ end
12
+
13
+ it 'should return nil when there is a query' do
14
+ @car.__send__(@name, :name => '__nothing__').should be_nil
15
+ end
16
+ end # when there is no associated resource
17
+
18
+ describe 'when there is an associated resource' do
19
+ before(:all) do
20
+ @expected = @model.new
21
+ @car.__send__("#{@name}=", @expected)
22
+ end
23
+
24
+ describe 'without a query' do
25
+ it 'should return an EmbeddedResource' do
26
+ returned = @car.__send__(@name)
27
+ returned.should be_kind_of(DataMapper::Mongo::EmbeddedResource)
28
+ end
29
+
30
+ it 'should return the correct EmbeddedResource' do
31
+ @car.__send__(@name).should == @expected
32
+ end
33
+ end
34
+
35
+ describe 'with a query' do
36
+ it 'should return a EmbeddedResource' do
37
+ returned = @car.__send__(@name, :name => @expected.name)
38
+ returned.should be_kind_of(DataMapper::Mongo::EmbeddedResource)
39
+ end
40
+
41
+ it 'should return the correct EmbeddedResource' do
42
+ @car.__send__(@name, :name => @expected.name).should == @expected
43
+ end
44
+ end
45
+ end # when there is an associated resource
46
+
47
+ end # reader
48
+ end # A singular embedment reader
49
+
50
+ share_examples_for 'A singular embedment writer' do
51
+ it { @car.should respond_to("#{@name}=") }
52
+
53
+ describe 'writer' do
54
+ describe 'when setting the wrong kind of target' do
55
+ it 'should raise an ArgumentError' do
56
+ calling = lambda { @car.__send__("#{@name}=", Object.new) }
57
+ calling.should raise_error(ArgumentError)
58
+ end
59
+ end
60
+
61
+ describe 'when setting an EmbeddedResource' do
62
+ before(:all) do
63
+ @expected = @model.new
64
+ @return = @car.__send__("#{@name}=", @expected)
65
+ end
66
+
67
+ it 'should return the expected EmbeddedResource' do
68
+ @return.should equal(@expected)
69
+ end
70
+
71
+ it 'should set the EmbeddedResource' do
72
+ @car.__send__(@name).should equal(@expected)
73
+ end
74
+
75
+ it 'should relate the associated EmbeddedResource' do
76
+ @expected.parent.should == @car
77
+ end
78
+
79
+ it 'should persist the Resource' do
80
+ @car.save.should be_true
81
+ @car.model.get(*@car.key).__send__(@name).should == @expected
82
+ end
83
+ end # when setting an EmbeddedResource
84
+
85
+ describe 'when setting a Hash' do
86
+ before(:all) do
87
+ @expected = @model.new(:name => 'Name')
88
+ @return = @car.__send__("#{@name}=", { :name => 'Name' })
89
+ end
90
+
91
+ it 'should return the expected EmbeddedResource' do
92
+ @return.should == @expected
93
+ end
94
+
95
+ it 'should set the EmbeddedResource' do
96
+ @car.__send__(@name).should equal(@return)
97
+ end
98
+
99
+ it 'should relate the associated EmbeddedResource' do
100
+ @car.__send__(@name).parent.should == @car
101
+ end
102
+
103
+ it 'should persist the Resource' do
104
+ @car.save.should be_true
105
+ @car.model.get(*@car.key).__send__(@name).should == @expected
106
+ end
107
+ end # when setting a Hash
108
+
109
+ describe 'when setting nil' do
110
+ before(:all) do
111
+ @car.__send__("#{@name}=", @model.new)
112
+ @return = @car.__send__("#{@name}=", nil)
113
+ end
114
+
115
+ it 'should return nil' do
116
+ @return.should be_nil
117
+ end
118
+
119
+ it 'should set nil' do
120
+ @car.__send__(@name).should be_nil
121
+ end
122
+
123
+ it 'should persist as nil' do
124
+ @car.save.should be_true
125
+ @car.model.get(*@car.key).__send__(@name).should be_nil
126
+ end
127
+ end # when setting nil
128
+
129
+ describe 'when changing the EmbeddedResource' do
130
+ before(:all) do
131
+ @car.__send__("#{@name}=", @model.new)
132
+ @return = @car.__send__("#{@name}=", @expected = @model.new)
133
+ end
134
+
135
+ it 'should return the expected EmbeddedResource' do
136
+ @return.should equal(@expected)
137
+ end
138
+
139
+ it 'should set the EmbeddedResource' do
140
+ @car.__send__(@name).should equal(@return)
141
+ end
142
+
143
+ it 'should relate the associated EmbeddedResource' do
144
+ @car.__send__(@name).parent.should == @car
145
+ end
146
+
147
+ it 'should persist the Resource' do
148
+ @car.save.should be_true
149
+ @car.model.get(*@car.key).__send__(@name).should == @expected
150
+ end
151
+ end # when changing the EmbeddedResource
152
+
153
+ end # writer
154
+ end # A singular embedment writer
155
+
156
+ share_examples_for 'A many embedment reader' do
157
+ it { @car.should respond_to(@name) }
158
+
159
+ describe 'reader' do
160
+ describe 'when there are no child resources and the source is saved' do
161
+ before(:all) do
162
+ @car.save.should be_true
163
+ @return = @car.__send__(@name)
164
+ end
165
+
166
+ it 'should return a Collection' do
167
+ @return.should be_kind_of(
168
+ DataMapper::Mongo::Embedments::OneToMany::Collection)
169
+ end
170
+
171
+ it 'should return an empty Collection' do
172
+ @return.should be_empty
173
+ end
174
+ end # when there is no child resource and the source is saved
175
+
176
+ describe 'when there are no child resources and the source is not saved' do
177
+ before(:all) do
178
+ @return = @car.__send__(@name)
179
+ end
180
+
181
+ it 'should return a Collection' do
182
+ @return.should be_kind_of(
183
+ DataMapper::Mongo::Embedments::OneToMany::Collection)
184
+ end
185
+
186
+ it 'should return an empty Collection' do
187
+ @return.should be_empty
188
+ end
189
+ end # when there is no child resource and the source is not save
190
+
191
+ describe 'when there is a child resource' do
192
+ before(:all) do
193
+ @expected = @model.new
194
+ @car.__send__("#{@name}=", [ @expected ])
195
+ @return = @car.__send__(@name)
196
+ end
197
+
198
+ it 'should return a Collection' do
199
+ @return.should be_kind_of(
200
+ DataMapper::Mongo::Embedments::OneToMany::Collection)
201
+ end
202
+
203
+ it 'should return the expected resources' do
204
+ @return.should == [ @expected ]
205
+ end
206
+ end # when there is a child resource
207
+
208
+ end # reader
209
+ end # A many embedment reader
210
+
211
+ share_examples_for 'A many embedment writer' do
212
+ it { @car.should respond_to("#{@name}=") }
213
+
214
+ describe 'writer' do
215
+ describe 'when setting an Array of the wrong kind of target' do
216
+ it 'should raise an ArgumentError' do
217
+ calling = lambda { @car.__send__("#{@name}=", [Object.new]) }
218
+ calling.should raise_error(ArgumentError)
219
+ end
220
+ end # when setting an Array of the wrong kind of target
221
+
222
+ describe 'when setting an Array of EmbeddedResources' do
223
+ before(:all) do
224
+ @expected = [ @model.new ]
225
+ @return = @car.__send__("#{@name}=", @expected)
226
+ end
227
+
228
+ it 'should return the expected Collection' do
229
+ @return.should == @expected
230
+ end
231
+
232
+ it 'should set the Collection' do
233
+ @car.__send__(@name).should == @expected
234
+ @car.__send__(@name).zip(@expected) do |value, expected|
235
+ value.should equal(expected)
236
+ end
237
+ end
238
+
239
+ it 'should relate the associated Collection' do
240
+ @expected.each { |resource| resource.parent.should == @car }
241
+ end
242
+
243
+ it 'should persist the Collection' do
244
+ @car.save.should be_true
245
+ @car.model.get(*@car.key).__send__(@name).should == @expected
246
+ end
247
+
248
+ it 'should persist the associated EmbeddedResources' do
249
+ @car.save.should be_true
250
+ @expected.each { |resource| resource.should be_saved }
251
+ end
252
+ end # when setting an Array of EmbeddedResources
253
+
254
+ describe 'when setting an Array of Hashes' do
255
+ before(:all) do
256
+ @expected = [ @model.new(:name => 'Name') ]
257
+ @return = @car.__send__("#{@name}=", [{ :name => 'Name' }])
258
+ end
259
+
260
+ it 'should return the expected Collection' do
261
+ @return.should == @expected
262
+ end
263
+
264
+ it 'should set the Collection' do
265
+ @car.__send__(@name).should == @expected
266
+ @car.__send__(@name).zip(@expected) do |value, expected|
267
+ value.should == expected
268
+ end
269
+ end
270
+
271
+ it 'should relate the associated Collection' do
272
+ @return.each { |resource| resource.parent.should == @car }
273
+ end
274
+
275
+ it 'should persist the Collection' do
276
+ @car.save.should be_true
277
+ @car.model.get(*@car.key).__send__(@name).should == @expected
278
+ end
279
+
280
+ it 'should persist the associated EmbeddedResources' do
281
+ @car.save.should be_true
282
+ @return.each { |resource| resource.should be_saved }
283
+ end
284
+ end # when setting an Array of Hashes
285
+
286
+ describe 'when setting an empty collection' do
287
+ before :all do
288
+ @car.__send__("#{@name}=", [ @model.new ])
289
+ @return = @car.__send__("#{@name}=", [])
290
+ end
291
+
292
+ it 'should return a Collection' do
293
+ @return.should be_kind_of(
294
+ DataMapper::Mongo::Embedments::OneToMany::Collection)
295
+ end
296
+
297
+ it 'should set a empty Collection' do
298
+ @car.__send__(@name).should be_empty
299
+ end
300
+
301
+ it 'should persist as an empty collection' do
302
+ @car.save.should be_true
303
+ @car.model.get(*@car.key).__send__(@name).should be_empty
304
+ end
305
+ end # when setting an empty collection
306
+
307
+ describe 'when changing an associated collection' do
308
+ before(:all) do
309
+ @car.__send__("#{@name}=", [ @model.new ])
310
+ @expected = [ @model.new ]
311
+ @return = @car.__send__("#{@name}=", @expected)
312
+ end
313
+
314
+ it 'should return the expected Resource' do
315
+ @return.should == @expected
316
+ end
317
+
318
+ it 'should set the Resource' do
319
+ @car.__send__(@name).should == @expected
320
+ end
321
+
322
+ it 'should relate the associated Resource' do
323
+ @expected.each { |resource| resource.parent.should == @car }
324
+ end
325
+
326
+ it 'should persist the Resource' do
327
+ @car.save.should be_true
328
+ @car.model.get(*@car.key).__send__(@name).should == @expected
329
+ end
330
+
331
+ it 'should persist the associated Resource' do
332
+ @car.save.should be_true
333
+ @expected.each { |resource| resource.should be_saved }
334
+ end
335
+ end # when setting an associated collection
336
+
337
+ end #writer
338
+ end # A many embedment writer
@@ -0,0 +1,56 @@
1
+ share_examples_for 'An ObjectID Type' do
2
+
3
+ describe '.load' do
4
+ it 'should return nil when given nil' do
5
+ @type_class.load(nil, nil).should be_nil
6
+ end
7
+
8
+ it 'should return the argument when given a string' do
9
+ loaded = @type_class.load('avalue', nil)
10
+ loaded.should == 'avalue'
11
+ end
12
+
13
+ it 'should return a string when given a Mongo::ObjectID' do
14
+ mongo_id = ::Mongo::ObjectID.new
15
+ loaded = @type_class.load(mongo_id, nil)
16
+ loaded.should be_kind_of(String)
17
+ loaded.should == mongo_id.to_s
18
+ end
19
+
20
+ it 'should raise an error when given anything else' do
21
+ [ 0, 1, Object.new, true, false, [], {} ].each do |value|
22
+ lambda {
23
+ @type_class.load(value, nil)
24
+ }.should raise_error(ArgumentError)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '.dump' do
30
+ it 'should return nil when given nil' do
31
+ @type_class.dump(nil, nil).should be_nil
32
+ end
33
+
34
+ it 'should return a Mongo::ObjectID when given a string' do
35
+ mongo_id = ::Mongo::ObjectID.new
36
+ dumped = @type_class.dump(mongo_id.to_s, nil)
37
+ dumped.should be_kind_of(::Mongo::ObjectID)
38
+ dumped.to_s.should == mongo_id.to_s
39
+ end
40
+
41
+ it 'should return the argument when given a Mongo::ObjectID' do
42
+ mongo_id = ::Mongo::ObjectID.new
43
+ dumped = @type_class.dump(mongo_id, nil)
44
+ dumped.should == mongo_id
45
+ end
46
+
47
+ it 'should raise an error when given anything else' do
48
+ [ 0, 1, Object.new, true, false, [], {} ].each do |value|
49
+ lambda {
50
+ @type_class.dump(value, nil)
51
+ }.should raise_error(ArgumentError)
52
+ end
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe DataMapper::Mongo::Types::DBRef do
4
+ before(:all) { @type_class = DataMapper::Mongo::Types::DBRef }
5
+ it_should_behave_like 'An ObjectID Type'
6
+ end
@@ -0,0 +1,118 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe DataMapper::Mongo::Types::Discriminator do
4
+ before :all do
5
+ class Article
6
+ include DataMapper::Mongo::Resource
7
+
8
+ property :id, ObjectID
9
+ property :title, String, :required => true
10
+ property :type, Discriminator
11
+ end
12
+
13
+ class Announcement < Article; end
14
+ class Release < Announcement; end
15
+
16
+ Article.all.destroy!
17
+
18
+ @article_model = Article
19
+ @announcement_model = Announcement
20
+ @release_model = Release
21
+ end
22
+
23
+ it 'should typecast to a Model' do
24
+ @article_model.properties[:type].typecast('Release').should equal(@release_model)
25
+ end
26
+
27
+ describe 'Model#new' do
28
+ describe 'when provided a String discriminator in the attributes' do
29
+ before :all do
30
+ @resource = @article_model.new(:type => 'Release')
31
+ end
32
+
33
+ it 'should return a Resource' do
34
+ @resource.should be_kind_of(DataMapper::Resource)
35
+ end
36
+
37
+ it 'should be an descendant instance' do
38
+ @resource.should be_instance_of(Release)
39
+ end
40
+ end
41
+
42
+ describe 'when provided a Class discriminator in the attributes' do
43
+ before :all do
44
+ @resource = @article_model.new(:type => Release)
45
+ end
46
+
47
+ it 'should return a Resource' do
48
+ @resource.should be_kind_of(DataMapper::Resource)
49
+ end
50
+
51
+ it 'should be an descendant instance' do
52
+ @resource.should be_instance_of(Release)
53
+ end
54
+ end
55
+
56
+ describe 'when not provided a discriminator in the attributes' do
57
+ before :all do
58
+ @resource = @article_model.new
59
+ end
60
+
61
+ it 'should return a Resource' do
62
+ @resource.should be_kind_of(DataMapper::Resource)
63
+ end
64
+
65
+ it 'should be a base model instance' do
66
+ @resource.should be_instance_of(@article_model)
67
+ end
68
+ end
69
+ end
70
+
71
+ describe 'Model#descendants' do
72
+ it 'should set the descendants for the grandparent model' do
73
+ @article_model.descendants.to_a.should == [ @article_model, @announcement_model, @release_model ]
74
+ end
75
+
76
+ it 'should set the descendants for the parent model' do
77
+ @announcement_model.descendants.to_a.should == [ @announcement_model, @release_model ]
78
+ end
79
+
80
+ it 'should set the descendants for the child model' do
81
+ @release_model.descendants.to_a.should == [ @release_model ]
82
+ end
83
+ end
84
+
85
+ describe 'Model#default_scope' do
86
+ it 'should set the default scope for the grandparent model' do
87
+ @article_model.default_scope[:type].should equal(@article_model.descendants)
88
+ end
89
+
90
+ it 'should set the default scope for the parent model' do
91
+ @announcement_model.default_scope[:type].should equal(@announcement_model.descendants)
92
+ end
93
+
94
+ it 'should set the default scope for the child model' do
95
+ @release_model.default_scope[:type].should equal(@release_model.descendants)
96
+ end
97
+ end
98
+
99
+ before :all do
100
+ @announcement = @announcement_model.create(:title => 'Announcement')
101
+ end
102
+
103
+ it 'should persist the type' do
104
+ @announcement.model.get(*@announcement.key).type.should equal(@announcement_model)
105
+ end
106
+
107
+ it 'should be retrieved as an instance of the correct class' do
108
+ @announcement.model.get(*@announcement.key).should be_instance_of(@announcement_model)
109
+ end
110
+
111
+ it 'should include descendants in finders' do
112
+ @article_model.first.should eql(@announcement)
113
+ end
114
+
115
+ it 'should not include ancestors' do
116
+ @release_model.first.should be_nil
117
+ end
118
+ end