mongo_mapper-unstable 2010.1.27 → 2010.1.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,652 +1,663 @@
1
1
  require 'test_helper'
2
2
 
3
- class Grandparent
4
- include MongoMapper::EmbeddedDocument
5
- key :grandparent, String
6
- end
7
-
8
- class Parent < Grandparent
9
- include MongoMapper::EmbeddedDocument
10
- key :parent, String
11
- end
12
-
13
- class Child < Parent
14
- include MongoMapper::EmbeddedDocument
15
- key :child, String
16
- end
17
-
18
3
  module KeyOverride
19
4
  def other_child
20
5
  self[:other_child] || "special result"
21
6
  end
22
-
7
+
23
8
  def other_child=(value)
24
9
  super(value + " modified")
25
10
  end
26
11
  end
27
12
 
28
- class OtherChild < Parent
29
- include MongoMapper::EmbeddedDocument
30
- include KeyOverride
31
-
32
- key :other_child, String
33
- end
34
-
35
13
  class EmbeddedDocumentTest < Test::Unit::TestCase
36
- context "Including MongoMapper::EmbeddedDocument in a class" do
14
+ context "" do
37
15
  setup do
38
- @klass = EDoc()
39
- end
40
-
41
- should "add _id key" do
42
- @klass.keys['_id'].should_not be_nil
43
- end
44
-
45
- should "know it is using object id" do
46
- @klass.using_object_id?.should be_true
47
- end
48
-
49
- should "know it is not using object id if _id type is changed" do
50
- @klass.key :_id, String
51
- @klass.using_object_id?.should be_false
52
- end
53
- end
54
-
55
- context "Class Methods" do
56
- should "include logger" do
57
- @klass = EDoc()
58
- @klass.logger.should == MongoMapper.logger
59
- @klass.logger.should be_instance_of(Logger)
60
- end
61
-
62
- should "return false for embeddable" do
63
- EDoc().embeddable?.should be_true
64
- end
65
-
66
- context "#to_mongo" do
67
- setup { @klass = EDoc() }
68
-
69
- should "be nil if nil" do
70
- @klass.to_mongo(nil).should be_nil
71
- end
72
-
73
- should "convert to_mongo for other values" do
74
- doc = @klass.new(:foo => 'bar')
75
- to_mongo = @klass.to_mongo(doc)
76
- to_mongo.is_a?(Hash).should be_true
77
- to_mongo['foo'].should == 'bar'
16
+ class ::Grandparent
17
+ include MongoMapper::EmbeddedDocument
18
+ key :grandparent, String
78
19
  end
79
- end
80
-
81
- context "#from_mongo" do
82
- setup { @klass = EDoc() }
83
-
84
- should "be nil if nil" do
85
- @klass.from_mongo(nil).should be_nil
86
- end
87
-
88
- should "be instance if instance of class" do
89
- doc = @klass.new
90
- @klass.from_mongo(doc).should == doc
91
- end
92
-
93
- should "be instance if hash of attributes" do
94
- doc = @klass.from_mongo({:foo => 'bar'})
95
- doc.instance_of?(@klass).should be_true
96
- doc.foo.should == 'bar'
97
- end
98
- end
99
20
 
100
- context "defining a key" do
101
- setup do
102
- @document = EDoc()
21
+ class ::Parent < ::Grandparent
22
+ include MongoMapper::EmbeddedDocument
23
+ key :parent, String
103
24
  end
104
25
 
105
- should "work with name" do
106
- key = @document.key(:name)
107
- key.name.should == 'name'
26
+ class ::Child < ::Parent
27
+ include MongoMapper::EmbeddedDocument
28
+ key :child, String
108
29
  end
109
30
 
110
- should "work with name and type" do
111
- key = @document.key(:name, String)
112
- key.name.should == 'name'
113
- key.type.should == String
114
- end
31
+ class ::OtherChild < ::Parent
32
+ include MongoMapper::EmbeddedDocument
33
+ include KeyOverride
115
34
 
116
- should "work with name, type and options" do
117
- key = @document.key(:name, String, :required => true)
118
- key.name.should == 'name'
119
- key.type.should == String
120
- key.options[:required].should be_true
35
+ key :other_child, String
121
36
  end
37
+ end
122
38
 
123
- should "work with name and options" do
124
- key = @document.key(:name, :required => true)
125
- key.name.should == 'name'
126
- key.options[:required].should be_true
39
+ teardown do
40
+ Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
41
+ Object.send :remove_const, 'Parent' if defined?(::Parent)
42
+ Object.send :remove_const, 'Child' if defined?(::Child)
43
+ Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
44
+ end
45
+
46
+ context "Including MongoMapper::EmbeddedDocument in a class" do
47
+ setup do
48
+ @klass = EDoc()
127
49
  end
128
50
 
129
- should "be tracked per document" do
130
- @document.key(:name, String)
131
- @document.key(:age, Integer)
132
- @document.keys['name'].name.should == 'name'
133
- @document.keys['name'].type.should == String
134
- @document.keys['age'].name.should == 'age'
135
- @document.keys['age'].type.should == Integer
51
+ should "add _id key" do
52
+ @klass.keys['_id'].should_not be_nil
136
53
  end
