mongo-find_replace 0.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. data/LICENSE.txt +202 -0
  2. data/README.rdoc +358 -0
  3. data/Rakefile +133 -0
  4. data/bin/bson_benchmark.rb +59 -0
  5. data/bin/fail_if_no_c.rb +11 -0
  6. data/examples/admin.rb +42 -0
  7. data/examples/capped.rb +22 -0
  8. data/examples/cursor.rb +48 -0
  9. data/examples/gridfs.rb +88 -0
  10. data/examples/index_test.rb +126 -0
  11. data/examples/info.rb +31 -0
  12. data/examples/queries.rb +70 -0
  13. data/examples/simple.rb +24 -0
  14. data/examples/strict.rb +35 -0
  15. data/examples/types.rb +36 -0
  16. data/lib/mongo.rb +61 -0
  17. data/lib/mongo/admin.rb +95 -0
  18. data/lib/mongo/collection.rb +664 -0
  19. data/lib/mongo/connection.rb +555 -0
  20. data/lib/mongo/cursor.rb +393 -0
  21. data/lib/mongo/db.rb +527 -0
  22. data/lib/mongo/exceptions.rb +60 -0
  23. data/lib/mongo/gridfs.rb +22 -0
  24. data/lib/mongo/gridfs/chunk.rb +90 -0
  25. data/lib/mongo/gridfs/grid_store.rb +555 -0
  26. data/lib/mongo/types/binary.rb +48 -0
  27. data/lib/mongo/types/code.rb +36 -0
  28. data/lib/mongo/types/dbref.rb +38 -0
  29. data/lib/mongo/types/min_max_keys.rb +58 -0
  30. data/lib/mongo/types/objectid.rb +219 -0
  31. data/lib/mongo/types/regexp_of_holding.rb +45 -0
  32. data/lib/mongo/util/bson_c.rb +18 -0
  33. data/lib/mongo/util/bson_ruby.rb +595 -0
  34. data/lib/mongo/util/byte_buffer.rb +222 -0
  35. data/lib/mongo/util/conversions.rb +97 -0
  36. data/lib/mongo/util/ordered_hash.rb +135 -0
  37. data/lib/mongo/util/server_version.rb +69 -0
  38. data/lib/mongo/util/support.rb +26 -0
  39. data/lib/mongo/util/xml_to_ruby.rb +112 -0
  40. data/mongo-ruby-driver.gemspec +28 -0
  41. data/test/replica/count_test.rb +34 -0
  42. data/test/replica/insert_test.rb +50 -0
  43. data/test/replica/pooled_insert_test.rb +54 -0
  44. data/test/replica/query_test.rb +39 -0
  45. data/test/test_admin.rb +67 -0
  46. data/test/test_bson.rb +397 -0
  47. data/test/test_byte_buffer.rb +81 -0
  48. data/test/test_chunk.rb +82 -0
  49. data/test/test_collection.rb +534 -0
  50. data/test/test_connection.rb +160 -0
  51. data/test/test_conversions.rb +120 -0
  52. data/test/test_cursor.rb +386 -0
  53. data/test/test_db.rb +254 -0
  54. data/test/test_db_api.rb +783 -0
  55. data/test/test_db_connection.rb +16 -0
  56. data/test/test_grid_store.rb +306 -0
  57. data/test/test_helper.rb +42 -0
  58. data/test/test_objectid.rb +156 -0
  59. data/test/test_ordered_hash.rb +168 -0
  60. data/test/test_round_trip.rb +114 -0
  61. data/test/test_slave_connection.rb +36 -0
  62. data/test/test_threading.rb +87 -0
  63. data/test/threading/test_threading_large_pool.rb +90 -0
  64. data/test/unit/collection_test.rb +52 -0
  65. data/test/unit/connection_test.rb +59 -0
  66. data/test/unit/cursor_test.rb +94 -0
  67. data/test/unit/db_test.rb +97 -0
  68. metadata +123 -0
