Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions lib/bson/dbref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ def as_json(*args)
# @example Create the DBRef.
# BSON::DBRef.new({'$ref' => 'users', '$id' => id, '$db' => 'database'})
#
# @param [ Hash ] hash the DBRef hash. It must contain $collection and $id.
# @param [ Hash ] hash the DBRef hash. It must contain $ref and $id.
def initialize(hash)
hash = reorder_fields(hash)
%w($ref $id).each do |key|
unless hash[key]
raise ArgumentError, "DBRef must have #{key}: #{hash}"
Expand All @@ -84,7 +85,7 @@ def initialize(hash)
end
end

super(hash)
super
end

# Converts the DBRef to raw BSON.
Expand All @@ -99,5 +100,26 @@ def initialize(hash)
def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
as_json.to_bson(buffer, validating_keys)
end

private

# Reorder the fields of the given Hash to have $ref first, $id second,
# and $db third. The rest of the fields in the hash can come in any
# order after that.
#
# @param [ Hash ] hash The input hash. Must be a valid dbref.
#
# @return [ Hash ] The hash with it's fields reordered.
def reorder_fields(hash)
hash = BSON::Document.new(hash)
reordered = {}
reordered['$ref'] = hash.delete('$ref')
reordered['$id'] = hash.delete('$id')
if db = hash.delete('$db')
reordered['$db'] = db
end

reordered.update(hash)
end
end
end
64 changes: 64 additions & 0 deletions spec/bson/dbref_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,70 @@
end.to raise_error(ArgumentError, /The value for key \$db must be a string/)
end
end

context 'when providing the fieds as symbols' do
let(:hash) do
{ :$ref => 'users', :$id => object_id, :$db => 'db' }
end

it 'does not raise an error' do
expect do
dbref
end.to_not raise_error
end
end

context 'when testing the ordering of the fields' do
context 'when the fields are in order' do
let(:hash) do
{ '$ref' => 'users', '$id' => object_id, '$db' => 'db' }
end

it 'has the correct order' do
expect(dbref.keys).to eq(['$ref', '$id', '$db'])
end
end

context 'when the fields are out of order' do
let(:hash) do
{ '$db' => 'db', '$id' => object_id, '$ref' => 'users' }
end

it 'has the correct order' do
expect(dbref.keys).to eq(['$ref', '$id', '$db'])
end
end

context 'when there is no db' do
let(:hash) do
{ '$id' => object_id, '$ref' => 'users' }
end

it 'has the correct order' do
expect(dbref.keys).to eq(['$ref', '$id'])
end
end

context 'when the there are other fields in order' do
let(:hash) do
{ '$ref' => 'users', '$id' => object_id, '$db' => 'db', 'x' => 'y', 'y' => 'z' }
end

it 'has the correct order' do
expect(dbref.keys).to eq(['$ref', '$id', '$db', 'x', 'y'])
end
end

context 'when the there are other fields out of order' do
let(:hash) do
{ 'y' => 'z', '$db' => 'db', '$id' => object_id, 'x' => 'y', '$ref' => 'users' }
end

it 'has the correct order' do
expect(dbref.keys).to eq(['$ref', '$id', '$db', 'y', 'x'])
end
end
end
end

describe '#to_bson' do
Expand Down