137
54
 
138
- should "be redefinable" do
139
- @document.key(:foo, String)
140
- @document.keys['foo'].type.should == String
141
- @document.key(:foo, Integer)
142
- @document.keys['foo'].type.should == Integer
55
+ should "know it is using object id" do
56
+ @klass.using_object_id?.should be_true
143
57
  end
144
58
 
145
- should "create reader method" do
146
- @document.new.should_not respond_to(:foo)
147
- @document.key(:foo, String)
148
- @document.new.should respond_to(:foo)
59
+ should "know it is not using object id if _id type is changed" do
60
+ @klass.key :_id, String
61
+ @klass.using_object_id?.should be_false
149
62
  end
63
+ end
150
64
 
151
- should "create reader before typecast method" do
152
- @document.new.should_not respond_to(:foo_before_typecast)
153
- @document.key(:foo, String)
154
- @document.new.should respond_to(:foo_before_typecast)
65
+ context "Class Methods" do
66
+ should "include logger" do
67
+ @klass = EDoc()
68
+ @klass.logger.should == MongoMapper.logger
69
+ @klass.logger.should be_instance_of(Logger)
155
70
  end
156
71
 
157
- should "create writer method" do
158
- @document.new.should_not respond_to(:foo=)
159
- @document.key(:foo, String)
160
- @document.new.should respond_to(:foo=)
72
+ should "return false for embeddable" do
73
+ EDoc().embeddable?.should be_true
161
74
  end
162
75
 
163
- should "create boolean method" do
164
- @document.new.should_not respond_to(:foo?)
165
- @document.key(:foo, String)
166
- @document.new.should respond_to(:foo?)
167
- end
168
- end
169
-
170
- context "keys" do
171
- should "be inherited" do
172
- Grandparent.keys.keys.sort.should == ['_id', 'grandparent']
173
- Parent.keys.keys.sort.should == ['_id', 'grandparent', 'parent']
174
- Child.keys.keys.sort.should == ['_id', 'child', 'grandparent', 'parent']
175
- end
76
+ context "#to_mongo" do
77
+ setup { @klass = EDoc() }
176
78
 
177
- should "propogate to descendants if key added after class definition" do
178
- Grandparent.key :_type, String
79
+ should "be nil if nil" do
80
+ @klass.to_mongo(nil).should be_nil
81
+ end
179
82
 
180
- Grandparent.keys.keys.sort.should == ['_id', '_type', 'grandparent']
181
- Parent.keys.keys.sort.should == ['_id', '_type', 'grandparent', 'parent']
182
- Child.keys.keys.sort.should == ['_id', '_type', 'child', 'grandparent', 'parent']
83
+ should "convert to_mongo for other values" do
84
+ doc = @klass.new(:foo => 'bar')
85
+ to_mongo = @klass.to_mongo(doc)
86
+ to_mongo.is_a?(Hash).should be_true
87
+ to_mongo['foo'].should == 'bar'
88
+ end
183
89
  end
184
90
 
185
- should "not add anonymous objects to the ancestor tree" do
186
- OtherChild.ancestors.any? { |a| a.name.blank? }.should be_false
187
- end
91
+ context "#from_mongo" do
92
+ setup { @klass = EDoc() }
188
93
 
189
- should "not include descendant keys" do
190
- lambda { Parent.new.other_child }.should raise_error
191
- end
192
- end
193
-
194
- context "descendants" do
195
- should "default to nil" do
196
- Child.descendants.should be_nil
197
- end
94
+ should "be nil if nil" do
95
+ @klass.from_mongo(nil).should be_nil
96
+ end
198
97
 
199
- should "be recorded" do
200
- Grandparent.descendants.should == [Parent]
201
- Parent.descendants.should == [Child, OtherChild]
202
- end
203
- end
204
- end
98
+ should "be instance if instance of class" do
99
+ doc = @klass.new
100
+ @klass.from_mongo(doc).should == doc
101
+ end
205
102
 
206
- context "An instance of an embedded document" do
207
- setup do
208
- @document = EDoc do
209
- key :name, String
210
- key :age, Integer
103
+ should "be instance if hash of attributes" do
104
+ doc = @klass.from_mongo({:foo => 'bar'})
105
+ doc.instance_of?(@klass).should be_true
106
+ doc.foo.should == 'bar'
107
+ end
211
108
  end
212
- end
213
-
214
- should "have to_param that is string representation of id" do
215
- doc = @document.new
216
- doc.to_param.should == doc.id.to_s
217
- doc.to_param.should be_instance_of(String)
218
- end
219
-
220
- should "have access to class logger" do
221
- doc = @document.new
222
- doc.logger.should == @document.logger
223
- doc.logger.should be_instance_of(Logger)
224
- end
225
-
226
- should "automatically have an _id key" do
227
- @document.keys.keys.should include('_id')
228
- end
229
-
230
- should "create id during initialization" do
231
- @document.new._id.should be_instance_of(Mongo::ObjectID)
232
- end
233
-
234
- should "have id method returns _id" do
235
- id = Mongo::ObjectID.new
236
- doc = @document.new(:_id => id)
237
- doc.id.should == id
238
- end
239
-
240
- should "convert string object id to mongo object id when assigning id with _id object id type" do
241
- id = Mongo::ObjectID.new
242
-
243
- doc = @document.new(:id => id.to_s)
244
- doc._id.should == id
245
- doc.id.should == id
246
-
247
- doc = @document.new(:_id => id.to_s)
248
- doc._id.should == id
249
- doc.id.should == id
250
- end
251
109
 
