mongo_doc 0.3.0
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 +7 -0
- data/LICENSE +20 -0
- data/README.textile +174 -0
- data/Rakefile +135 -0
- data/TODO +31 -0
- data/VERSION +1 -0
- data/data/.gitignore +2 -0
- data/examples/simple_document.rb +35 -0
- data/examples/simple_object.rb +30 -0
- data/features/finders.feature +76 -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 +105 -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 +14 -0
- data/features/step_definitions/document_steps.rb +149 -0
- data/features/step_definitions/documents.rb +30 -0
- data/features/step_definitions/finder_steps.rb +15 -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 +32 -0
- data/features/step_definitions/query_steps.rb +54 -0
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/step_definitions/scope_steps.rb +18 -0
- data/features/step_definitions/util_steps.rb +7 -0
- data/features/support/support.rb +10 -0
- data/features/using_criteria.feature +128 -0
- data/lib/mongo_doc/associations/collection_proxy.rb +105 -0
- data/lib/mongo_doc/associations/document_proxy.rb +56 -0
- data/lib/mongo_doc/associations/hash_proxy.rb +98 -0
- data/lib/mongo_doc/associations/proxy_base.rb +53 -0
- data/lib/mongo_doc/attributes.rb +140 -0
- data/lib/mongo_doc/bson.rb +45 -0
- data/lib/mongo_doc/collection.rb +55 -0
- data/lib/mongo_doc/connection.rb +88 -0
- data/lib/mongo_doc/contexts/enumerable.rb +128 -0
- data/lib/mongo_doc/contexts/ids.rb +41 -0
- data/lib/mongo_doc/contexts/mongo.rb +232 -0
- data/lib/mongo_doc/contexts.rb +25 -0
- data/lib/mongo_doc/criteria.rb +38 -0
- data/lib/mongo_doc/cursor.rb +32 -0
- data/lib/mongo_doc/document.rb +216 -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 +11 -0
- data/lib/mongo_doc/ext/date.rb +16 -0
- data/lib/mongo_doc/ext/date_time.rb +13 -0
- data/lib/mongo_doc/ext/dbref.rb +7 -0
- data/lib/mongo_doc/ext/hash.rb +7 -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 +17 -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 +5 -0
- data/lib/mongo_doc/finders.rb +49 -0
- data/lib/mongo_doc/matchers.rb +35 -0
- data/lib/mongo_doc/query.rb +7 -0
- data/lib/mongo_doc/scope.rb +64 -0
- data/lib/mongo_doc/validations/macros.rb +11 -0
- data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
- data/lib/mongo_doc.rb +19 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +247 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +92 -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.gemspec +205 -0
- data/mongod.example.yml +2 -0
- data/mongodb.example.yml +14 -0
- data/perf/mongo_doc_runner.rb +90 -0
- data/perf/ruby_driver_runner.rb +64 -0
- data/script/console +8 -0
- data/spec/associations/collection_proxy_spec.rb +200 -0
- data/spec/associations/document_proxy_spec.rb +42 -0
- data/spec/associations/hash_proxy_spec.rb +163 -0
- data/spec/attributes_spec.rb +273 -0
- data/spec/bson_matchers.rb +54 -0
- data/spec/bson_spec.rb +196 -0
- data/spec/collection_spec.rb +161 -0
- data/spec/connection_spec.rb +147 -0
- data/spec/contexts/enumerable_spec.rb +274 -0
- data/spec/contexts/ids_spec.rb +49 -0
- data/spec/contexts/mongo_spec.rb +198 -0
- data/spec/contexts_spec.rb +28 -0
- data/spec/criteria_spec.rb +33 -0
- data/spec/cursor_spec.rb +91 -0
- data/spec/document_ext.rb +9 -0
- data/spec/document_spec.rb +664 -0
- data/spec/embedded_save_spec.rb +109 -0
- data/spec/finders_spec.rb +73 -0
- data/spec/hash_matchers.rb +27 -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/query_spec.rb +12 -0
- data/spec/scope_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +13 -0
- metadata +290 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Saving embedded documents" do
|
|
4
|
+
class NestedDocsRoot
|
|
5
|
+
include MongoDoc::Document
|
|
6
|
+
|
|
7
|
+
has_many :nested_children
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class NestedChild
|
|
11
|
+
include MongoDoc::Document
|
|
12
|
+
|
|
13
|
+
has_one :leaf
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class LeafDoc
|
|
17
|
+
include MongoDoc::Document
|
|
18
|
+
|
|
19
|
+
key :data
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:leaf) do
|
|
23
|
+
doc = LeafDoc.new
|
|
24
|
+
doc._id = 'id'
|
|
25
|
+
doc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
let(:data) { 'data' }
|
|
29
|
+
|
|
30
|
+
context "#save" do
|
|
31
|
+
let(:root) { NestedDocsRoot.new(:nested_children => [NestedChild.new(:leaf => leaf)]) }
|
|
32
|
+
|
|
33
|
+
it "calls the root document's save" do
|
|
34
|
+
root.should_receive(:save).with(true)
|
|
35
|
+
leaf.save
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "(with bang!) calls the root documents save!" do
|
|
39
|
+
root.should_receive(:save!)
|
|
40
|
+
leaf.save!
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "update_attributes naive" do
|
|
45
|
+
context "with no has_many, update_attributes" do
|
|
46
|
+
let(:root) { NestedChild.new(:leaf => leaf) }
|
|
47
|
+
|
|
48
|
+
it "calls the root document's _naive_update_attributes with a full attribute path and not safe" do
|
|
49
|
+
root.should_receive(:_naive_update_attributes).with({'leaf.data' => data}, false)
|
|
50
|
+
leaf.update_attributes(:data => data)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "(with bang!) calls the root document's _naive_update_attributes with a full attribute path and safe" do
|
|
54
|
+
root.should_receive(:_naive_update_attributes).with({'leaf.data' => data}, true)
|
|
55
|
+
leaf.update_attributes!(:data => data)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "with has_many, update_attributes" do
|
|
60
|
+
let(:root) { NestedDocsRoot.new(:nested_children => [NestedChild.new(:leaf => leaf)]) }
|
|
61
|
+
|
|
62
|
+
it "calls the root document's _naive_update_attributes with a full attribute path and not safe" do
|
|
63
|
+
root.should_receive(:_naive_update_attributes).with({'nested_children.0.leaf.data' => data}, false)
|
|
64
|
+
leaf.update_attributes(:data => data)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "(with bang!) calls the root document's _naive_update_attributes with a full attribute path and safe" do
|
|
68
|
+
root.should_receive(:_naive_update_attributes).with({'nested_children.0.leaf.data' => data}, true)
|
|
69
|
+
leaf.update_attributes!(:data => data)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "update_attributes strict" do
|
|
75
|
+
let(:leaf_id) { 'leaf_id' }
|
|
76
|
+
|
|
77
|
+
before do
|
|
78
|
+
leaf.stub(:_id).and_return(leaf_id)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "with no has_many, update_attributes" do
|
|
82
|
+
let(:root) { NestedChild.new(:leaf => leaf) }
|
|
83
|
+
|
|
84
|
+
it "calls the root document's _strict_update_attributes with a full attribute path and not safe" do
|
|
85
|
+
root.should_receive(:_strict_update_attributes).with({'leaf.data' => data}, false, 'leaf._id' => leaf_id)
|
|
86
|
+
leaf.update_attributes(:data => data, :__strict__ => true)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "(with bang!) calls the root document's _naive_update_attributes with a full attribute path and safe" do
|
|
90
|
+
root.should_receive(:_strict_update_attributes).with({'leaf.data' => data}, true, 'leaf._id' => leaf_id)
|
|
91
|
+
leaf.update_attributes!(:data => data, :__strict__ => true)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "with has_many, update_attributes" do
|
|
96
|
+
let(:root) { NestedDocsRoot.new(:nested_children => [NestedChild.new(:leaf => leaf)]) }
|
|
97
|
+
|
|
98
|
+
it "calls the root document's _naive_update_attributes with a full attribute path and not safe" do
|
|
99
|
+
root.should_receive(:_strict_update_attributes).with({'nested_children.0.leaf.data' => data}, false, 'nested_children.0.leaf._id' => leaf_id)
|
|
100
|
+
leaf.update_attributes(:data => data, :__strict__ => true)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "(with bang!) calls the root document's _naive_update_attributes with a full attribute path and safe" do
|
|
104
|
+
root.should_receive(:_strict_update_attributes).with({'nested_children.0.leaf.data' => data}, true, 'nested_children.0.leaf._id' => leaf_id)
|
|
105
|
+
leaf.update_attributes!(:data => data, :__strict__ => true)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper.rb"))
|
|
2
|
+
|
|
3
|
+
describe MongoDoc::Finders do
|
|
4
|
+
class FindersTest
|
|
5
|
+
include MongoDoc::Document
|
|
6
|
+
|
|
7
|
+
key :data
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:criteria) { stub('criteria').as_null_object }
|
|
11
|
+
|
|
12
|
+
context ".find" do
|
|
13
|
+
before do
|
|
14
|
+
FindersTest.stub(:criteria).and_return(criteria)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "delegates to id for the criteria" do
|
|
18
|
+
args = [1, 2, 3]
|
|
19
|
+
criteria.should_receive(:id).with(*args)
|
|
20
|
+
FindersTest.find(*args)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context ".find_all" do
|
|
25
|
+
it "delegates to an empty criteria" do
|
|
26
|
+
FindersTest.should_receive(:criteria)
|
|
27
|
+
FindersTest.find_all
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "returns the empty criteria" do
|
|
31
|
+
FindersTest.stub(:criteria).and_return(criteria)
|
|
32
|
+
FindersTest.find_all.should == criteria
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context ".find_one" do
|
|
37
|
+
context "with an id" do
|
|
38
|
+
it "delegates to translate" do
|
|
39
|
+
id = 'an id'
|
|
40
|
+
Mongoid::Criteria.should_receive(:translate).with(FindersTest, id)
|
|
41
|
+
FindersTest.find_one(id)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "with conditions" do
|
|
46
|
+
let(:conditions) { {:where => 'this.a > 3'} }
|
|
47
|
+
|
|
48
|
+
it "calls translate with the conditions" do
|
|
49
|
+
Mongoid::Criteria.should_receive(:translate).with(FindersTest, conditions).and_return(criteria)
|
|
50
|
+
FindersTest.find_one(conditions)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "call one on the result" do
|
|
54
|
+
Mongoid::Criteria.stub(:translate).and_return(criteria)
|
|
55
|
+
criteria.should_receive(:one)
|
|
56
|
+
FindersTest.find_one(conditions)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "all other finders" do
|
|
62
|
+
before do
|
|
63
|
+
FindersTest.stub(:criteria).and_return(criteria)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
%w(count first last).each do |which|
|
|
67
|
+
it "calls #{which} on the new criteria" do
|
|
68
|
+
criteria.should_receive(which)
|
|
69
|
+
FindersTest.send(which)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class HasEntry
|
|
2
|
+
def initialize(expected)
|
|
3
|
+
@expected = expected
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def matches?(target)
|
|
7
|
+
@target = target
|
|
8
|
+
@expected.all? do |key, value|
|
|
9
|
+
@target[key] == value
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def failure_message_for_should
|
|
14
|
+
"expected #{@target.inspect} to have entries #{@expected.inspect}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def failure_message_for_should_not
|
|
18
|
+
"expected #{@target.inspect} not to have entries #{@expected.inspect}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module HashMatchers
|
|
23
|
+
def has_entry(expected)
|
|
24
|
+
HasEntry.new(expected)
|
|
25
|
+
end
|
|
26
|
+
alias :has_entries :has_entry
|
|
27
|
+
end
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe MongoDoc::Matchers do
|
|
4
|
+
|
|
5
|
+
class Address
|
|
6
|
+
include MongoDoc::Matchers
|
|
7
|
+
|
|
8
|
+
attr_accessor :number
|
|
9
|
+
attr_accessor :services
|
|
10
|
+
attr_accessor :street
|
|
11
|
+
|
|
12
|
+
def initialize(attrs = {})
|
|
13
|
+
attrs.each {|key, value| send("#{key}=", value)}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "#matches?" do
|
|
18
|
+
|
|
19
|
+
context "when performing simple matching" do
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
@document = Address.new(:street => "Clarkenwell Road")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "when the attributes match" do
|
|
26
|
+
|
|
27
|
+
before do
|
|
28
|
+
@selector = { :street => "Clarkenwell Road" }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "returns true" do
|
|
32
|
+
@document.matches?(@selector).should be_true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "when the attributes dont match" do
|
|
38
|
+
|
|
39
|
+
before do
|
|
40
|
+
@selector = { :street => "Broadway Ave" }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "returns false" do
|
|
44
|
+
@document.matches?(@selector).should be_false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "when performing complex matching" do
|
|
52
|
+
|
|
53
|
+
before do
|
|
54
|
+
@document = Address.new(:services => ["first", "second"], :number => 100)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "with an $all selector" do
|
|
58
|
+
|
|
59
|
+
context "when the attributes match" do
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
@selector = { :services => { "$all" => [ "first", "second" ] } }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "returns true" do
|
|
66
|
+
@document.matches?(@selector).should be_true
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "when the attributes do not match" do
|
|
72
|
+
|
|
73
|
+
before do
|
|
74
|
+
@selector = { :services => { "$all" => [ "first" ] } }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "returns false" do
|
|
78
|
+
@document.matches?(@selector).should be_false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "with an $exists selector" do
|
|
86
|
+
|
|
87
|
+
context "when the attributes match" do
|
|
88
|
+
|
|
89
|
+
before do
|
|
90
|
+
@selector = { :services => { "$exists" => true } }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "returns true" do
|
|
94
|
+
@document.matches?(@selector).should be_true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "when the attributes do not match" do
|
|
100
|
+
|
|
101
|
+
before do
|
|
102
|
+
@selector = { :services => { "$exists" => false } }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "returns false" do
|
|
106
|
+
@document.matches?(@selector).should be_false
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "with a $gt selector" do
|
|
114
|
+
|
|
115
|
+
context "when the attributes match" do
|
|
116
|
+
|
|
117
|
+
before do
|
|
118
|
+
@selector = { :number => { "$gt" => 50 } }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "returns true" do
|
|
122
|
+
@document.matches?(@selector).should be_true
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "when the attributes do not match" do
|
|
128
|
+
|
|
129
|
+
before do
|
|
130
|
+
@selector = { :number => { "$gt" => 200 } }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "returns false" do
|
|
134
|
+
@document.matches?(@selector).should be_false
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context "with a $gte selector" do
|
|
142
|
+
|
|
143
|
+
context "when the attributes match" do
|
|
144
|
+
|
|
145
|
+
before do
|
|
146
|
+
@selector = { :number => { "$gte" => 100 } }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "returns true" do
|
|
150
|
+
@document.matches?(@selector).should be_true
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
context "when the attributes do not match" do
|
|
156
|
+
|
|
157
|
+
before do
|
|
158
|
+
@selector = { :number => { "$gte" => 200 } }
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "returns false" do
|
|
162
|
+
@document.matches?(@selector).should be_false
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
context "with an $in selector" do
|
|
170
|
+
|
|
171
|
+
context "when the attributes match" do
|
|
172
|
+
|
|
173
|
+
before do
|
|
174
|
+
@selector = { :number => { "$in" => [ 100, 200 ] } }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "returns true" do
|
|
178
|
+
@document.matches?(@selector).should be_true
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context "when the attributes do not match" do
|
|
184
|
+
|
|
185
|
+
before do
|
|
186
|
+
@selector = { :number => { "$in" => [ 200, 300 ] } }
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "returns false" do
|
|
190
|
+
@document.matches?(@selector).should be_false
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
context "with a $lt selector" do
|
|
198
|
+
|
|
199
|
+
context "when the attributes match" do
|
|
200
|
+
|
|
201
|
+
before do
|
|
202
|
+
@selector = { :number => { "$lt" => 200 } }
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "returns true" do
|
|
206
|
+
@document.matches?(@selector).should be_true
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
context "when the attributes do not match" do
|
|
212
|
+
|
|
213
|
+
before do
|
|
214
|
+
@selector = { :number => { "$lt" => 50 } }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it "returns false" do
|
|
218
|
+
@document.matches?(@selector).should be_false
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
context "with a $lte selector" do
|
|
226
|
+
|
|
227
|
+
context "when the attributes match" do
|
|
228
|
+
|
|
229
|
+
before do
|
|
230
|
+
@selector = { :number => { "$lte" => 200 } }
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "returns true" do
|
|
234
|
+
@document.matches?(@selector).should be_true
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
context "when the attributes do not match" do
|
|
240
|
+
|
|
241
|
+
before do
|
|
242
|
+
@selector = { :number => { "$lte" => 50 } }
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it "returns false" do
|
|
246
|
+
@document.matches?(@selector).should be_false
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
context "with an $ne selector" do
|
|
254
|
+
|
|
255
|
+
context "when the attributes match" do
|
|
256
|
+
|
|
257
|
+
before do
|
|
258
|
+
@selector = { :number => { "$ne" => 200 } }
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "returns true" do
|
|
262
|
+
@document.matches?(@selector).should be_true
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context "when the attributes do not match" do
|
|
268
|
+
|
|
269
|
+
before do
|
|
270
|
+
@selector = { :number => { "$ne" => 100 } }
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "returns false" do
|
|
274
|
+
@document.matches?(@selector).should be_false
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
context "with a $nin selector" do
|
|
282
|
+
|
|
283
|
+
context "when the attributes match" do
|
|
284
|
+
|
|
285
|
+
before do
|
|
286
|
+
@selector = { :number => { "$nin" => [ 1, 2, 3 ] } }
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "returns true" do
|
|
290
|
+
@document.matches?(@selector).should be_true
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
context "when the attributes do not match" do
|
|
296
|
+
|
|
297
|
+
before do
|
|
298
|
+
@selector = { :number => { "$nin" => [ 100 ] } }
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "returns false" do
|
|
302
|
+
@document.matches?(@selector).should be_false
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
context "with a $size selector" do
|
|
310
|
+
|
|
311
|
+
context "when the attributes match" do
|
|
312
|
+
|
|
313
|
+
before do
|
|
314
|
+
@selector = { :services => { "$size" => 2 } }
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "returns true" do
|
|
318
|
+
@document.matches?(@selector).should be_true
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
context "when the attributes do not match" do
|
|
324
|
+
|
|
325
|
+
before do
|
|
326
|
+
@selector = { :services => { "$size" => 5 } }
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it "returns false" do
|
|
330
|
+
@document.matches?(@selector).should be_false
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
end
|
|
342
|
+
|
data/spec/mongodb.yml
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "MongoDoc::Document _id and #new_record?" do
|
|
4
|
+
class Child
|
|
5
|
+
include MongoDoc::Document
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class Parent
|
|
9
|
+
include MongoDoc::Document
|
|
10
|
+
|
|
11
|
+
has_one :child
|
|
12
|
+
has_many :children
|
|
13
|
+
|
|
14
|
+
key :data
|
|
15
|
+
|
|
16
|
+
validates_presence_of :data
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:id) { 'id' }
|
|
20
|
+
let(:collection) { stub('collection', :save => id) }
|
|
21
|
+
let(:child) { Child.new }
|
|
22
|
+
|
|
23
|
+
context "as a has_one child" do
|
|
24
|
+
it "when added to the parent is a new record" do
|
|
25
|
+
Parent.new(:data => 'data', :child => child)
|
|
26
|
+
child.should be_new_record
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "saving" do
|
|
30
|
+
before do
|
|
31
|
+
Parent.stub(:collection).and_return(collection)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "#save" do
|
|
35
|
+
it "when saved is not a new record" do
|
|
36
|
+
parent = Parent.new(:data => 'data', :child => child)
|
|
37
|
+
parent.save
|
|
38
|
+
child.should_not be_new_record
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "if parent is invalid, remains a new record" do
|
|
42
|
+
parent = Parent.new(:child => child)
|
|
43
|
+
parent.save
|
|
44
|
+
child.should be_new_record
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "#save!" do
|
|
49
|
+
it "when saved is not a new record" do
|
|
50
|
+
parent = Parent.new(:data => 'data', :child => child)
|
|
51
|
+
parent.save!
|
|
52
|
+
child.should_not be_new_record
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "if parent is invalid, remains a new record" do
|
|
56
|
+
parent = Parent.new(:child => child)
|
|
57
|
+
parent.save! rescue nil
|
|
58
|
+
child.should be_new_record
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "when db error is raised, remains a new record" do
|
|
62
|
+
collection.stub(:save).and_raise(Mongo::OperationFailure)
|
|
63
|
+
parent = Parent.new(:data => 'data', :child => child)
|
|
64
|
+
expect do
|
|
65
|
+
parent.save!
|
|
66
|
+
end.should raise_error(Mongo::OperationFailure)
|
|
67
|
+
child.should be_new_record
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "as a has_many child" do
|
|
74
|
+
it "when added to the parent is a new record" do
|
|
75
|
+
parent = Parent.new(:data => 'data')
|
|
76
|
+
parent.children << child
|
|
77
|
+
child.should be_new_record
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context "saving" do
|
|
81
|
+
before do
|
|
82
|
+
Parent.stub(:collection).and_return(collection)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "#save" do
|
|
86
|
+
it "when saved is not a new record" do
|
|
87
|
+
parent = Parent.new(:data => 'data')
|
|
88
|
+
parent.children << child
|
|
89
|
+
parent.save
|
|
90
|
+
child.should_not be_new_record
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "if parent is invalid, remains a new record" do
|
|
94
|
+
parent = Parent.new
|
|
95
|
+
parent.children << child
|
|
96
|
+
parent.save
|
|
97
|
+
child.should be_new_record
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context "#save!" do
|
|
102
|
+
it "when saved is not a new record" do
|
|
103
|
+
parent = Parent.new(:data => 'data')
|
|
104
|
+
parent.children << child
|
|
105
|
+
parent.save!
|
|
106
|
+
child.should_not be_new_record
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "if parent is invalid, remains a new record" do
|
|
110
|
+
parent = Parent.new
|
|
111
|
+
parent.children << child
|
|
112
|
+
parent.save! rescue nil
|
|
113
|
+
child.should be_new_record
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "when db error is raised, remains a new record" do
|
|
117
|
+
collection.stub(:save).and_raise(Mongo::OperationFailure)
|
|
118
|
+
parent = Parent.new(:data => 'data')
|
|
119
|
+
parent.children << child
|
|
120
|
+
expect do
|
|
121
|
+
parent.save!
|
|
122
|
+
end.should raise_error(Mongo::OperationFailure)
|
|
123
|
+
child.should be_new_record
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
data/spec/query_spec.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Query support for MongoDoc" do
|
|
4
|
+
describe "#set_modifier" do
|
|
5
|
+
it "modifies all simple key/values of the hash to a set modifier" do
|
|
6
|
+
key = 'key'
|
|
7
|
+
value = 'value'
|
|
8
|
+
hash = {key => value}
|
|
9
|
+
MongoDoc::Query.set_modifier(hash).should == {'$set' => hash}
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|