bson 1.12.5-java → 2.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bson might be problematic. Click here for more details.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +80 -0
- data/CONTRIBUTING.md +42 -0
- data/NOTICE +2 -0
- data/README.md +190 -0
- data/Rakefile +109 -0
- data/lib/bson-ruby.jar +0 -0
- data/lib/bson.rb +60 -87
- data/lib/bson/array.rb +104 -0
- data/lib/bson/binary.rb +193 -0
- data/lib/bson/boolean.rb +48 -0
- data/lib/bson/code.rb +109 -0
- data/lib/bson/code_with_scope.rb +120 -0
- data/lib/bson/document.rb +549 -0
- data/lib/bson/encodable.rb +86 -0
- data/lib/bson/environment.rb +98 -0
- data/lib/bson/false_class.rb +61 -0
- data/lib/bson/float.rb +82 -0
- data/lib/bson/hash.rb +84 -0
- data/lib/bson/int32.rb +59 -0
- data/lib/bson/int64.rb +59 -0
- data/lib/bson/integer.rb +185 -0
- data/lib/bson/json.rb +37 -0
- data/lib/bson/max_key.rb +70 -0
- data/lib/bson/min_key.rb +70 -0
- data/lib/bson/nil_class.rb +70 -0
- data/lib/bson/object_id.rb +395 -0
- data/lib/bson/regexp.rb +124 -0
- data/lib/bson/registry.rb +70 -0
- data/lib/bson/specialized.rb +74 -0
- data/lib/bson/string.rb +203 -0
- data/lib/bson/symbol.rb +87 -0
- data/lib/bson/time.rb +72 -0
- data/lib/bson/timestamp.rb +113 -0
- data/lib/bson/true_class.rb +61 -0
- data/lib/bson/undefined.rb +74 -0
- data/lib/bson/version.rb +17 -0
- data/spec/bson/array_spec.rb +58 -0
- data/spec/bson/binary_spec.rb +115 -0
- data/spec/bson/boolean_spec.rb +48 -0
- data/spec/bson/code_spec.rb +42 -0
- data/spec/bson/code_with_scope_spec.rb +74 -0
- data/spec/bson/document_spec.rb +778 -0
- data/spec/bson/false_class_spec.rb +28 -0
- data/spec/bson/float_spec.rb +29 -0
- data/spec/bson/hash_spec.rb +56 -0
- data/spec/bson/int32_spec.rb +28 -0
- data/spec/bson/int64_spec.rb +28 -0
- data/spec/bson/integer_spec.rb +76 -0
- data/spec/bson/json_spec.rb +53 -0
- data/spec/bson/max_key_spec.rb +75 -0
- data/spec/bson/min_key_spec.rb +75 -0
- data/spec/bson/nil_class_spec.rb +29 -0
- data/spec/bson/object_id_spec.rb +527 -0
- data/spec/bson/regexp_spec.rb +89 -0
- data/spec/bson/registry_spec.rb +55 -0
- data/spec/bson/string_spec.rb +298 -0
- data/spec/bson/symbol_spec.rb +55 -0
- data/spec/bson/time_spec.rb +43 -0
- data/spec/bson/timestamp_spec.rb +74 -0
- data/spec/bson/true_class_spec.rb +28 -0
- data/spec/bson/undefined_spec.rb +29 -0
- data/{lib/bson/types/dbref.rb → spec/bson_spec.rb} +22 -16
- data/spec/spec_helper.rb +32 -0
- data/spec/support/shared_examples.rb +95 -0
- metadata +116 -48
- metadata.gz.sig +1 -1
- data/VERSION +0 -1
- data/bin/b2json +0 -63
- data/bin/j2bson +0 -64
- data/bson.gemspec +0 -34
- data/ext/jbson/lib/java-bson.jar +0 -0
- data/ext/jbson/target/jbson.jar +0 -0
- data/lib/bson/bson_c.rb +0 -37
- data/lib/bson/bson_java.rb +0 -49
- data/lib/bson/bson_ruby.rb +0 -645
- data/lib/bson/byte_buffer.rb +0 -241
- data/lib/bson/exceptions.rb +0 -37
- data/lib/bson/grow.rb +0 -173
- data/lib/bson/ordered_hash.rb +0 -197
- data/lib/bson/support/hash_with_indifferent_access.rb +0 -174
- data/lib/bson/types/binary.rb +0 -52
- data/lib/bson/types/code.rb +0 -55
- data/lib/bson/types/min_max_keys.rb +0 -56
- data/lib/bson/types/object_id.rb +0 -226
- data/lib/bson/types/regex.rb +0 -116
- data/lib/bson/types/timestamp.rb +0 -72
@@ -0,0 +1,120 @@
|
|
1
|
+
# Copyright (C) 2009-2013 MongoDB Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module BSON
|
16
|
+
|
17
|
+
# Represents a code with scope, which is a wrapper around javascript code
|
18
|
+
# with variable scope provided.
|
19
|
+
#
|
20
|
+
# @see http://bsonspec.org/#/specification
|
21
|
+
#
|
22
|
+
# @since 2.0.0
|
23
|
+
class CodeWithScope
|
24
|
+
include Encodable
|
25
|
+
include JSON
|
26
|
+
|
27
|
+
# A code with scope is type 0x0F in the BSON spec.
|
28
|
+
#
|
29
|
+
# @since 2.0.0
|
30
|
+
BSON_TYPE = 15.chr.force_encoding(BINARY).freeze
|
31
|
+
|
32
|
+
# @!attribute javascript
|
33
|
+
# @return [ String ] The javascript code.
|
34
|
+
# @since 2.0.0
|
35
|
+
# @!attribute scope
|
36
|
+
# @return [ Hash ] The variable scope.
|
37
|
+
# @since 2.0.0
|
38
|
+
attr_reader :javascript, :scope
|
39
|
+
|
40
|
+
# Determine if this code with scope object is equal to another object.
|
41
|
+
#
|
42
|
+
# @example Check the code with scope equality.
|
43
|
+
# code_with_scope == other
|
44
|
+
#
|
45
|
+
# @param [ Object ] other The object to compare against.
|
46
|
+
#
|
47
|
+
# @return [ true, false ] If the objects are equal.
|
48
|
+
#
|
49
|
+
# @since 2.0.0
|
50
|
+
def ==(other)
|
51
|
+
return false unless other.is_a?(CodeWithScope)
|
52
|
+
javascript == other.javascript && scope == other.scope
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the code with scope as JSON hash data.
|
56
|
+
#
|
57
|
+
# @example Get the code with scope as a JSON hash.
|
58
|
+
# code_with_scope.as_json
|
59
|
+
#
|
60
|
+
# @return [ Hash ] The code with scope as a JSON hash.
|
61
|
+
#
|
62
|
+
# @since 2.0.0
|
63
|
+
def as_json(*args)
|
64
|
+
{ "$code" => javascript, "$scope" => scope }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Instantiate the new code with scope.
|
68
|
+
#
|
69
|
+
# @example Instantiate the code with scope.
|
70
|
+
# BSON::CodeWithScope.new("this.value = name", name: "sid")
|
71
|
+
#
|
72
|
+
# @param [ String ] javascript The javascript code.
|
73
|
+
# @param [ Hash ] scope The variable scope.
|
74
|
+
#
|
75
|
+
# @since 2.0.0
|
76
|
+
def initialize(javascript = "", scope = {})
|
77
|
+
@javascript = javascript
|
78
|
+
@scope = scope
|
79
|
+
end
|
80
|
+
|
81
|
+
# Encode the javascript code with scope.
|
82
|
+
#
|
83
|
+
# @example Encode the code with scope.
|
84
|
+
# code_with_scope.to_bson
|
85
|
+
#
|
86
|
+
# @return [ String ] The encoded string.
|
87
|
+
#
|
88
|
+
# @see http://bsonspec.org/#/specification
|
89
|
+
#
|
90
|
+
# @since 2.0.0
|
91
|
+
def to_bson(encoded = ''.force_encoding(BINARY))
|
92
|
+
# -1 because we are removing an extra byte
|
93
|
+
out = encode_with_placeholder_and_null(BSON_ADJUST - 1, encoded) do |encoded|
|
94
|
+
javascript.to_bson(encoded)
|
95
|
+
scope.to_bson(encoded)
|
96
|
+
end
|
97
|
+
# an extra null byte has been added; we must remove it
|
98
|
+
out.chop!
|
99
|
+
end
|
100
|
+
|
101
|
+
# Deserialize a code with scope from BSON.
|
102
|
+
#
|
103
|
+
# @param [ BSON ] bson The encoded code with scope.
|
104
|
+
#
|
105
|
+
# @return [ TrueClass, FalseClass ] The decoded code with scope.
|
106
|
+
#
|
107
|
+
# @see http://bsonspec.org/#/specification
|
108
|
+
#
|
109
|
+
# @since 2.0.0
|
110
|
+
def self.from_bson(bson)
|
111
|
+
bson.read(4) # Throw away the total length.
|
112
|
+
new(bson.read(Int32.from_bson(bson)).from_bson_string.chop!, ::Hash.from_bson(bson))
|
113
|
+
end
|
114
|
+
|
115
|
+
# Register this type when the module is loaded.
|
116
|
+
#
|
117
|
+
# @since 2.0.0
|
118
|
+
Registry.register(BSON_TYPE, self)
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,549 @@
|
|
1
|
+
# Copyright (C) 2009-2013 MongoDB Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "yaml"
|
16
|
+
|
17
|
+
# Since we have a custom bsondoc type for yaml serialization, we need
|
18
|
+
# to ensure that it's properly deserialized when parsed.
|
19
|
+
#
|
20
|
+
# @since 2.0.0
|
21
|
+
YAML.add_builtin_type("bsondoc") do |type, value|
|
22
|
+
BSON::Document[value.map{ |val| val.to_a.first }]
|
23
|
+
end
|
24
|
+
|
25
|
+
module BSON
|
26
|
+
|
27
|
+
# This module provides behaviour for serializing and deserializing entire
|
28
|
+
# BSON documents, according to the BSON specification.
|
29
|
+
#
|
30
|
+
# @note The specification is: document ::= int32 e_list "\x00"
|
31
|
+
#
|
32
|
+
# @see http://bsonspec.org/#/specification
|
33
|
+
#
|
34
|
+
# @since 2.0.0
|
35
|
+
class Document < ::Hash
|
36
|
+
|
37
|
+
# Get a value from the document for the provided key. Can use string or
|
38
|
+
# symbol access, but the fastest will be to always provide a key that is of
|
39
|
+
# the same type as the stored keys.
|
40
|
+
#
|
41
|
+
# @example Get an element for the key.
|
42
|
+
# document["field"]
|
43
|
+
#
|
44
|
+
# @example Get an element for the key by symbol.
|
45
|
+
# document[:field]
|
46
|
+
#
|
47
|
+
# @param [ String, Symbol ] key The key to lookup.
|
48
|
+
#
|
49
|
+
# @return [ Object ] The found value, or nil if none found.
|
50
|
+
#
|
51
|
+
# @since 2.0.0
|
52
|
+
def [](key)
|
53
|
+
super(key) || super(key.to_s)
|
54
|
+
end
|
55
|
+
|
56
|
+
# If we have ordered hashes, the a BSON::Document is simply a hash. If we do
|
57
|
+
# not, then we need to import our custom BSON::Document implementation.
|
58
|
+
#
|
59
|
+
# @since 2.0.0
|
60
|
+
unless Environment.retaining_hash_order?
|
61
|
+
|
62
|
+
# Message for argument error when providing bad arguments to [].
|
63
|
+
#
|
64
|
+
# @since 2.0.0
|
65
|
+
ARG_ERROR = "An even number of arguments must be passed to BSON::Document[]."
|
66
|
+
|
67
|
+
# Sets a value for the provided key.
|
68
|
+
#
|
69
|
+
# @example Set the value in the document.
|
70
|
+
# document[:name] = "Sid"
|
71
|
+
#
|
72
|
+
# @param [ Object ] key The name of the key.
|
73
|
+
# @param [ Object ] value The value for the key.
|
74
|
+
#
|
75
|
+
# @return [ Object ] The passed in value.
|
76
|
+
#
|
77
|
+
# @since 2.0.0
|
78
|
+
def []=(key, value)
|
79
|
+
order.push(key) unless has_key?(key)
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
# Clear out all elements in the document.
|
84
|
+
#
|
85
|
+
# @example Clear out all elements.
|
86
|
+
# document.clear
|
87
|
+
#
|
88
|
+
# @return [ BSON::Document ] The empty document.
|
89
|
+
#
|
90
|
+
# @since 2.0.0
|
91
|
+
def clear
|
92
|
+
super
|
93
|
+
order.clear
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
# Delete a value from the document for the provided key.
|
98
|
+
#
|
99
|
+
# @example Delete a value from the document.
|
100
|
+
# document.delete(:name)
|
101
|
+
#
|
102
|
+
# @param [ Object ] key The key to delete for.
|
103
|
+
#
|
104
|
+
# @return [ Object ] The deleted value.
|
105
|
+
#
|
106
|
+
# @since 2.0.0
|
107
|
+
def delete(key)
|
108
|
+
if has_key?(key)
|
109
|
+
order.delete_at(order.index(key))
|
110
|
+
end
|
111
|
+
super
|
112
|
+
end
|
113
|
+
|
114
|
+
# Delete each key/value pair in the document for which the provided block
|
115
|
+
# returns true.
|
116
|
+
#
|
117
|
+
# @example Delete each for when the block is true.
|
118
|
+
# document.delete_if do |key, value|
|
119
|
+
# value == 1
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# @return [ BSON::Document ] The document.
|
123
|
+
#
|
124
|
+
# @since 2.0.0
|
125
|
+
def delete_if
|
126
|
+
super
|
127
|
+
synchronize!
|
128
|
+
self
|
129
|
+
end
|
130
|
+
alias :reject! :delete_if
|
131
|
+
|
132
|
+
# Iterate over each element of the document in insertion order and yield
|
133
|
+
# the key and value.
|
134
|
+
#
|
135
|
+
# @example Iterate over the document.
|
136
|
+
# document.each do |key, value|
|
137
|
+
# #...
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# @return [ BSON::Document ] The document if a block was given, otherwise
|
141
|
+
# an enumerator.
|
142
|
+
#
|
143
|
+
# @since 2.0.0
|
144
|
+
def each
|
145
|
+
if block_given?
|
146
|
+
order.each{ |key| yield([ key, self[key]]) }
|
147
|
+
self
|
148
|
+
else
|
149
|
+
to_enum(:each)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Iterate over each key in the document in insertion order and yield the
|
154
|
+
# key.
|
155
|
+
#
|
156
|
+
# @example Iterate over the keys.
|
157
|
+
# document.each_key do |key|
|
158
|
+
# #...
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# @return [ BSON::Document ] The document if a block was given, otherwise
|
162
|
+
# an enumerator.
|
163
|
+
#
|
164
|
+
# @since 2.0.0
|
165
|
+
def each_key
|
166
|
+
if block_given?
|
167
|
+
order.each{ |key| yield(key) }
|
168
|
+
self
|
169
|
+
else
|
170
|
+
to_enum(:each_key)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Iterate over each value in the document in insertion order and yield the
|
175
|
+
# value.
|
176
|
+
#
|
177
|
+
# @example Iterate over the values.
|
178
|
+
# document.each_value do |value|
|
179
|
+
# #...
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# @return [ BSON::Document ] The document if a block was given, otherwise
|
183
|
+
# an enumerator.
|
184
|
+
#
|
185
|
+
# @since 2.0.0
|
186
|
+
def each_value
|
187
|
+
if block_given?
|
188
|
+
order.each{ |key| yield(self[key]) }
|
189
|
+
self
|
190
|
+
else
|
191
|
+
to_enum(:each_value)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Iterate over each element of the document in insertion order and yield
|
196
|
+
# the key and value.
|
197
|
+
#
|
198
|
+
# @example Iterate over the document.
|
199
|
+
# document.each_pair do |key, value|
|
200
|
+
# #...
|
201
|
+
# end
|
202
|
+
#
|
203
|
+
# @return [ BSON::Document ] The document if a block was given, otherwise
|
204
|
+
# an enumerator.
|
205
|
+
#
|
206
|
+
# @since 2.0.0
|
207
|
+
def each_pair
|
208
|
+
if block_given?
|
209
|
+
order.each{ |key| yield([ key, self[key]]) }
|
210
|
+
self
|
211
|
+
else
|
212
|
+
to_enum(:each_pair)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Encode the document with the provided coder.
|
217
|
+
#
|
218
|
+
# @example Encode the document with the coder.
|
219
|
+
# document.encode_with(coder)
|
220
|
+
#
|
221
|
+
# @param [ Object ] coder The coder.
|
222
|
+
#
|
223
|
+
# @return [ String ] The encoded document.
|
224
|
+
#
|
225
|
+
# @since 2.0.0
|
226
|
+
def encode_with(coder)
|
227
|
+
coder.represent_seq("!bsondoc", map{ |key, value| { key => value }})
|
228
|
+
end
|
229
|
+
|
230
|
+
# Get all the keys in the document, in order.
|
231
|
+
#
|
232
|
+
# @example Get all the keys in the document.
|
233
|
+
# document.keys
|
234
|
+
#
|
235
|
+
# @return [ Array<Object> ] The ordered keys.
|
236
|
+
#
|
237
|
+
# @since 2.0.0
|
238
|
+
def keys
|
239
|
+
order.dup
|
240
|
+
end
|
241
|
+
|
242
|
+
# Instantiate a new Document.
|
243
|
+
#
|
244
|
+
# @example Instantiate an empty new document.
|
245
|
+
# BSON::Document.new
|
246
|
+
#
|
247
|
+
# @since 2.0.0
|
248
|
+
def initialize(*args, &block)
|
249
|
+
super
|
250
|
+
@order = []
|
251
|
+
end
|
252
|
+
|
253
|
+
# Inspect the contents of the document.
|
254
|
+
#
|
255
|
+
# @example Inspect the document.
|
256
|
+
# document.inspect
|
257
|
+
#
|
258
|
+
# @return [ String ] The inspection string.
|
259
|
+
#
|
260
|
+
# @since 2.0.0
|
261
|
+
def inspect
|
262
|
+
"#<BSON::Document #{super}>"
|
263
|
+
end
|
264
|
+
|
265
|
+
# Invert the document - reverses the order of all key/value pairs and
|
266
|
+
# returns a new document.
|
267
|
+
#
|
268
|
+
# @example Invert the document.
|
269
|
+
# document.invert
|
270
|
+
#
|
271
|
+
# @return [ BSON::Document ] The inverted document.
|
272
|
+
#
|
273
|
+
# @since 2.0.0
|
274
|
+
def invert
|
275
|
+
Document[to_a.map!{ |pair| pair.reverse }]
|
276
|
+
end
|
277
|
+
|
278
|
+
# Merge a document into this document. Will overwrite any existing keys and
|
279
|
+
# add potential new ones. This returns a new document instead of merging in
|
280
|
+
# place.
|
281
|
+
#
|
282
|
+
# @example Merge the document into this document.
|
283
|
+
# document.merge(other_document)
|
284
|
+
#
|
285
|
+
# @param [ BSON::Document ] other The document to merge in.
|
286
|
+
#
|
287
|
+
# @return [ BSON::Document ] A newly merged document.
|
288
|
+
#
|
289
|
+
# @since 2.0.0
|
290
|
+
def merge(other, &block)
|
291
|
+
dup.merge!(other, &block)
|
292
|
+
end
|
293
|
+
|
294
|
+
# Merge a document into this document. Will overwrite any existing keys and
|
295
|
+
# add potential new ones.
|
296
|
+
#
|
297
|
+
# @example Merge the document into this document.
|
298
|
+
# document.merge!(other_document)
|
299
|
+
#
|
300
|
+
# @param [ BSON::Document ] other The document to merge in.
|
301
|
+
#
|
302
|
+
# @return [ BSON::Document ] The document.
|
303
|
+
#
|
304
|
+
# @since 2.0.0
|
305
|
+
def merge!(other)
|
306
|
+
if block_given?
|
307
|
+
other.each do |key, value|
|
308
|
+
self[key] = key?(key) ? yield(key, self[key], value) : value
|
309
|
+
end
|
310
|
+
else
|
311
|
+
other.each{ |key, value| self[key] = value }
|
312
|
+
end
|
313
|
+
self
|
314
|
+
end
|
315
|
+
alias :update :merge!
|
316
|
+
|
317
|
+
# Delete each key/value pair in the document for which the provided block
|
318
|
+
# returns true. This returns a new document instead of modifying in place.
|
319
|
+
#
|
320
|
+
# @example Delete each for when the block is true.
|
321
|
+
# document.reject do |key, value|
|
322
|
+
# value == 1
|
323
|
+
# end
|
324
|
+
#
|
325
|
+
# @return [ BSON::Document ] The new document.
|
326
|
+
#
|
327
|
+
# @since 2.0.0
|
328
|
+
def reject(&block)
|
329
|
+
dup.reject!(&block)
|
330
|
+
end
|
331
|
+
|
332
|
+
# Replace this document with the other document.
|
333
|
+
#
|
334
|
+
# @example Replace the contents of this document with the other.
|
335
|
+
# document.replace(other_document)
|
336
|
+
#
|
337
|
+
# @param [ BSON::Document ] other The other document.
|
338
|
+
#
|
339
|
+
# @return [ BSON::Document ] The document replaced.
|
340
|
+
#
|
341
|
+
# @since 2.0.0
|
342
|
+
def replace(other)
|
343
|
+
super
|
344
|
+
@order = other.keys
|
345
|
+
self
|
346
|
+
end
|
347
|
+
|
348
|
+
# Shift the document by popping off the first key/value pair in the
|
349
|
+
# document.
|
350
|
+
#
|
351
|
+
# @example Shift the document.
|
352
|
+
# document.shift
|
353
|
+
#
|
354
|
+
# @return [ Array<Object, Object> ] The first key/value pair.
|
355
|
+
#
|
356
|
+
# @since 2.0.0
|
357
|
+
def shift
|
358
|
+
key = order.first
|
359
|
+
value = delete(key)
|
360
|
+
[ key, value ]
|
361
|
+
end
|
362
|
+
|
363
|
+
alias :select :find_all
|
364
|
+
|
365
|
+
# Get the document as an array. This returns a multi-dimensional array
|
366
|
+
# where each element is a [ key, value ] pair in the insertion order.
|
367
|
+
#
|
368
|
+
# @example Get the document as an array.
|
369
|
+
# document.to_a
|
370
|
+
#
|
371
|
+
# @return [ Array<Array<Object, Object>> ] The pairs in insertion order.
|
372
|
+
#
|
373
|
+
# @since 2.0.0
|
374
|
+
def to_a
|
375
|
+
order.map{ |key| [ key, self[key] ]}
|
376
|
+
end
|
377
|
+
|
378
|
+
# Convert this document to a hash. Since a document is simply an ordered
|
379
|
+
# hash we return self.
|
380
|
+
#
|
381
|
+
# @example Get the document as a hash.
|
382
|
+
# document.to_hash
|
383
|
+
#
|
384
|
+
# @return [ BSON::Document ] The document.
|
385
|
+
#
|
386
|
+
# @since 2.0.0
|
387
|
+
def to_hash
|
388
|
+
self
|
389
|
+
end
|
390
|
+
|
391
|
+
# Convert the document to yaml.
|
392
|
+
#
|
393
|
+
# @example Convert the document to yaml.
|
394
|
+
# document.to_yaml
|
395
|
+
#
|
396
|
+
# @param [ Hash ] options The yaml options.
|
397
|
+
#
|
398
|
+
# @return [ String ] The document as yaml.
|
399
|
+
#
|
400
|
+
# @since 2.0.0
|
401
|
+
def to_yaml(options = {})
|
402
|
+
if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
|
403
|
+
return super
|
404
|
+
end
|
405
|
+
YAML.quick_emit(self, options) do |out|
|
406
|
+
out.seq(taguri) do |seq|
|
407
|
+
each{ |key, value| seq.add(key => value) }
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
# Get the custom yaml type for the document.
|
413
|
+
#
|
414
|
+
# @example Get the yaml type.
|
415
|
+
# document.to_yaml_type
|
416
|
+
#
|
417
|
+
# @return [ String ] "!bsondoc".
|
418
|
+
#
|
419
|
+
# @since 2.0.0
|
420
|
+
def to_yaml_type
|
421
|
+
"!bsondoc"
|
422
|
+
end
|
423
|
+
|
424
|
+
# Get all the values in the document, by order of insertion.
|
425
|
+
#
|
426
|
+
# @example Get all the values in the document.
|
427
|
+
# document.values
|
428
|
+
#
|
429
|
+
# @return [ Array<Object> ] The ordered values.
|
430
|
+
#
|
431
|
+
# @since 2.0.0
|
432
|
+
def values
|
433
|
+
order.map{ |key| self[key] }
|
434
|
+
end
|
435
|
+
|
436
|
+
class << self
|
437
|
+
|
438
|
+
# Create a new document given the provided arguments. The args can either
|
439
|
+
# be empty in order to instantiate an empty document, or an array of
|
440
|
+
# key/value pairs in the order that they should remain in.
|
441
|
+
#
|
442
|
+
# @example Create a new empty document.
|
443
|
+
# BSON::Document[]
|
444
|
+
#
|
445
|
+
# @example Create a new document with the provided elements.
|
446
|
+
# BSON::Document[1, 2, 3, 4]
|
447
|
+
#
|
448
|
+
# @example Create a new document with key/value array pairs.
|
449
|
+
# BSON::Document[[ 1, 2 ], [ 3, 4 ]]
|
450
|
+
#
|
451
|
+
# @param [ Array<Object> ] args The key/value pairs.
|
452
|
+
#
|
453
|
+
# @return [ BSON::Document ] The new document.
|
454
|
+
#
|
455
|
+
# @since 2.0.0
|
456
|
+
def [](*args)
|
457
|
+
if (args.length == 1 && args.first.is_a?(Array))
|
458
|
+
return document_from_pairs(args)
|
459
|
+
end
|
460
|
+
raise ArgumentError.new(ARG_ERROR) unless (args.size % 2 == 0)
|
461
|
+
document_from_args(args)
|
462
|
+
end
|
463
|
+
|
464
|
+
private
|
465
|
+
|
466
|
+
# Returns a document that will be generated from an array of [ key, value ]
|
467
|
+
# array pairs.
|
468
|
+
#
|
469
|
+
# @api private
|
470
|
+
#
|
471
|
+
# @example Initialize a document from array pairs.
|
472
|
+
# BSON::Document[[ 1, 2 ], [ 3, 4 ]]
|
473
|
+
#
|
474
|
+
# @param [ Array ] pairs The key/value pairs.
|
475
|
+
#
|
476
|
+
# @since 2.0.0
|
477
|
+
#
|
478
|
+
# @return [ BSON::Document ] The document.
|
479
|
+
def document_from_pairs(pairs)
|
480
|
+
document = new
|
481
|
+
pairs.first.each do |pair|
|
482
|
+
next unless (pair.is_a?(Array))
|
483
|
+
document[pair[0]] = pair[1]
|
484
|
+
end
|
485
|
+
return document
|
486
|
+
end
|
487
|
+
|
488
|
+
# Returns a document that will be generated from an even number of
|
489
|
+
# individual arguments.
|
490
|
+
#
|
491
|
+
# @api private
|
492
|
+
#
|
493
|
+
# @example Initialize a document from args.
|
494
|
+
# BSON::Document[1, 2, 3, 4]
|
495
|
+
#
|
496
|
+
# @param [ Array ] args The arguments.
|
497
|
+
#
|
498
|
+
# @return [ BSON::Document ] The document.
|
499
|
+
#
|
500
|
+
# @since 2.0.0
|
501
|
+
def document_from_args(args)
|
502
|
+
document = new
|
503
|
+
args.each_with_index do |val, ind|
|
504
|
+
next if (ind % 2 != 0)
|
505
|
+
document[val] = args[ind + 1]
|
506
|
+
end
|
507
|
+
document
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
private
|
512
|
+
|
513
|
+
# @!attribute order
|
514
|
+
# @api private
|
515
|
+
# @return [ Array<String> ] The document keys in order.
|
516
|
+
# @since 2.0.0
|
517
|
+
attr_reader :order
|
518
|
+
|
519
|
+
# Initialize a copy of the document for use with clone or dup.
|
520
|
+
#
|
521
|
+
# @api private
|
522
|
+
#
|
523
|
+
# @example Clone the document.
|
524
|
+
# document.clone
|
525
|
+
#
|
526
|
+
# @param [ Object ] other The original copy.
|
527
|
+
#
|
528
|
+
# @since 2.0.0
|
529
|
+
def initialize_copy(other)
|
530
|
+
super
|
531
|
+
@order = other.keys
|
532
|
+
end
|
533
|
+
|
534
|
+
# Ensure that the ordered keys are the same entries as the internal keys.
|
535
|
+
#
|
536
|
+
# @api private
|
537
|
+
#
|
538
|
+
# @example Synchronize the keys.
|
539
|
+
# document.synchronize!
|
540
|
+
#
|
541
|
+
# @return [ Array<Object> ] The keys.
|
542
|
+
#
|
543
|
+
# @since 2.0.0
|
544
|
+
def synchronize!
|
545
|
+
order.reject!{ |key| !has_key?(key) }
|
546
|
+
end
|
547
|
+
end
|
548
|
+
end
|
549
|
+
end
|