252
- context "_root_document" do
253
- should "default to nil" do
254
- @document.new._root_document.should be_nil
110
+ context "defining a key" do
111
+ setup do
112
+ @document = EDoc()
113
+ end
114
+
115
+ should "work with name" do
116
+ key = @document.key(:name)
117
+ key.name.should == 'name'
118
+ end
119
+
120
+ should "work with name and type" do
121
+ key = @document.key(:name, String)
122
+ key.name.should == 'name'
123
+ key.type.should == String
124
+ end
125
+
126
+ should "work with name, type and options" do
127
+ key = @document.key(:name, String, :required => true)
128
+ key.name.should == 'name'
129
+ key.type.should == String
130
+ key.options[:required].should be_true
131
+ end
132
+
133
+ should "work with name and options" do
134
+ key = @document.key(:name, :required => true)
135
+ key.name.should == 'name'
136
+ key.options[:required].should be_true
137
+ end
138
+
139
+ should "be tracked per document" do
140
+ @document.key(:name, String)
141
+ @document.key(:age, Integer)
142
+ @document.keys['name'].name.should == 'name'
143
+ @document.keys['name'].type.should == String
144
+ @document.keys['age'].name.should == 'age'
145
+ @document.keys['age'].type.should == Integer
146
+ end
147
+
148
+ should "be redefinable" do
149
+ @document.key(:foo, String)
150
+ @document.keys['foo'].type.should == String
151
+ @document.key(:foo, Integer)
152
+ @document.keys['foo'].type.should == Integer
153
+ end
154
+
155
+ should "create reader method" do
156
+ @document.new.should_not respond_to(:foo)
157
+ @document.key(:foo, String)
158
+ @document.new.should respond_to(:foo)
159
+ end
160
+
161
+ should "create reader before typecast method" do
162
+ @document.new.should_not respond_to(:foo_before_typecast)
163
+ @document.key(:foo, String)
164
+ @document.new.should respond_to(:foo_before_typecast)
165
+ end
166
+
167
+ should "create writer method" do
168
+ @document.new.should_not respond_to(:foo=)
169
+ @document.key(:foo, String)
170
+ @document.new.should respond_to(:foo=)
171
+ end
172
+
173
+ should "create boolean method" do
174
+ @document.new.should_not respond_to(:foo?)
175
+ @document.key(:foo, String)
176
+ @document.new.should respond_to(:foo?)
177
+ end
255
178
  end
256
179
 
257
- should "allow setting when initialized" do
258
- root = Doc().new
259
- doc = @document.new :_root_document => root
260
-
261
- doc._root_document.should be(root)
180
+ context "keys" do
181
+ should "be inherited" do
182
+ Grandparent.keys.keys.sort.should == ['_id', 'grandparent']
183
+ Parent.keys.keys.sort.should == ['_id', 'grandparent', 'parent']
184
+ Child.keys.keys.sort.should == ['_id', 'child', 'grandparent', 'parent']
185
+ end
186
+
187
+ should "propogate to descendants if key added after class definition" do
188
+ Grandparent.key :_type, String
189
+
190
+ Grandparent.keys.keys.sort.should == ['_id', '_type', 'grandparent']
191
+ Parent.keys.keys.sort.should == ['_id', '_type', 'grandparent', 'parent']
192
+ Child.keys.keys.sort.should == ['_id', '_type', 'child', 'grandparent', 'parent']
193
+ end
194
+
195
+ should "not add anonymous objects to the ancestor tree" do
196
+ OtherChild.ancestors.any? { |a| a.name.blank? }.should be_false
197
+ end
198
+
199
+ should "not include descendant keys" do
200
+ lambda { Parent.new.other_child }.should raise_error
201
+ end
262
202
  end
263
203
 
264
- should "also be set on many embedded documents" do
265
- root = Doc().new
266
- klass = EDoc { many :children }
267
- doc = klass.new(:_root_document => root, :children => [{}])
268
-
269
- doc.children.first._root_document.should == root
204
+ context "descendants" do
205
+ should "default to nil" do
206
+ Child.descendants.should be_nil
207
+ end
208
+
209
+ should "be recorded" do
210
+ Grandparent.descendants.should == [Parent]
211
+ Parent.descendants.should == [Child, OtherChild]
212
+ end
270
213
  end
271
214
  end
272
215
 