@@ -0,0 +1,18 @@
1
+ # A thin wrapper for the CBson class
2
+ class BSON_C
3
+
4
+ def self.serialize(obj, check_keys=false)
5
+ ByteBuffer.new(CBson.serialize(obj, check_keys))
6
+ end
7
+
8
+ def self.deserialize(buf=nil)
9
+ if buf.is_a? String
10
+ to_deserialize = ByteBuffer.new(buf) if buf
11
+ else
12
+ buf = ByteBuffer.new(buf.to_a) if buf
13
+ end
14
+ buf.rewind
15
+ CBson.deserialize(buf.to_s)
16
+ end
17
+
18
+ end
@@ -0,0 +1,595 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'base64'
18
+ require 'mongo/util/byte_buffer'
19
+ require 'mongo/util/ordered_hash'
20
+ require 'mongo/types/binary'
21
+ require 'mongo/types/dbref'
22
+ require 'mongo/types/objectid'
23
+ require 'mongo/types/regexp_of_holding'
24
+
25
+ # A BSON seralizer/deserializer in pure Ruby.
26
+ class BSON_RUBY
27
+
28
+ include Mongo
29
+
30
+ MINKEY = -1
31
+ EOO = 0
32
+ NUMBER = 1
33
+ STRING = 2
34
+ OBJECT = 3
35
+ ARRAY = 4
36
+ BINARY = 5
37
+ UNDEFINED = 6
38
+ OID = 7
39
+ BOOLEAN = 8
40
+ DATE = 9
41
+ NULL = 10
42
+ REGEX = 11
43
+ REF = 12
44
+ CODE = 13
45
+ SYMBOL = 14
46
+ CODE_W_SCOPE = 15
47
+ NUMBER_INT = 16
48
+ TIMESTAMP = 17
49
+ NUMBER_LONG = 18
50
+ MAXKEY = 127
51
+
52
+ def initialize
53
+ @buf = ByteBuffer.new
54
+ end
55
+
56
+ if RUBY_VERSION >= '1.9'
57
+ def self.to_utf8(str)
58
+ str.encode("utf-8")
59
+ end
60
+ else
61
+ def self.to_utf8(str)
62
+ begin
63
+ str.unpack("U*")
64
+ rescue => ex
65
+ raise InvalidStringEncoding, "String not valid utf-8: #{str}"
66
+ end
67
+ str
68
+ end
69
+ end
70
+
71
+ def self.serialize_cstr(buf, val)
72
+ buf.put_array(to_utf8(val.to_s).unpack("C*") << 0)
73
+ end
74
+
75
+ def self.serialize_key(buf, key)
76
+ raise InvalidDocument, "Key names / regex patterns must not contain the NULL byte" if key.include? "\x00"
77
+ self.serialize_cstr(buf, key)
78
+ end
79
+
80
+ def to_a
81
+ @buf.to_a
82
+ end
83
+
84
+ def to_s
85
+ @buf.to_s
86
+ end
87
+
88
+ # Serializes an object.
89
+ # Implemented to ensure an API compatible with BSON extension.
90
+ def self.serialize(obj, check_keys=false)
91
+ new.serialize(obj, check_keys)
92
+ end
93
+
94
+ def self.deserialize(buf=nil)
95
+ new.deserialize(buf)
96
+ end
97
+
98
+ def serialize(obj, check_keys=false)
99
+ raise "Document is null" unless obj
100
+
101
+ @buf.rewind
102
+ # put in a placeholder for the total size
103
+ @buf.put_int(0)
104
+
105
+ # Write key/value pairs. Always write _id first if it exists.
106
+ if obj.has_key? '_id'
107
+ serialize_key_value('_id', obj['_id'], check_keys)
108
+ elsif obj.has_key? :_id
109
+ serialize_key_value('_id', obj[:_id], check_keys)
110
+ end
111
+
112
+ obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id }
113
+
114
+ serialize_eoo_element(@buf)
115
+ if @buf.size > 4 * 1024 * 1024
116
+ raise InvalidDocument, "Document is too large (#{@buf.size}). BSON documents are limited to 4MB (#{4 * 1024 * 1024})."
117
+ end
118
+ @buf.put_int(@buf.size, 0)
119
+ self
120
+ end
121
+
122
+ # Returns the array stored in the buffer.
123
+ # Implemented to ensure an API compatible with BSON extension.
124
+ def unpack(arg)
125
+ @buf.to_a
126
+ end
127
+
128
+ def serialize_key_value(k, v, check_keys)
129
+ k = k.to_s
130
+ if check_keys
131
+ if k[0] == ?$
132
+ raise InvalidName.new("key #{k} must not start with '$'")
133
+ end
134
+ if k.include? ?.
135
+ raise InvalidName.new("key #{k} must not contain '.'")
136
+ end
137
+ end
138
+ type = bson_type(v)
139
+ case type
140
+ when STRING, SYMBOL
141
+ serialize_string_element(@buf, k, v, type)
142
+ when NUMBER, NUMBER_INT
143
+ serialize_number_element(@buf, k, v, type)
144
+ when OBJECT
145
+ serialize_object_element(@buf, k, v, check_keys)
146
+ when OID
147
+ serialize_oid_element(@buf, k, v)
148
+ when ARRAY
149
+ serialize_array_element(@buf, k, v, check_keys)
150
+ when REGEX
151
+ serialize_regex_element(@buf, k, v)
152
+ when BOOLEAN
153
+ serialize_boolean_element(@buf, k, v)
154
+ when DATE
155
+ serialize_date_element(@buf, k, v)
156
+ when NULL
157
+ serialize_null_element(@buf, k)
158
+ when REF
159
+ serialize_dbref_element(@buf, k, v)
160
+ when BINARY
161
+ serialize_binary_element(@buf, k, v)
162
+ when UNDEFINED
163
+ serialize_null_element(@buf, k)
164
+ when CODE_W_SCOPE
165
+ serialize_code_w_scope(@buf, k, v)
166
+ when MAXKEY
167
+ serialize_max_key_element(@buf, k)
168
+ when MINKEY
169
+ serialize_min_key_element(@buf, k)
170
+ else
171
+ raise "unhandled type #{type}"
172
+ end
173
+ end
174
+
175
+ def deserialize(buf=nil)
176
+ # If buf is nil, use @buf, assumed to contain already-serialized BSON.
177
+ # This is only true during testing.
178
+ if buf.is_a? String
179
+ @buf = ByteBuffer.new(buf) if buf
180
+ else
181
+ @buf = ByteBuffer.new(buf.to_a) if buf
182
+ end
183
+ @buf.rewind
184
+ @buf.get_int # eat message size
185
+ doc = OrderedHash.new
186
+ while @buf.more?
187
+ type = @buf.get
188
+ case type
189
+ when STRING, CODE
190
+ key = deserialize_cstr(@buf)
191
+ doc[key] = deserialize_string_data(@buf)
192
+ when SYMBOL
193
+ key = deserialize_cstr(@buf)
194
+ doc[key] = deserialize_string_data(@buf).intern
195
+ when NUMBER
196
+ key = deserialize_cstr(@buf)
197
+ doc[key] = deserialize_number_data(@buf)
198
+ when NUMBER_INT
199
+ key = deserialize_cstr(@buf)
200
+ doc[key] = deserialize_number_int_data(@buf)
201
+ when NUMBER_LONG
202
+ key = deserialize_cstr(@buf)
203
+ doc[key] = deserialize_number_long_data(@buf)
204
+ when OID
205
+ key = deserialize_cstr(@buf)
206
+ doc[key] = deserialize_oid_data(@buf)
207
+ when ARRAY
208
+ key = deserialize_cstr(@buf)
209
+ doc[key] = deserialize_array_data(@buf)
210
+ when REGEX
211
+ key = deserialize_cstr(@buf)
212
+ doc[key] = deserialize_regex_data(@buf)
213
+ when OBJECT
214
+ key = deserialize_cstr(@buf)
215
+ doc[key] = deserialize_object_data(@buf)
216
+ when BOOLEAN
217
+ key = deserialize_cstr(@buf)
218
+ doc[key] = deserialize_boolean_data(@buf)
219
+ when DATE
220
+ key = deserialize_cstr(@buf)
221
+ doc[key] = deserialize_date_data(@buf)
222
+ when NULL
223
+ key = deserialize_cstr(@buf)
224
+ doc[key] = nil
225
+ when UNDEFINED
226
+ key = deserialize_cstr(@buf)
227
+ doc[key] = nil
228
+ when REF
229
+ key = deserialize_cstr(@buf)
230
+ doc[key] = deserialize_dbref_data(@buf)
231
+ when BINARY
232
+ key = deserialize_cstr(@buf)
233
+ doc[key] = deserialize_binary_data(@buf)
234
+ when CODE_W_SCOPE
235
+ key = deserialize_cstr(@buf)
236
+ doc[key] = deserialize_code_w_scope_data(@buf)
237
+ when TIMESTAMP
238
+ key = deserialize_cstr(@buf)
239
+ doc[key] = [deserialize_number_int_data(@buf),
240
+ deserialize_number_int_data(@buf)]
241
+ when MAXKEY
242
+ key = deserialize_cstr(@buf)
243
+ doc[key] = MaxKey.new
244
+ when MINKEY, 255 # This is currently easier than unpack the type byte as an unsigned char.
245
+ key = deserialize_cstr(@buf)
246
+ doc[key] = MinKey.new
247
+ when EOO
248
+ break
249
+ else
250
+ raise "Unknown type #{type}, key = #{key}"
251
+ end
252
+ end
253
+ @buf.rewind
254
+ doc
255
+ end
256
+
257
+ # For debugging.
258
+ def hex_dump
259
+ str = ''
260
+ @buf.to_a.each_with_index { |b,i|
261
+ if (i % 8) == 0
262
+ str << "\n" if i > 0
263
+ str << '%4d: ' % i
264
+ else
265
+ str << ' '
266
+ end
267
+ str << '%02X' % b
268
+ }
269
+ str
270
+ end
271
+
272
+ def deserialize_date_data(buf)
273
+ unsigned = buf.get_long()
274
+ # see note for deserialize_number_long_data below
275
+ milliseconds = unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned
276
+ Time.at(milliseconds.to_f / 1000.0).utc # at() takes fractional seconds
277
+ end
278
+
279
+ def deserialize_boolean_data(buf)
280
+ buf.get == 1
281
+ end
282
+
283
+ def deserialize_number_data(buf)
284
+ buf.get_double
285
+ end
286
+
287
+ def deserialize_number_int_data(buf)
288
+ # sometimes ruby makes me angry... why would the same code pack as signed
289
+ # but unpack as unsigned
290
+ unsigned = buf.get_int
291
+ unsigned >= 2**32 / 2 ? unsigned - 2**32 : unsigned
292
+ end
293
+
294
+ def deserialize_number_long_data(buf)
295
+ # same note as above applies here...
296
+ unsigned = buf.get_long
297
+ unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned
298
+ end
299
+
300
+ def deserialize_object_data(buf)
301
+ size = buf.get_int
302
+ buf.position -= 4
303
+ object = BSON.new().deserialize(buf.get(size))
304
+ if object.has_key? "$ref"
305
+ DBRef.new(object["$ref"], object["$id"])
306
+ else
307
+ object
308
+ end
309
+ end
310
+
311
+ def deserialize_array_data(buf)
312
+ h = deserialize_object_data(buf)
313
+ a = []
314
+ h.each { |k, v| a[k.to_i] = v }
315
+ a
316
+ end
317
+
318
+ def deserialize_regex_data(buf)
319
+ str = deserialize_cstr(buf)
320
+ options_str = deserialize_cstr(buf)
321
+ options = 0
322
+ options |= Regexp::IGNORECASE if options_str.include?('i')
323
+ options |= Regexp::MULTILINE if options_str.include?('m')
324
+ options |= Regexp::EXTENDED if options_str.include?('x')
325
+ options_str.gsub!(/[imx]/, '') # Now remove the three we understand
326
+ RegexpOfHolding.new(str, options, options_str)
327
+ end
328
+
329
+ def deserialize_string_data(buf)
330
+ len = buf.get_int
331
+ bytes = buf.get(len)
332
+ str = bytes[0..-2]
333
+ if str.respond_to? "pack"
334
+ str = str.pack("C*")
335
+ end
336
+ if RUBY_VERSION >= '1.9'
337
+ str.force_encoding("utf-8")
338
+ end
339
+ str
340
+ end
341
+
342
+ def deserialize_code_w_scope_data(buf)
343
+ buf.get_int
344
+ len = buf.get_int
345
+ code = buf.get(len)[0..-2]
346
+ if code.respond_to? "pack"
347
+ code = code.pack("C*")
348
+ end
349
+ if RUBY_VERSION >= '1.9'
350
+ code.force_encoding("utf-8")
351
+ end
352
+
353
+ scope_size = buf.get_int
354
+ buf.position -= 4
355
+ scope = BSON.new().deserialize(buf.get(scope_size))
356
+
357
+ Code.new(code, scope)
358
+ end
359
+
360
+ def deserialize_oid_data(buf)
361
+ ObjectID.new(buf.get(12))
362
+ end
363
+
364
+ def deserialize_dbref_data(buf)
365
+ ns = deserialize_string_data(buf)
366
+ oid = deserialize_oid_data(buf)
367
+ DBRef.new(ns, oid)
368
+ end
369
+
370
+ def deserialize_binary_data(buf)
371
+ len = buf.get_int
372
+ type = buf.get
373
+ len = buf.get_int if type == Binary::SUBTYPE_BYTES
374
+ Binary.new(buf.get(len), type)
375
+ end
376
+
377
+ def serialize_eoo_element(buf)
378
+ buf.put(EOO)
379
+ end
380
+
381
+ def serialize_null_element(buf, key)
382
+ buf.put(NULL)
383
+ self.class.serialize_key(buf, key)
384
+ end
385
+
386
+ def serialize_dbref_element(buf, key, val)
387
+ oh = OrderedHash.new
388
+ oh['$ref'] = val.namespace
389
+ oh['$id'] = val.object_id
390
+ serialize_object_element(buf, key, oh, false)
391
+ end
392
+
393
+ def serialize_binary_element(buf, key, val)
394
+ buf.put(BINARY)
395
+ self.class.serialize_key(buf, key)
396
+
397
+ bytes = val.to_a
398
+ num_bytes = bytes.length
399
+ subtype = val.respond_to?(:subtype) ? val.subtype : Binary::SUBTYPE_BYTES
400
+ if subtype == Binary::SUBTYPE_BYTES
401
+ buf.put_int(num_bytes + 4)
402
+ buf.put(subtype)
403
+ buf.put_int(num_bytes)
404
+ buf.put_array(bytes)
405
+ else
406
+ buf.put_int(num_bytes)
407
+ buf.put(subtype)
408
+ buf.put_array(bytes)
409
+ end
410
+ end
411
+
412
+ def serialize_boolean_element(buf, key, val)
413
+ buf.put(BOOLEAN)
414
+ self.class.serialize_key(buf, key)
415
+ buf.put(val ? 1 : 0)
416
+ end
417
+
418
+ def serialize_date_element(buf, key, val)
419
+ buf.put(DATE)
420
+ self.class.serialize_key(buf, key)
421
+ millisecs = (val.to_f * 1000).to_i
422
+ buf.put_long(millisecs)
423
+ end
424
+
425
+ def serialize_number_element(buf, key, val, type)
426
+ if type == NUMBER
427
+ buf.put(type)
428
+ self.class.serialize_key(buf, key)
429
+ buf.put_double(val)
430
+ else
431
+ if val > 2**64 / 2 - 1 or val < -2**64 / 2
432
+ raise RangeError.new("MongoDB can only handle 8-byte ints")
433
+ end
434
+ if val > 2**32 / 2 - 1 or val < -2**32 / 2
435
+ buf.put(NUMBER_LONG)
436
+ self.class.serialize_key(buf, key)
437
+ buf.put_long(val)
438
+ else
439
+ buf.put(type)
440
+ self.class.serialize_key(buf, key)
441
+ buf.put_int(val)
442
+ end
443
+ end
444
+ end
445
+
446
+ def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT)
447
+ buf.put(opcode)
448
+ self.class.serialize_key(buf, key)
449
+ buf.put_array(BSON.new.serialize(val, check_keys).to_a)
450
+ end
451
+
452
+ def serialize_array_element(buf, key, val, check_keys)
453
+ # Turn array into hash with integer indices as keys
454
+ h = OrderedHash.new
455
+ i = 0
456
+ val.each { |v| h[i] = v; i += 1 }
457
+ serialize_object_element(buf, key, h, check_keys, ARRAY)
458
+ end
459
+
460
+ def serialize_regex_element(buf, key, val)
461
+ buf.put(REGEX)
462
+ self.class.serialize_key(buf, key)
463
+
464
+ str = val.source
465
+ # We use serialize_key here since regex patterns aren't prefixed with
466
+ # length (can't contain the NULL byte).
467
+ self.class.serialize_key(buf, str)
468
+
469
+ options = val.options
470
+ options_str = ''
471
+ options_str << 'i' if ((options & Regexp::IGNORECASE) != 0)
472
+ options_str << 'm' if ((options & Regexp::MULTILINE) != 0)
473
+ options_str << 'x' if ((options & Regexp::EXTENDED) != 0)
474
+ options_str << val.extra_options_str if val.respond_to?(:extra_options_str)
475
+ # Must store option chars in alphabetical order
476
+ self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join)
477
+ end
478
+
479
+ def serialize_max_key_element(buf, key)
480
+ buf.put(MAXKEY)
481
+ self.class.serialize_key(buf, key)
482
+ end
483
+
484
+ def serialize_min_key_element(buf, key)
485
+ buf.put(MINKEY)
486
+ self.class.serialize_key(buf, key)
487
+ end
488
+
489
+ def serialize_oid_element(buf, key, val)
490
+ buf.put(OID)
491
+ self.class.serialize_key(buf, key)
492
+
493
+ buf.put_array(val.to_a)
494
+ end
495
+
496
+ def serialize_string_element(buf, key, val, type)
497
+ buf.put(type)
498
+ self.class.serialize_key(buf, key)
499
+
500
+ # Make a hole for the length
501
+ len_pos = buf.position
502
+ buf.put_int(0)
503
+
504
+ # Save the string
505
+ start_pos = buf.position
506
+ self.class.serialize_cstr(buf, val)
507
+ end_pos = buf.position
508
+
509
+ # Put the string size in front
510
+ buf.put_int(end_pos - start_pos, len_pos)
511
+
512
+ # Go back to where we were
513
+ buf.position = end_pos
514
+ end
515
+
516
+ def serialize_code_w_scope(buf, key, val)
517
+ buf.put(CODE_W_SCOPE)
518
+ self.class.serialize_key(buf, key)
519
+
520
+ # Make a hole for the length
521
+ len_pos = buf.position
522
+ buf.put_int(0)
523
+
524
+ buf.put_int(val.length + 1)
525
+ self.class.serialize_cstr(buf, val)
526
+ buf.put_array(BSON.new.serialize(val.scope).to_a)
527
+
528
+ end_pos = buf.position
529
+ buf.put_int(end_pos - len_pos, len_pos)
530
+ buf.position = end_pos
531
+ end
532
+
533
+ def deserialize_cstr(buf)
534
+ chars = ""
535
+ while true
536
+ b = buf.get
537
+ break if b == 0
538
+ chars << b.chr
539
+ end
540
+ if RUBY_VERSION >= '1.9'
541
+ chars.force_encoding("utf-8") # Mongo stores UTF-8
542
+ end
543
+ chars
544
+ end
545
+
546
+ def bson_type(o)
547
+ case o
548
+ when nil
549
+ NULL
550
+ when Integer
551
+ NUMBER_INT
552
+ when Float
553
+ NUMBER
554
+ when ByteBuffer
555
+ BINARY
556
+ when Code
557
+ CODE_W_SCOPE
558
+ when String
559
+ STRING
560
+ when Array
561
+ ARRAY
562
+ when Regexp
563
+ REGEX
564
+ when ObjectID
565
+ OID
566
+ when DBRef
567
+ REF
568
+ when true, false
569
+ BOOLEAN
570
+ when Time
571
+ DATE
572
+ when Hash
573
+ OBJECT
574
+ when Symbol
575
+ SYMBOL
576
+ when MaxKey
577
+ MAXKEY
578
+ when MinKey
579
+ MINKEY
580
+ when Numeric
581
+ raise InvalidDocument, "Cannot serialize the Numeric type #{o.class} as BSON; only Fixum, Bignum, and Float are supported."
582
+ when Date, DateTime
583
+ raise InvalidDocument, "#{o.class} is not currently supported; " +
584
+ "use a UTC Time instance instead."
585
+ else
586
+ if defined?(ActiveSupport::TimeWithZone) && o.is_a?(ActiveSupport::TimeWithZone)
587
+ raise InvalidDocument, "ActiveSupport::TimeWithZone is not currently supported; " +
588
+ "use a UTC Time instance instead."
589
+ else
590
+ raise InvalidDocument, "Cannot serialize #{o.class} as a BSON type; it either isn't supported or won't translate to BSON."
591
+ end
592
+ end
593
+ end
594
+
595
+ end