mongo_doc_rails2 0.6.1
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.
- data/.document +5 -0
- data/.gitignore +8 -0
- data/HISTORY.md +11 -0
- data/LICENSE +20 -0
- data/README.textile +185 -0
- data/Rakefile +188 -0
- data/TODO +40 -0
- data/VERSION +1 -0
- data/data/.gitignore +2 -0
- data/examples/simple_document.rb +46 -0
- data/examples/simple_object.rb +34 -0
- data/features/collections.feature +9 -0
- data/features/embed_hash.feature +16 -0
- data/features/finders.feature +76 -0
- data/features/indexes.feature +28 -0
- data/features/mongodb.yml +7 -0
- data/features/mongodoc_base.feature +128 -0
- data/features/new_record.feature +36 -0
- data/features/partial_updates.feature +95 -0
- data/features/removing_documents.feature +68 -0
- data/features/saving_an_object.feature +15 -0
- data/features/scopes.feature +66 -0
- data/features/step_definitions/collection_steps.rb +17 -0
- data/features/step_definitions/document_steps.rb +149 -0
- data/features/step_definitions/documents.rb +40 -0
- data/features/step_definitions/embed_hash_steps.rb +6 -0
- data/features/step_definitions/finder_steps.rb +15 -0
- data/features/step_definitions/index_steps.rb +10 -0
- data/features/step_definitions/json_steps.rb +9 -0
- data/features/step_definitions/object_steps.rb +50 -0
- data/features/step_definitions/objects.rb +24 -0
- data/features/step_definitions/partial_update_steps.rb +31 -0
- data/features/step_definitions/query_steps.rb +66 -0
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/step_definitions/scope_steps.rb +18 -0
- data/features/step_definitions/string_casting_steps.rb +29 -0
- data/features/step_definitions/util_steps.rb +7 -0
- data/features/string_casting.feature +10 -0
- data/features/support/support.rb +10 -0
- data/features/using_criteria.feature +142 -0
- data/lib/mongo_doc.rb +12 -0
- data/lib/mongo_doc/associations.rb +109 -0
- data/lib/mongo_doc/associations/collection_proxy.rb +121 -0
- data/lib/mongo_doc/associations/document_proxy.rb +65 -0
- data/lib/mongo_doc/associations/hash_proxy.rb +102 -0
- data/lib/mongo_doc/associations/proxy_base.rb +48 -0
- data/lib/mongo_doc/attributes.rb +84 -0
- data/lib/mongo_doc/bson.rb +31 -0
- data/lib/mongo_doc/collection.rb +82 -0
- data/lib/mongo_doc/connection.rb +88 -0
- data/lib/mongo_doc/contexts.rb +31 -0
- data/lib/mongo_doc/contexts/ids.rb +41 -0
- data/lib/mongo_doc/contexts/mongo.rb +272 -0
- data/lib/mongo_doc/criteria.rb +70 -0
- data/lib/mongo_doc/cursor.rb +32 -0
- data/lib/mongo_doc/document.rb +205 -0
- data/lib/mongo_doc/ext.rb +16 -0
- data/lib/mongo_doc/ext/array.rb +5 -0
- data/lib/mongo_doc/ext/binary.rb +7 -0
- data/lib/mongo_doc/ext/boolean_class.rb +17 -0
- data/lib/mongo_doc/ext/date.rb +19 -0
- data/lib/mongo_doc/ext/date_time.rb +17 -0
- data/lib/mongo_doc/ext/dbref.rb +7 -0
- data/lib/mongo_doc/ext/hash.rb +7 -0
- data/lib/mongo_doc/ext/min_max_keys.rb +13 -0
- data/lib/mongo_doc/ext/nil_class.rb +5 -0
- data/lib/mongo_doc/ext/numeric.rb +17 -0
- data/lib/mongo_doc/ext/object.rb +19 -0
- data/lib/mongo_doc/ext/object_id.rb +7 -0
- data/lib/mongo_doc/ext/regexp.rb +5 -0
- data/lib/mongo_doc/ext/string.rb +5 -0
- data/lib/mongo_doc/ext/symbol.rb +5 -0
- data/lib/mongo_doc/ext/time.rb +9 -0
- data/lib/mongo_doc/finders.rb +38 -0
- data/lib/mongo_doc/index.rb +46 -0
- data/lib/mongo_doc/matchers.rb +35 -0
- data/lib/mongo_doc/root.rb +26 -0
- data/lib/mongo_doc/scope.rb +64 -0
- data/lib/mongo_doc/validations.rb +12 -0
- data/lib/mongo_doc/validations/macros.rb +11 -0
- data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
- data/lib/mongoid/contexts/enumerable.rb +151 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +239 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +93 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/mongo_doc_rails2.gemspec +237 -0
- data/mongod.example.yml +2 -0
- data/mongodb.example.yml +14 -0
- data/perf/mongo_doc_object.rb +83 -0
- data/perf/mongo_document.rb +84 -0
- data/perf/ruby_driver.rb +49 -0
- data/script/console +8 -0
- data/spec/array_including_argument_matcher.rb +62 -0
- data/spec/associations/collection_proxy_spec.rb +233 -0
- data/spec/associations/document_proxy_spec.rb +45 -0
- data/spec/associations/hash_proxy_spec.rb +181 -0
- data/spec/associations/proxy_base_spec.rb +92 -0
- data/spec/associations_spec.rb +218 -0
- data/spec/attributes_accessor_spec.rb +33 -0
- data/spec/attributes_spec.rb +145 -0
- data/spec/bson_matchers.rb +54 -0
- data/spec/bson_spec.rb +196 -0
- data/spec/collection_spec.rb +169 -0
- data/spec/connection_spec.rb +147 -0
- data/spec/contexts/ids_spec.rb +49 -0
- data/spec/contexts/mongo_spec.rb +235 -0
- data/spec/contexts_spec.rb +56 -0
- data/spec/criteria_spec.rb +69 -0
- data/spec/cursor_spec.rb +91 -0
- data/spec/document_ext.rb +9 -0
- data/spec/document_spec.rb +553 -0
- data/spec/embedded_save_spec.rb +73 -0
- data/spec/ext_spec.rb +89 -0
- data/spec/finders_spec.rb +61 -0
- data/spec/hash_matchers.rb +27 -0
- data/spec/index_spec.rb +79 -0
- data/spec/matchers_spec.rb +342 -0
- data/spec/mongodb.yml +6 -0
- data/spec/mongodb_pairs.yml +8 -0
- data/spec/new_record_spec.rb +128 -0
- data/spec/root_spec.rb +41 -0
- data/spec/scope_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/validations_spec.rb +30 -0
- metadata +346 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Attributes attributes accessor" do
|
|
4
|
+
class AttributesTest
|
|
5
|
+
include MongoDoc::Attributes
|
|
6
|
+
|
|
7
|
+
attr_accessor :name
|
|
8
|
+
attr_accessor :age
|
|
9
|
+
attr_accessor :birthdate, :type => Date
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context "#attributes" do
|
|
13
|
+
subject do
|
|
14
|
+
AttributesTest.new.attributes
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns a hash of the given attributes" do
|
|
18
|
+
should have_key(:name)
|
|
19
|
+
should have_key(:age)
|
|
20
|
+
should have_key(:birthdate)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "#attributes=" do
|
|
25
|
+
let(:object) { AttributesTest.new }
|
|
26
|
+
|
|
27
|
+
it "sets attributes from a hash" do
|
|
28
|
+
name = 'name'
|
|
29
|
+
object.attributes = {:name => name}
|
|
30
|
+
object.name.should == name
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Attributes" do
|
|
4
|
+
class AttributesTest
|
|
5
|
+
include MongoDoc::Attributes
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "defines _id attribute" do
|
|
9
|
+
AttributesTest.new.should respond_to(:_id)
|
|
10
|
+
AttributesTest.new.should respond_to(:_id=)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context ".key" do
|
|
14
|
+
class AttributeAccessorTest
|
|
15
|
+
include MongoDoc::Attributes
|
|
16
|
+
|
|
17
|
+
key :date, :default => Date.today, :type => Date
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "is an alias for attr_accessor" do
|
|
21
|
+
AttributeAccessorTest._keys.should include(:date)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context ".attr_accessor" do
|
|
26
|
+
class TestKeys
|
|
27
|
+
include MongoDoc::Attributes
|
|
28
|
+
|
|
29
|
+
attr_accessor :attr1, :attr2
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "adds its arguments to _keys" do
|
|
33
|
+
TestKeys._keys.should == [:attr1, :attr2]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "accessors" do
|
|
37
|
+
subject do
|
|
38
|
+
TestKeys.new
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "has an attr1 reader" do
|
|
42
|
+
should respond_to(:attr1)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "has an attr1 writer" do
|
|
46
|
+
should respond_to(:attr1=)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "default values" do
|
|
51
|
+
class TestDefault
|
|
52
|
+
include MongoDoc::Attributes
|
|
53
|
+
|
|
54
|
+
attr_accessor :with_default, :default => 'value'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
let(:object) { TestDefault.new }
|
|
58
|
+
|
|
59
|
+
it "uses the default value" do
|
|
60
|
+
object.with_default.should == 'value'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "only uses the default value once" do
|
|
64
|
+
object.with_default.should == 'value'
|
|
65
|
+
class << object
|
|
66
|
+
def _default_with_default
|
|
67
|
+
'other value'
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
object.with_default.should == 'value'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "does not set the default value if the setter is invoked first" do
|
|
74
|
+
object.with_default = nil
|
|
75
|
+
object.with_default.should be_nil
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "specified type" do
|
|
80
|
+
class TestType
|
|
81
|
+
include MongoDoc::Attributes
|
|
82
|
+
|
|
83
|
+
attr_accessor :birthdate, :type => Date
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
let(:object) { TestType.new }
|
|
87
|
+
|
|
88
|
+
it "does not call Type.cast_from_string when the set value is not a string" do
|
|
89
|
+
Date.should_not_receive :cast_from_string
|
|
90
|
+
object.birthdate = Date.today
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "when the accessor is set with a string" do
|
|
94
|
+
let(:date) { Date.today }
|
|
95
|
+
|
|
96
|
+
it "delegates to Type.cast_from_string to set the value" do
|
|
97
|
+
Date.should_receive(:cast_from_string).with(date.to_s)
|
|
98
|
+
object.birthdate = date.to_s
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "sets the value to the result of the case" do
|
|
102
|
+
object.birthdate = date.to_s
|
|
103
|
+
object.birthdate.should == date
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "used with inheritance" do
|
|
109
|
+
class TestParent
|
|
110
|
+
include MongoDoc::Attributes
|
|
111
|
+
|
|
112
|
+
attr_accessor :parent_attr
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class TestChild < TestParent
|
|
116
|
+
attr_accessor :child_attr
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "has its own keys" do
|
|
120
|
+
TestChild._keys.should include(:child_attr)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "has the keys from the parent class" do
|
|
124
|
+
TestChild._keys.should include(*TestParent._keys)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "does not add keys to the parent class" do
|
|
128
|
+
TestParent._keys.should_not include(:child_attr)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "._attributes" do
|
|
134
|
+
class TestHasOneDoc
|
|
135
|
+
include MongoDoc::Document
|
|
136
|
+
|
|
137
|
+
attr_accessor :key
|
|
138
|
+
embed :embed
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "is _keys + _associations" do
|
|
142
|
+
TestHasOneDoc._attributes.should == TestHasOneDoc._keys + TestHasOneDoc._associations
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module BsonMatchers
|
|
2
|
+
class BeBsonEql
|
|
3
|
+
def initialize(expected)
|
|
4
|
+
@expected = expected
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def matches?(target)
|
|
8
|
+
@target = target
|
|
9
|
+
@target == @expected
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def failure_message
|
|
13
|
+
"expected\...#{@target.inspect}\n" +
|
|
14
|
+
"to be BSON code equivalent to\...#{@expected.inspect}\n" +
|
|
15
|
+
"Difference:\...#{@expected.diff(@target).inspect}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def negative_failure_message
|
|
19
|
+
"expected\...#{@target.inspect}\n" +
|
|
20
|
+
"to be BSON code different from\...#{@expected.inspect}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class BeMongoEql
|
|
25
|
+
def initialize(expected, include_id)
|
|
26
|
+
@include_id = include_id
|
|
27
|
+
@expected = include_id ? expected : expected.except('_id')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def matches?(target)
|
|
31
|
+
@target = @include_id ? target : target.except('_id')
|
|
32
|
+
@target == @expected
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def failure_message
|
|
36
|
+
"expected\...#{@target.inspect}\n" +
|
|
37
|
+
"to be BSON code equivalent to\...#{@expected.inspect}\n" +
|
|
38
|
+
"Difference:\...#{@expected.diff(@target).inspect}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def negative_failure_message
|
|
42
|
+
"expected\...#{@target.inspect}\n" +
|
|
43
|
+
"to be BSON code different from\...#{@expected.inspect}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def be_bson_eql(expected)
|
|
48
|
+
BeBsonEql.new(expected)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def be_mongo_eql(expected, include_id = true)
|
|
52
|
+
BeMongoEql.new(expected, include_id)
|
|
53
|
+
end
|
|
54
|
+
end
|
data/spec/bson_spec.rb
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "BSON for Mongo (BSON)" do
|
|
4
|
+
describe "#decode" do
|
|
5
|
+
it "just returns the json if the :raw_json option is used" do
|
|
6
|
+
hash = {}
|
|
7
|
+
MongoDoc::BSON.should_not_receive(:bson_create)
|
|
8
|
+
MongoDoc::BSON.decode(hash, :raw_json => true).should == hash
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "calls bson_create if parameter is a hash" do
|
|
12
|
+
hash = {}
|
|
13
|
+
options = {:option => true}
|
|
14
|
+
MongoDoc::BSON.should_receive(:bson_create).with(hash, options)
|
|
15
|
+
MongoDoc::BSON.decode(hash, options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "if parameter is an array, it calls array_create" do
|
|
19
|
+
array = []
|
|
20
|
+
options = {:option => true}
|
|
21
|
+
MongoDoc::BSON.should_receive(:array_create).with(array, options)
|
|
22
|
+
MongoDoc::BSON.decode(array, options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "returns the json value as is if the parameter is not a hash or array" do
|
|
26
|
+
["", 1, 1.5, true, false, nil].each do |type_value|
|
|
27
|
+
MongoDoc::BSON.decode(type_value).should == type_value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#array_create" do
|
|
33
|
+
it "calls decode for each element" do
|
|
34
|
+
first = 1
|
|
35
|
+
array = [first]
|
|
36
|
+
options = {:option => true}
|
|
37
|
+
MongoDoc::BSON.should_receive(:decode).with(first, options)
|
|
38
|
+
MongoDoc::BSON.array_create(array, options)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "just returns the array if the :raw_json option is used" do
|
|
42
|
+
hash = {'key' => 'value', MongoDoc::BSON::CLASS_KEY => 'Date'}
|
|
43
|
+
array = [hash]
|
|
44
|
+
MongoDoc::BSON.should_not_receive(:decode)
|
|
45
|
+
MongoDoc::BSON.array_create(array, :raw_json => true).should == array
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#bson_create" do
|
|
50
|
+
it "leaves a simple hash intact" do
|
|
51
|
+
hash = {}
|
|
52
|
+
MongoDoc::BSON.bson_create(hash).should == hash
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "a class hash extracts the class, and calls class.bson_create" do
|
|
56
|
+
base_hash = {'key' => 'value'}
|
|
57
|
+
bson_hash = base_hash.merge(MongoDoc::BSON::CLASS_KEY => 'Date')
|
|
58
|
+
Date.should_receive(:bson_create).with(base_hash, {})
|
|
59
|
+
MongoDoc::BSON.bson_create(bson_hash)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "ignores a class hash when the :raw_json option is used" do
|
|
63
|
+
hash = {'key' => 'value', MongoDoc::BSON::CLASS_KEY => 'Date'}
|
|
64
|
+
MongoDoc::BSON.bson_create(hash, :raw_json => true).should == hash
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "Hash" do
|
|
69
|
+
it "#to_bson returns the hash" do
|
|
70
|
+
hash = {'key' => 1}
|
|
71
|
+
hash.to_bson.should == hash
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "#to_bson returns the hash with symbol keys as strings" do
|
|
75
|
+
{:key => 1}.to_bson.should == {"key" => 1}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "decodes to a hash" do
|
|
79
|
+
hash = {'key' => 1}
|
|
80
|
+
MongoDoc::BSON.decode(hash.to_bson).should == hash
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "decodes the values of the hash" do
|
|
84
|
+
hash = {'key' => {'subkey' => Date.today}}
|
|
85
|
+
MongoDoc::BSON.decode(hash.to_bson).should == hash
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "Array" do
|
|
90
|
+
it "#to_bson returns the array" do
|
|
91
|
+
array = ['string', 1]
|
|
92
|
+
array.to_bson.should == array
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "#to_bson iterates over its elements" do
|
|
96
|
+
array = []
|
|
97
|
+
array.should_receive(:map)
|
|
98
|
+
array.to_bson
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "decodes to an array" do
|
|
102
|
+
array = ['string', 1]
|
|
103
|
+
MongoDoc::BSON.decode(array.to_bson).should == array
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "Extensions to core classes" do
|
|
108
|
+
it "#to_bson for objects that are BSON native return themselves" do
|
|
109
|
+
[true, false, nil, 1.0, 1, /regexp/, 'string', :symbol, Time.now].each do |native|
|
|
110
|
+
native.to_bson.should == native
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "objects that are BSON native decode to themselves" do
|
|
115
|
+
[true, false, nil, 1.0, 1, /regexp/, 'string', :symbol, Time.now].each do |native|
|
|
116
|
+
hash = {'native' => native}
|
|
117
|
+
MongoDoc::BSON.decode(hash.to_bson).should == hash
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "Date#to_bson returns a date hash" do
|
|
122
|
+
date = Date.today
|
|
123
|
+
date.to_bson.should == {MongoDoc::BSON::CLASS_KEY => "Date", "dt" => date.strftime, "sg" => date.respond_to?(:start) ? date.start : date.sg}
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "roundtrips Date" do
|
|
127
|
+
date = Date.today
|
|
128
|
+
MongoDoc::BSON.decode(date.to_bson).should == date
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "DateTime#to_bson returns a datetime hash" do
|
|
132
|
+
datetime = DateTime.now
|
|
133
|
+
datetime.to_bson.should == {MongoDoc::BSON::CLASS_KEY => "DateTime", "dt" => datetime.strftime, "sg" => datetime.respond_to?(:start) ? datetime.start : datetime.sg}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "roundtrips DateTime" do
|
|
137
|
+
datetime = DateTime.now
|
|
138
|
+
MongoDoc::BSON.decode(datetime.to_bson).to_s.should == datetime.to_s
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
describe "Mongo Classes" do
|
|
143
|
+
[BSON::ObjectID.new, BSON::DBRef.new('ns', 1), BSON::Code.new('code'), BSON::Binary.new, BSON::MinKey.new, BSON::MaxKey.new].each do |obj|
|
|
144
|
+
it "#to_bson for #{obj.class.name} returns self" do
|
|
145
|
+
obj.to_bson.should == obj
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "objects of type #{obj.class.name} decode to themselves" do
|
|
149
|
+
hash = {"mongo" => obj}
|
|
150
|
+
MongoDoc::BSON.decode(hash.to_bson)["mongo"].should == obj
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
describe "Extensions to Object" do
|
|
156
|
+
class Simple
|
|
157
|
+
attr_accessor :value
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class Complex
|
|
161
|
+
attr_accessor :array_of_simple
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
before do
|
|
165
|
+
@value1 = 'value1'
|
|
166
|
+
@simple1 = Simple.new
|
|
167
|
+
@simple1.value = @value1
|
|
168
|
+
@value2 = 'value2'
|
|
169
|
+
@simple2 = Simple.new
|
|
170
|
+
@simple2.value = @value2
|
|
171
|
+
@complex = Complex.new
|
|
172
|
+
@complex.array_of_simple = [@simple1, @simple2]
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "renders a json representation of a simple object" do
|
|
176
|
+
@simple1.to_bson.should be_bson_eql({MongoDoc::BSON::CLASS_KEY => Simple.name, "value" => @value1})
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "renders a json representation of an object with embedded objects" do
|
|
180
|
+
@complex.to_bson.should be_bson_eql({MongoDoc::BSON::CLASS_KEY => Complex.name, "array_of_simple" => [@simple1.to_bson, @simple2.to_bson]})
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it "ignores a class hash when the :raw_json option is used" do
|
|
184
|
+
Complex.bson_create(@complex.to_bson.except(MongoDoc::BSON::CLASS_KEY), :raw_json => true).array_of_simple.first.should == @simple1.to_bson
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "roundtrips the object" do
|
|
188
|
+
MongoDoc::BSON.decode(@complex.to_bson).should be_kind_of(Complex)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "allows for embedded arrays of objects" do
|
|
192
|
+
obj = MongoDoc::BSON.decode(@complex.to_bson)
|
|
193
|
+
obj.array_of_simple.each {|o| o.should be_kind_of(Simple)}
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Collection" do
|
|
4
|
+
|
|
5
|
+
let(:mongo_collection) { stub('collection') }
|
|
6
|
+
|
|
7
|
+
it ".new delegates to .mongo_collection" do
|
|
8
|
+
name = 'collection_name'
|
|
9
|
+
MongoDoc::Collection.should_receive(:mongo_collection).with(name).and_return(mongo_collection)
|
|
10
|
+
MongoDoc::Collection.new(name)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "with the underlying Mongo::Collection" do
|
|
14
|
+
|
|
15
|
+
let(:collection) do
|
|
16
|
+
MongoDoc::Collection.stub(:mongo_collection).and_return(mongo_collection)
|
|
17
|
+
MongoDoc::Collection.new('collection_name')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "has Criteria mixed in" do
|
|
21
|
+
MongoDoc::Criteria.should === collection
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "#collection references self for Mongo context" do
|
|
25
|
+
collection.send(:collection).should == collection
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
%w([] clear count create_index db distinct drop drop_index drop_indexes group hint index_information map_reduce mapreduce name options pk_factory remove rename size).each do |delegated_method|
|
|
29
|
+
it "delegates #{delegated_method} to the Mongo::Collection" do
|
|
30
|
+
mongo_collection.should_receive(delegated_method)
|
|
31
|
+
collection.send(delegated_method)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "#find" do
|
|
36
|
+
let(:cursor) { MongoDoc::Cursor.new(collection, stub('cursor', :close => nil)) }
|
|
37
|
+
|
|
38
|
+
before do
|
|
39
|
+
collection.stub(:wrapped_cursor).and_return(cursor)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "wraps the cursor" do
|
|
43
|
+
query = {'sample' => 'data'}
|
|
44
|
+
options = { :limit => 1}
|
|
45
|
+
collection.should_receive(:wrapped_cursor).with(query, options).and_return(cursor)
|
|
46
|
+
collection.find(query, options)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "calls the block with a wrapped cursor" do
|
|
50
|
+
collection.find {|c| @result = c}
|
|
51
|
+
@result.should == cursor
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context "#find_one" do
|
|
56
|
+
let(:bson) { stub('bson') }
|
|
57
|
+
|
|
58
|
+
before do
|
|
59
|
+
mongo_collection.stub(:find_one).and_return(bson)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "delegates to the Mongo::Collection" do
|
|
63
|
+
spec = { 'sample' => 'data' }
|
|
64
|
+
options = {:limit => 1}
|
|
65
|
+
mongo_collection.should_receive(:find_one).with(spec, options)
|
|
66
|
+
collection.find_one(spec, options)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "converts the result back from bson" do
|
|
70
|
+
MongoDoc::BSON.should_receive(:decode).with(bson)
|
|
71
|
+
collection.find_one({ 'sample' => 'data' })
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "returns the converted result" do
|
|
75
|
+
obj = stub('obj')
|
|
76
|
+
MongoDoc::BSON.stub(:decode).and_return(obj)
|
|
77
|
+
collection.find_one({ 'sample' => 'data' }).should == obj
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "returns nil if the delegate returns nil" do
|
|
81
|
+
mongo_collection.stub(:find_one)
|
|
82
|
+
collection.find_one({ 'sample' => 'data' }).should be_nil
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context "#insert" do
|
|
87
|
+
let(:doc) { {'sample' => 'data'} }
|
|
88
|
+
|
|
89
|
+
it "delegates to the Mongo::Collection" do
|
|
90
|
+
options = {:safe => false}
|
|
91
|
+
mongo_collection.should_receive(:insert).with(doc, options)
|
|
92
|
+
collection.insert(doc, options)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "converts the doc_or_docs to bson" do
|
|
96
|
+
doc.should_receive(:to_bson)
|
|
97
|
+
mongo_collection.stub(:insert)
|
|
98
|
+
collection.insert(doc, options)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "returns the delegates result" do
|
|
102
|
+
result = 'result'
|
|
103
|
+
mongo_collection.stub(:insert).and_return(result)
|
|
104
|
+
collection.insert(doc).should == result
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "#save" do
|
|
109
|
+
let(:doc) { {'sample' => 'data'} }
|
|
110
|
+
|
|
111
|
+
it "delegates to the Mongo::Collection" do
|
|
112
|
+
options = {:safe => false}
|
|
113
|
+
mongo_collection.should_receive(:save).with(doc, options)
|
|
114
|
+
collection.save(doc, options)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "converts the doc to bson" do
|
|
118
|
+
doc.should_receive(:to_bson)
|
|
119
|
+
mongo_collection.stub(:save)
|
|
120
|
+
collection.save(doc)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "returns the delegates result" do
|
|
124
|
+
result = 'result'
|
|
125
|
+
mongo_collection.stub(:save).and_return(result)
|
|
126
|
+
collection.save(doc).should == result
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "#update" do
|
|
131
|
+
let(:spec) { {'sample' => 'old'} }
|
|
132
|
+
|
|
133
|
+
let(:doc) { {'sample' => 'data'} }
|
|
134
|
+
|
|
135
|
+
let(:options) { {:safe => false} }
|
|
136
|
+
|
|
137
|
+
before do
|
|
138
|
+
collection.stub(:last_error).and_return('updatedExisting' => true)
|
|
139
|
+
mongo_collection.stub(:update)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "delegates to the Mongo::Collection" do
|
|
143
|
+
mongo_collection.should_receive(:update).with(spec, doc, options)
|
|
144
|
+
collection.update(spec, doc, options)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "converts the doc to bson" do
|
|
148
|
+
doc.should_receive(:to_bson)
|
|
149
|
+
collection.update(spec, doc, options)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "gets the last error from the database" do
|
|
153
|
+
collection.should_receive(:last_error)
|
|
154
|
+
collection.update(spec, doc, options)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "returns the updateExisting value of get last error" do
|
|
158
|
+
result = 'check'
|
|
159
|
+
collection.stub(:last_error).and_return({'updatedExisting' => result})
|
|
160
|
+
collection.update(spec, doc, options).should == result
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "returns false otherwise" do
|
|
164
|
+
collection.stub(:last_error)
|
|
165
|
+
collection.update(spec, doc, options).should be_false
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|