273
- context "being initialized" do
274
- should "accept a hash that sets keys and values" do
275
- doc = @document.new(:name => 'John', :age => 23)
276
- doc.attributes.keys.sort.should == ['_id', 'age', 'name']
277
- doc.attributes['name'].should == 'John'
278
- doc.attributes['age'].should == 23
279
- end
280
-
281
- should "be able to assign keys dynamically" do
282
- doc = @document.new(:name => 'John', :skills => ['ruby', 'rails'])
283
- doc.name.should == 'John'
284
- doc.skills.should == ['ruby', 'rails']
216
+ context "An instance of an embedded document" do
217
+ setup do
218
+ @document = EDoc do
219
+ key :name, String
220
+ key :age, Integer
221
+ end
285
222
  end
286
223
 
287
- should "not throw error if initialized with nil" do
288
- assert_nothing_raised { @document.new(nil) }
224
+ should "have to_param that is string representation of id" do
225
+ doc = @document.new
226
+ doc.to_param.should == doc.id.to_s
227
+ doc.to_param.should be_instance_of(String)
289
228
  end
290
- end
291
-
292
- context "initialized when _type key present" do
293
- setup do
294
- @klass = EDoc('FooBar') { key :_type, String }
229
+
230
+ should "have access to class logger" do
231
+ doc = @document.new
232
+ doc.logger.should == @document.logger
233
+ doc.logger.should be_instance_of(Logger)
295
234
  end
296
235
 
297
- should "set _type to class name" do
298
- @klass.new._type.should == 'FooBar'
236
+ should "automatically have an _id key" do
237
+ @document.keys.keys.should include('_id')
299
238
  end
300
-
301
- should "not change _type if already set" do
302
- @klass.new(:_type => 'Foo')._type.should == 'Foo'
239
+
240
+ should "create id during initialization" do
241
+ @document.new._id.should be_instance_of(Mongo::ObjectID)
303
242
  end
304
- end
305
243
 
306
- context "attributes=" do
307
- should "update values for keys provided" do
308
- doc = @document.new(:name => 'foobar', :age => 10)
309
- doc.attributes = {:name => 'new value', :age => 5}
310
- doc.attributes[:name].should == 'new value'
311
- doc.attributes[:age].should == 5
244
+ should "have id method returns _id" do
245
+ id = Mongo::ObjectID.new
246
+ doc = @document.new(:_id => id)
247
+ doc.id.should == id
312
248
  end
313
249
 
314
- should "not update values for keys that were not provided" do
315
- doc = @document.new(:name => 'foobar', :age => 10)
316
- doc.attributes = {:name => 'new value'}
317
- doc.attributes[:name].should == 'new value'
318
- doc.attributes[:age].should == 10
250
+ should "convert string object id to mongo object id when assigning id with _id object id type" do
251
+ id = Mongo::ObjectID.new
252
+
253
+ doc = @document.new(:id => id.to_s)
254
+ doc._id.should == id
255
+ doc.id.should == id
256
+
257
+ doc = @document.new(:_id => id.to_s)
258
+ doc._id.should == id
259
+ doc.id.should == id
319
260
  end
320
261
 
321
- should "work with pre-defined methods" do
322
- @document.class_eval do
323
- attr_writer :password
262
+ context "_root_document" do
263
+ should "default to nil" do
264
+ @document.new._root_document.should be_nil
265
+ end
324
266
 
325
- def passwd
326
- @password
327
- end
267
+ should "allow setting when initialized" do
268
+ root = Doc().new
269
+ doc = @document.new :_root_document => root
270
+
271
+ doc._root_document.should be(root)
328
272
  end
329
273
 
330
- doc = @document.new(:name => 'foobar', :password => 'secret')
331
- doc.passwd.should == 'secret'
332
- end
274
+ should "also be set on many embedded documents" do
275
+ root = Doc().new
276
+ klass = EDoc { many :children }
277
+ doc = klass.new(:_root_document => root, :children => [{}])
333
278
 
334
- should "typecast key values" do
335
- doc = @document.new(:name => 1234, :age => '21')
336
- doc.name.should == '1234'
337
- doc.age.should == 21
279
+ doc.children.first._root_document.should == root
280
+ end
338
281
  end
339
- end
340
282
 
341
- context "attributes" do
342
- should "default to hash with all keys" do
343
- doc = @document.new
344
- doc.attributes.keys.sort.should == ['_id', 'age', 'name']
345
- end
283
+ context "being initialized" do
284
+ should "accept a hash that sets keys and values" do
285
+ doc = @document.new(:name => 'John', :age => 23)
286
+ doc.attributes.keys.sort.should == ['_id', 'age', 'name']
287
+ doc.attributes['name'].should == 'John'
288
+ doc.attributes['age'].should == 23
289
+ end
346
290
 
347
- should "return all keys with values" do
348
- doc = @document.new(:name => 'string', :age => nil)
349
- doc.attributes.keys.sort.should == ['_id', 'age', 'name']
350
- doc.attributes.values.should include('string')
351
- doc.attributes.values.should include(nil)
352
- end
353
-
354
- should "have indifferent access" do
355
- doc = @document.new(:name => 'string')
356
- doc.attributes[:name].should == 'string'
357
- doc.attributes['name'].should == 'string'
358
- end
359
- end
360
-
361
- context "to_mongo" do
362
- should "default to hash with _id key" do
363
- doc = @document.new
364
- doc.to_mongo.keys.sort.should == ['_id', 'age', 'name']
365
- end
366
-
367
- should "return all keys" do
368
- doc = @document.new(:name => 'string', :age => nil)
369
- doc.to_mongo.keys.sort.should == ['_id', 'age', 'name']
370
- doc.to_mongo.values.should include('string')
371
- doc.to_mongo.values.should include(nil)
372
- end
373
- end
291
+ should "be able to assign keys dynamically" do
292
+ doc = @document.new(:name => 'John', :skills => ['ruby', 'rails'])
293
+ doc.name.should == 'John'
294
+ doc.skills.should == ['ruby', 'rails']
295
+ end
374
296
 
