mongo_mapper-unstable 2010.1.27 → 2010.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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