375
- context "clone" do
376
- should "regenerate the id" do
377
- doc = @document.new(:name => "foo", :age => 27)
378
- doc_id = doc.id
379
- clone = doc.clone
380
- clone_id = clone.id
381
- clone_id.should_not == doc_id
297
+ should "not throw error if initialized with nil" do
298
+ assert_nothing_raised { @document.new(nil) }
299
+ end
382
300
  end
383
301
 
384
- should "copy the attributes" do
385
- doc = @document.new(:name => "foo", :age => 27)
386
- clone = doc.clone
387
- clone.name.should == "foo"
388
- clone.age.should == 27
302
+ context "initialized when _type key present" do
303
+ setup do
304
+ @klass = EDoc('FooBar') { key :_type, String }
305
+ end
306
+
307
+ should "set _type to class name" do
308
+ @klass.new._type.should == 'FooBar'
309
+ end
310
+
311
+ should "not change _type if already set" do
312
+ @klass.new(:_type => 'Foo')._type.should == 'Foo'
313
+ end
389
314
  end
390
- end
391
-
392
- context "key shorcut access" do
393
- context "[]" do
394
- should "work when key found" do
395
- doc = @document.new(:name => 'string')
396
- doc[:name].should == 'string'
315
+
316
+ context "attributes=" do
317
+ should "update values for keys provided" do
318
+ doc = @document.new(:name => 'foobar', :age => 10)
319
+ doc.attributes = {:name => 'new value', :age => 5}
320
+ doc.attributes[:name].should == 'new value'
321
+ doc.attributes[:age].should == 5
397
322
  end
398
-
399
- should "raise exception when key not found" do
400
- doc = @document.new(:name => 'string')
401
- assert_raises(MongoMapper::KeyNotFound) { doc[:not_here] }
323
+
324
+ should "not update values for keys that were not provided" do
325
+ doc = @document.new(:name => 'foobar', :age => 10)
326
+ doc.attributes = {:name => 'new value'}
327
+ doc.attributes[:name].should == 'new value'
328
+ doc.attributes[:age].should == 10
329
+ end
330
+
331
+ should "work with pre-defined methods" do
332
+ @document.class_eval do
333
+ attr_writer :password
334
+
335
+ def passwd
336
+ @password
337
+ end
338
+ end
339
+
340
+ doc = @document.new(:name => 'foobar', :password => 'secret')
341
+ doc.passwd.should == 'secret'
342
+ end
343
+
344
+ should "typecast key values" do
345
+ doc = @document.new(:name => 1234, :age => '21')
346
+ doc.name.should == '1234'
347
+ doc.age.should == 21
402
348
  end
403
349
  end
404
-
405
- context "[]=" do
406
- should "write key value for existing key" do
350
+
351
+ context "attributes" do
352
+ should "default to hash with all keys" do
407
353
  doc = @document.new
408
- doc[:name] = 'string'
409
- doc[:name].should == 'string'
354
+ doc.attributes.keys.sort.should == ['_id', 'age', 'name']
410
355
  end
411
-
412
- should "create key and write value for missing key" do
413
- doc = @document.new
414
- doc[:foo] = 'string'
415
- doc.class.keys.include?('foo').should be_true
416
- doc[:foo].should == 'string'
356
+
357
+ should "return all keys with values" do
358
+ doc = @document.new(:name => 'string', :age => nil)
359
+ doc.attributes.keys.sort.should == ['_id', 'age', 'name']
360
+ doc.attributes.values.should include('string')
361
+ doc.attributes.values.should include(nil)
417
362
  end
418
363
 
419
- should "share the new key with the class" do
420
- doc = @document.new
421
- doc[:foo] = 'string'
422
- @document.keys.should include('foo')
423
- end
364
+ should "have indifferent access" do
365
+ doc = @document.new(:name => 'string')
366
+ doc.attributes[:name].should == 'string'
367
+ doc.attributes['name'].should == 'string'
368
+ end
424
369
  end
425
- end
426
370
 
427
- context "reading a key" do
428
- should "work for defined keys" do
429
- doc = @document.new(:name => 'string')
430
- doc.name.should == 'string'
371
+ context "to_mongo" do
372
+ should "default to hash with _id key" do
373
+ doc = @document.new
374
+ doc.to_mongo.keys.sort.should == ['_id', 'age', 'name']
375
+ end
376
+
377
+ should "return all keys" do
378
+ doc = @document.new(:name => 'string', :age => nil)
379
+ doc.to_mongo.keys.sort.should == ['_id', 'age', 'name']
380
+ doc.to_mongo.values.should include('string')
381
+ doc.to_mongo.values.should include(nil)
382
+ end
431
383
  end
432
384
 
433
- should "raise no method error for undefined keys" do
434
- doc = @document.new
435
- lambda { doc.fart }.should raise_error(NoMethodError)
385
+ context "clone" do
386
+ should "regenerate the id" do
387
+ doc = @document.new(:name => "foo", :age => 27)
388
+ doc_id = doc.id
389
+ clone = doc.clone
390
+ clone_id = clone.id
391
+ clone_id.should_not == doc_id
392
+ end
393
+
394
+ should "copy the attributes" do
395
+ doc = @document.new(:name => "foo", :age => 27)
396
+ clone = doc.clone
397
+ clone.name.should == "foo"
398
+ clone.age.should == 27
399
+ end
436
400
  end
437
401
 
438
- should "be accessible for use in the model" do
439
- @document.class_eval do
440
- def name_and_age
441
- "#{self[:name]} (#{self[:age]})"
402
+ context "key shorcut access" do
403
+ context "[]" do
404
+ should "work when key found" do
405
+ doc = @document.new(:name => 'string')
406
+ doc[:name].should == 'string'
407
+ end
408
+
409
+ should "raise exception when key not found" do
410
+ doc = @document.new(:name => 'string')
411
+ assert_raises(MongoMapper::KeyNotFound) { doc[:not_here] }
442
412
  end
443
413
  end
444
414
 
445
- doc = @document.new(:name => 'John', :age => 27)
446
- doc.name_and_age.should == 'John (27)'
447
- end
448
-
449
- should "set instance variable" do
450
- @document.key :foo, Array
451
- doc = @document.new
452
- doc.instance_variable_get("@foo").should be_nil
453
- doc.foo
454
- doc.instance_variable_get("@foo").should == []
455
- end
456
-
457
- should "be overrideable by modules" do
458
- @document = Doc do
459
- key :other_child, String
460
- end
461
-
462
- child = @document.new
463
- child.other_child.should be_nil
464
-
465
- @document.send :include, KeyOverride
466
-
467
- overriden_child = @document.new
468
- overriden_child.other_child.should == 'special result'
469
- end
470
- end
415
+ context "[]=" do
416
+ should "write key value for existing key" do
417
+ doc = @document.new
418
+ doc[:name] = 'string'
419
+ doc[:name].should == 'string'
420
+ end
471
421
 
472
- context "reading a key before typcasting" do
473
- should "work for defined keys" do
474
- doc = @document.new(:name => 12)
475
- doc.name_before_typecast.should == 12
476
- end
422
+ should "create key and write value for missing key" do
423
+ doc = @document.new
424
+ doc[:foo] = 'string'
425
+ doc.class.keys.include?('foo').should be_true
426
+ doc[:foo].should == 'string'
427
+ end
477
428
 
478
- should "raise no method error for undefined keys" do
479
- doc = @document.new
480
- lambda { doc.foo_before_typecast }.should raise_error(NoMethodError)
429
+ should "share the new key with the class" do
430
+ doc = @document.new
431
+ doc[:foo] = 'string'
432
+ @document.keys.should include('foo')
433
+ end
434
+ end
481
435
  end
482
436
 
483
- should "be accessible for use in a document" do
484
- @document.class_eval do
485
- def untypcasted_name
486
- read_key_before_typecast(:name)
437
+ context "reading a key" do
438
+ should "work for defined keys" do
439
+ doc = @document.new(:name => 'string')
440
+ doc.name.should == 'string'
441
+ end
442
+
443
+ should "raise no method error for undefined keys" do
444
+ doc = @document.new
445
+ lambda { doc.fart }.should raise_error(NoMethodError)
446
+ end
447
+
448
+ should "be accessible for use in the model" do
449
+ @document.class_eval do
450
+ def name_and_age
451
+ "#{self[:name]} (#{self[:age]})"
452
+ end
487
453
  end
454
+
455
+ doc = @document.new(:name => 'John', :age => 27)
456
+ doc.name_and_age.should == 'John (27)'
488
457
  end
489
458
 
490
- doc = @document.new(:name => 12)
491
- doc.name.should == '12'
492
- doc.untypcasted_name.should == 12
493
- end
494
- end
459
+ should "set instance variable" do
460
+ @document.key :foo, Array
461
+ doc = @document.new
462
+ doc.instance_variable_get("@foo").should be_nil
463
+ doc.foo
464
+ doc.instance_variable_get("@foo").should == []
465
+ end
495
466
 
496
- context "writing a key" do
497
- should "work for defined keys" do
498
- doc = @document.new
499
- doc.name = 'John'
500
- doc.name.should == 'John'
467
+ should "be overrideable by modules" do
468
+ @document = Doc do
469
+ key :other_child, String
470
+ end
471
+
472
+ child = @document.new
473
+ child.other_child.should be_nil
474
+
475
+ @document.send :include, KeyOverride
476
+
477
+ overriden_child = @document.new
478
+ overriden_child.other_child.should == 'special result'
479
+ end
501
480
  end
502
481
 
503
- should "raise no method error for undefined keys" do
504
- doc = @document.new
505
- lambda { doc.fart = 'poof!' }.should raise_error(NoMethodError)
482
+ context "reading a key before typcasting" do
483
+ should "work for defined keys" do
484
+ doc = @document.new(:name => 12)
485
+ doc.name_before_typecast.should == 12
486
+ end
487
+
488
+ should "raise no method error for undefined keys" do
489
+ doc = @document.new
490
+ lambda { doc.foo_before_typecast }.should raise_error(NoMethodError)
491
+ end
492
+
493
+ should "be accessible for use in a document" do
494
+ @document.class_eval do
495
+ def untypcasted_name
496
+ read_key_before_typecast(:name)
497
+ end
498
+ end
499
+
500
+ doc = @document.new(:name => 12)
501
+ doc.name.should == '12'
502
+ doc.untypcasted_name.should == 12
503
+ end
506
504
  end
507
505
 
508
- should "typecast value" do
509
- doc = @document.new
510
- doc.name = 1234
511
- doc.name.should == '1234'
512
- doc.age = '21'
513
- doc.age.should == 21
514
- end
515
-
516
- should "be accessible for use in the model" do
517
- @document.class_eval do
518
- def name_and_age=(new_value)
519
- new_value.match(/([^\(\s]+) \((.*)\)/)
520
- write_key :name, $1
521
- write_key :age, $2
506
+ context "writing a key" do
507
+ should "work for defined keys" do
508
+ doc = @document.new
509
+ doc.name = 'John'
510
+ doc.name.should == 'John'
511
+ end
512
+
513
+ should "raise no method error for undefined keys" do
514
+ doc = @document.new
515
+ lambda { doc.fart = 'poof!' }.should raise_error(NoMethodError)
516
+ end
517
+
518
+ should "typecast value" do
519
+ doc = @document.new
520
+ doc.name = 1234
521
+ doc.name.should == '1234'
522
+ doc.age = '21'
523
+ doc.age.should == 21
524
+ end
525
+
526
+ should "be accessible for use in the model" do
527
+ @document.class_eval do
528
+ def name_and_age=(new_value)
529
+ new_value.match(/([^\(\s]+) \((.*)\)/)
530
+ write_key :name, $1
531
+ write_key :age, $2
532
+ end
522
533
  end
534
+
535
+ doc = @document.new
536
+ doc.name_and_age = 'Frank (62)'
537
+ doc.name.should == 'Frank'
538
+ doc.age.should == 62
523
539
  end
524
540
 
525
- doc = @document.new
526
- doc.name_and_age = 'Frank (62)'
527
- doc.name.should == 'Frank'
528
- doc.age.should == 62
529
- end
530
-
531
- should "be overrideable by modules" do
532
- @document = Doc do
533
- key :other_child, String
534
- end
535
-
536
- child = @document.new(:other_child => 'foo')
537
- child.other_child.should == 'foo'
538
-
539
- @document.send :include, KeyOverride
540
-
541
- overriden_child = @document.new(:other_child => 'foo')
542
- overriden_child.other_child.should == 'foo modified'
543
- end
544
- end # writing a key
545
-
546
- context "checking if a keys value is present" do
547
- should "work for defined keys" do
548
- doc = @document.new
549
- doc.name?.should be_false
550
- doc.name = 'John'
551
- doc.name?.should be_true
552
- end
553
-
554
- should "raise no method error for undefined keys" do
555
- doc = @document.new
556
- lambda { doc.fart? }.should raise_error(NoMethodError)
557
- end
558
- end
559
-
560
- should "call inspect on the document's attributes instead of to_s when inspecting the document" do
561
- doc = @document.new(:animals => %w(dog cat))
562
- doc.inspect.should include(%(animals: ["dog", "cat"]))
563
- end
564
-
565
- context "equality" do
566
- setup do
567
- @oid = Mongo::ObjectID.new
568
- end
569
-
570
- should "delegate hash to _id" do
571
- doc = @document.new
572
- doc.hash.should == doc._id.hash
573
- end
574
-
575
- should "delegate eql to ==" do
576
- doc = @document.new
577
- other = @document.new
578
- doc.eql?(other).should == (doc == other)
579
- doc.eql?(doc).should == (doc == doc)
580
- end
581
-
582
- should "know if same object as another" do
583
- doc = @document.new
584
- doc.should equal(doc)
585
- doc.should_not equal(@document.new)
586
- end
587
-
588
- should "allow set operations on array of documents" do
589
- doc = @document.new
590
- ([doc] & [doc]).should == [doc]
591
- end
592
-
593
- should "be equal if id and class are the same" do
594
- (@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be_true
595
- end
541
+ should "be overrideable by modules" do
542
+ @document = Doc do
543
+ key :other_child, String
544
+ end
596
545
 
597
- should "not be equal if class same but id different" do
598
- (@document.new('_id' => @oid) == @document.new('_id' => Mongo::ObjectID.new)).should be_false
599
- end
546
+ child = @document.new(:other_child => 'foo')
547
+ child.other_child.should == 'foo'
600
548
 
601
- should "not be equal if id same but class different" do
602
- another_document = Doc()
603
- (@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be_false
604
- end
605
- end
606
-
607
- context "reading keys with default values" do
608
- setup do
609
- @document = EDoc do
610
- key :name, String, :default => 'foo'
611
- key :age, Integer, :default => 20
612
- key :net_worth, Float, :default => 100.00
613
- key :active, Boolean, :default => true
614
- key :smart, Boolean, :default => false
615
- key :skills, Array, :default => [1]
616
- key :options, Hash, :default => {'foo' => 'bar'}
549
+ @document.send :include, KeyOverride
550
+
551
+ overriden_child = @document.new(:other_child => 'foo')
552
+ overriden_child.other_child.should == 'foo modified'
617
553
  end
554
+ end # writing a key
618
555
 
619
- @doc = @document.new
620
- end
556
+ context "checking if a keys value is present" do
557
+ should "work for defined keys" do
558
+ doc = @document.new
559
+ doc.name?.should be_false
560
+ doc.name = 'John'
561
+ doc.name?.should be_true
562
+ end
621
563
 
622
- should "work for strings" do
623
- @doc.name.should == 'foo'
564
+ should "raise no method error for undefined keys" do
565
+ doc = @document.new
566
+ lambda { doc.fart? }.should raise_error(NoMethodError)
567
+ end
624
568
  end
625
569
 
626
- should "work for integers" do
627
- @doc.age.should == 20
570
+ should "call inspect on the document's attributes instead of to_s when inspecting the document" do
571
+ doc = @document.new(:animals => %w(dog cat))
572
+ doc.inspect.should include(%(animals: ["dog", "cat"]))
628
573
  end
629
574
 
630
- should "work for floats" do
631
- @doc.net_worth.should == 100.00
632
- end
575
+ context "equality" do
576
+ setup do
577
+ @oid = Mongo::ObjectID.new
578
+ end
633
579
 
634
- should "work for booleans" do
635
- @doc.active.should == true
636
- @doc.smart.should == false
637
- end
580
+ should "delegate hash to _id" do
581
+ doc = @document.new
582
+ doc.hash.should == doc._id.hash
583
+ end
584
+
585
+ should "delegate eql to ==" do
586
+ doc = @document.new
587
+ other = @document.new
588
+ doc.eql?(other).should == (doc == other)
589
+ doc.eql?(doc).should == (doc == doc)
590
+ end
591
+
592
+ should "know if same object as another" do
593
+ doc = @document.new
594
+ doc.should equal(doc)
595
+ doc.should_not equal(@document.new)
596
+ end
638
597
 
639
- should "work for arrays" do
640
- @doc.skills.should == [1]
641
- @doc.skills << 2
642
- @doc.skills.should == [1, 2]
598
+ should "allow set operations on array of documents" do
599
+ doc = @document.new
600
+ ([doc] & [doc]).should == [doc]
601
+ end
602
+
603
+ should "be equal if id and class are the same" do
604
+ (@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be_true
605
+ end
606
+
607
+ should "not be equal if class same but id different" do
608
+ (@document.new('_id' => @oid) == @document.new('_id' => Mongo::ObjectID.new)).should be_false
609
+ end
610
+
611
+ should "not be equal if id same but class different" do
612
+ another_document = Doc()
613
+ (@document.new('_id' => @oid) == another_document.new('_id' => @oid)).should be_false
614
+ end
643
615
  end
644
616
 
645
- should "work for hashes" do
646
- @doc.options['foo'].should == 'bar'
647
- @doc.options['baz'] = 'wick'
648
- @doc.options['baz'].should == 'wick'
617
+ context "reading keys with default values" do
618
+ setup do
619
+ @document = EDoc do
620
+ key :name, String, :default => 'foo'
621
+ key :age, Integer, :default => 20
622
+ key :net_worth, Float, :default => 100.00
623
+ key :active, Boolean, :default => true
624
+ key :smart, Boolean, :default => false
625
+ key :skills, Array, :default => [1]
626
+ key :options, Hash, :default => {'foo' => 'bar'}
627
+ end
628
+
629
+ @doc = @document.new
630
+ end
631
+
632
+ should "work for strings" do
633
+ @doc.name.should == 'foo'
634
+ end
635
+
636
+ should "work for integers" do
637
+ @doc.age.should == 20
638
+ end
639
+
640
+ should "work for floats" do
641
+ @doc.net_worth.should == 100.00
642
+ end
643
+
644
+ should "work for booleans" do
645
+ @doc.active.should == true
646
+ @doc.smart.should == false
647
+ end
648
+
649
+ should "work for arrays" do
650
+ @doc.skills.should == [1]
651
+ @doc.skills << 2
652
+ @doc.skills.should == [1, 2]
653
+ end
654
+
655
+ should "work for hashes" do
656
+ @doc.options['foo'].should == 'bar'
657
+ @doc.options['baz'] = 'wick'
658
+ @doc.options['baz'].should == 'wick'
659
+ end
649
660
  end
650
- end
651
- end # instance of a embedded document
661
+ end # instance of a embedded document
662
+ end
652
663
  end