mongo_doc 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.md +4 -0
- data/README.textile +5 -1
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/features/partial_updates.feature +13 -23
- data/features/step_definitions/partial_update_steps.rb +1 -2
- data/lib/mongo_doc/associations/collection_proxy.rb +2 -2
- data/lib/mongo_doc/associations/hash_proxy.rb +1 -1
- data/lib/mongo_doc/associations/proxy_base.rb +3 -3
- data/lib/mongo_doc/attributes.rb +2 -2
- data/lib/mongo_doc/connection.rb +1 -1
- data/lib/mongo_doc/document.rb +3 -21
- data/lib/mongo_doc.rb +1 -1
- data/mongo_doc.gemspec +12 -9
- data/spec/array_including_argument_matcher.rb +62 -0
- data/spec/associations/collection_proxy_spec.rb +11 -1
- data/spec/associations/hash_proxy_spec.rb +6 -1
- data/spec/connection_spec.rb +2 -2
- data/spec/document_spec.rb +67 -172
- data/spec/embedded_save_spec.rb +9 -45
- data/spec/index_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -0
- metadata +10 -5
data/HISTORY.md
ADDED
data/README.textile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
h1. MongoDoc
|
2
2
|
|
3
|
-
Version: Turbulence (0.4.
|
3
|
+
Version: Turbulence (0.4.2) 2010/03/23
|
4
|
+
|
5
|
+
h2. What's New in Turbulence (0.4.2)
|
6
|
+
|
7
|
+
Support for the $ positional operator for in-place array updates. This requires MongoDB version 1.3.4 or higher.
|
4
8
|
|
5
9
|
h2. What's New in Turbulence (0.4.1)
|
6
10
|
|
data/Rakefile
CHANGED
@@ -10,8 +10,8 @@ begin
|
|
10
10
|
gem.homepage = "http://github.com/leshill/mongodoc"
|
11
11
|
gem.authors = ["Les Hill"]
|
12
12
|
gem.add_dependency "activesupport", ">= 2.3.4"
|
13
|
-
gem.add_dependency "mongo", "= 0.19"
|
14
|
-
gem.add_dependency "mongo_ext", "= 0.19"
|
13
|
+
gem.add_dependency "mongo", "= 0.19.1"
|
14
|
+
gem.add_dependency "mongo_ext", "= 0.19.1"
|
15
15
|
gem.add_dependency "durran-validatable", "= 2.0.1"
|
16
16
|
gem.add_dependency "leshill-will_paginate", "= 2.3.11"
|
17
17
|
gem.add_development_dependency "rspec", "= 1.3.0"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.2
|
@@ -59,47 +59,37 @@ Feature: Partial Updates
|
|
59
59
|
| 1 Main St. | Jacksonville | FL | 32218 |
|
60
60
|
And I save the document 'hashrocket_hq'
|
61
61
|
|
62
|
-
Scenario:
|
62
|
+
Scenario: Update
|
63
63
|
When I update the 'note' for 'contractor' to 'Knows MongoDB and MongoDoc'
|
64
|
-
Then the
|
64
|
+
Then the last return value is true
|
65
|
+
And the document 'contractor' roundtrips
|
65
66
|
|
66
|
-
Scenario:
|
67
|
+
Scenario: Update on a has one
|
67
68
|
When I update the 'street' for 'hq_address' to '320 1st Street North'
|
68
|
-
Then the
|
69
|
+
Then the last return value is true
|
70
|
+
And the document 'hashrocket_hq' roundtrips
|
69
71
|
|
70
|
-
Scenario:
|
72
|
+
Scenario: Update on a has many
|
71
73
|
When 'hq_address' is the first address of 'hashrocket'
|
72
74
|
And I update the 'street' for 'hq_address' to '320 1st Street North'
|
73
|
-
Then the
|
75
|
+
Then the last return value is true
|
76
|
+
And the document 'hashrocket' roundtrips
|
74
77
|
|
75
|
-
Scenario:
|
76
|
-
When I strict update the 'note' for 'contractor' to 'Knows MongoDB and MongoDoc'
|
77
|
-
Then the document 'contractor' roundtrips
|
78
|
-
|
79
|
-
Scenario: Strict Update on a has one
|
80
|
-
When I strict update the 'street' for 'hq_address' to '320 1st Street North'
|
81
|
-
Then the document 'hashrocket_hq' roundtrips
|
82
|
-
|
83
|
-
Scenario: Strict Update on a has many
|
84
|
-
When 'hq_address' is the first address of 'hashrocket'
|
85
|
-
And I strict update the 'street' for 'hq_address' to '320 1st Street North'
|
86
|
-
Then the document 'hashrocket' roundtrips
|
87
|
-
|
88
|
-
Scenario: Failing Strict Update on a has one
|
78
|
+
Scenario: Failing Update on a has one
|
89
79
|
When someone else changes the Address 'address' of 'hashrocket_hq' to
|
90
80
|
| Street | City | State | Zip Code |
|
91
81
|
| 1 Ocean Blvd. | Jacksonville | FL | 32218 |
|
92
|
-
And I
|
82
|
+
And I update the 'street' for 'hq_address' to '320 1st Street North'
|
93
83
|
Then the last return value is false
|
94
84
|
And the document 'hashrocket_hq' does not roundtrip
|
95
85
|
|
96
|
-
Scenario: Failing
|
86
|
+
Scenario: Failing Update on a has many
|
97
87
|
When 'hq_address' is the first address of 'hashrocket'
|
98
88
|
And someone else changes the addresses of 'hashrocket':
|
99
89
|
| Street | City | State | Zip Code |
|
100
90
|
| 320 1st N, #712 | Jacksonville Beach | FL | 32250 |
|
101
91
|
| 1001 Mulligan Street | Chicago | IL | 60611 |
|
102
92
|
| 345 Avenida Grande | Santiago | Chile | |
|
103
|
-
And I
|
93
|
+
And I update the 'street' for 'hq_address' to '320 1st Street North'
|
104
94
|
Then the last return value is false
|
105
95
|
And the document 'hashrocket' does not roundtrip
|
@@ -1,7 +1,6 @@
|
|
1
|
-
When /^I
|
1
|
+
When /^I update the '(.+)' for '(.+)' to '(.+)'$/ do |attr, doc_name, value|
|
2
2
|
doc = instance_variable_get("@#{doc_name}")
|
3
3
|
attrs = {attr => value}
|
4
|
-
attrs.merge!(:__strict__ => true) unless strict.blank?
|
5
4
|
@last_return = doc.update_attributes(attrs)
|
6
5
|
end
|
7
6
|
|
@@ -92,8 +92,8 @@ module MongoDoc
|
|
92
92
|
|
93
93
|
protected
|
94
94
|
|
95
|
-
def annotated_keys(src, attrs)
|
96
|
-
assoc_path = "#{assoc_name}
|
95
|
+
def annotated_keys(src, attrs, selector = false)
|
96
|
+
assoc_path = "#{assoc_name}" + (selector ? "" : ".$")
|
97
97
|
annotated = {}
|
98
98
|
attrs.each do |(key, value)|
|
99
99
|
annotated["#{assoc_path}.#{key}"] = value
|
@@ -11,8 +11,8 @@ module MongoDoc
|
|
11
11
|
@_parent = parent
|
12
12
|
end
|
13
13
|
|
14
|
-
def _path_to_root(src, attrs)
|
15
|
-
_parent._path_to_root(src, annotated_keys(src, attrs))
|
14
|
+
def _path_to_root(src, attrs, selector = false)
|
15
|
+
_parent._path_to_root(src, annotated_keys(src, attrs, selector), selector)
|
16
16
|
end
|
17
17
|
|
18
18
|
def _root=(root)
|
@@ -37,7 +37,7 @@ module MongoDoc
|
|
37
37
|
|
38
38
|
protected
|
39
39
|
|
40
|
-
def annotated_keys(src, hash)
|
40
|
+
def annotated_keys(src, hash, selector = false)
|
41
41
|
annotated = {}
|
42
42
|
hash.each do |(key, value)|
|
43
43
|
annotated["#{assoc_name}.#{key}"] = value
|
data/lib/mongo_doc/attributes.rb
CHANGED
@@ -40,9 +40,9 @@ module MongoDoc
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
def _path_to_root(src, attrs)
|
43
|
+
def _path_to_root(src, attrs, selector = false)
|
44
44
|
return attrs unless _parent
|
45
|
-
_parent._path_to_root(self, attrs)
|
45
|
+
_parent._path_to_root(self, attrs, selector)
|
46
46
|
end
|
47
47
|
|
48
48
|
module ClassMethods
|
data/lib/mongo_doc/connection.rb
CHANGED
@@ -82,7 +82,7 @@ module MongoDoc
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def verify_server_version(connection)
|
85
|
-
raise UnsupportedServerVersionError.new('MongoDoc requires at least mongoDB version 1.3.2') unless connection.server_version >= "1.3.
|
85
|
+
raise UnsupportedServerVersionError.new('MongoDoc requires at least mongoDB version 1.3.2') unless connection.server_version >= "1.3.4"
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
data/lib/mongo_doc/document.rb
CHANGED
@@ -80,15 +80,10 @@ module MongoDoc
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def update_attributes(attrs)
|
83
|
-
strict = attrs.delete(:__strict__)
|
84
83
|
self.attributes = attrs
|
85
84
|
return save if new_record?
|
86
85
|
return false unless valid?
|
87
|
-
|
88
|
-
_strict_update_attributes(_path_to_root(self, attrs), false)
|
89
|
-
else
|
90
|
-
_naive_update_attributes(_path_to_root(self, attrs), false)
|
91
|
-
end
|
86
|
+
_update({}, attrs, false)
|
92
87
|
end
|
93
88
|
|
94
89
|
def update_attributes!(attrs)
|
@@ -96,11 +91,7 @@ module MongoDoc
|
|
96
91
|
self.attributes = attrs
|
97
92
|
return save! if new_record?
|
98
93
|
raise DocumentInvalidError unless valid?
|
99
|
-
|
100
|
-
_strict_update_attributes(_path_to_root(self, attrs), true)
|
101
|
-
else
|
102
|
-
_naive_update_attributes(_path_to_root(self, attrs), true)
|
103
|
-
end
|
94
|
+
_update({}, attrs, true)
|
104
95
|
end
|
105
96
|
|
106
97
|
module ClassMethods
|
@@ -139,21 +130,12 @@ module MongoDoc
|
|
139
130
|
self.class.collection
|
140
131
|
end
|
141
132
|
|
142
|
-
def _naive_update_attributes(attrs, safe)
|
143
|
-
return _root.send(:_naive_update_attributes, attrs, safe) if _root
|
144
|
-
_update({}, attrs, safe)
|
145
|
-
end
|
146
|
-
|
147
133
|
def _remove
|
148
134
|
_collection.remove({'_id' => _id})
|
149
135
|
end
|
150
136
|
|
151
|
-
def _strict_update_attributes(attrs, safe, selector = {})
|
152
|
-
return _root.send(:_strict_update_attributes, attrs, safe, _path_to_root(self, '_id' => _id)) if _root
|
153
|
-
_update(selector, attrs, safe)
|
154
|
-
end
|
155
|
-
|
156
137
|
def _update(selector, data, safe)
|
138
|
+
return _root.send(:_update, _path_to_root(self, {'_id' => _id}, true), _path_to_root(self, data), safe) if _root
|
157
139
|
_collection.update({'_id' => _id}.merge(selector), MongoDoc::Query.set_modifier(data), :safe => safe)
|
158
140
|
end
|
159
141
|
|
data/lib/mongo_doc.rb
CHANGED
data/mongo_doc.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{mongo_doc}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Les Hill"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-23}
|
13
13
|
s.description = %q{ODM for MongoDB}
|
14
14
|
s.email = %q{leshill@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.files = [
|
21
21
|
".document",
|
22
22
|
".gitignore",
|
23
|
+
"HISTORY.md",
|
23
24
|
"LICENSE",
|
24
25
|
"README.textile",
|
25
26
|
"Rakefile",
|
@@ -120,6 +121,7 @@ Gem::Specification.new do |s|
|
|
120
121
|
"perf/mongo_doc_runner.rb",
|
121
122
|
"perf/ruby_driver_runner.rb",
|
122
123
|
"script/console",
|
124
|
+
"spec/array_including_argument_matcher.rb",
|
123
125
|
"spec/associations/collection_proxy_spec.rb",
|
124
126
|
"spec/associations/document_proxy_spec.rb",
|
125
127
|
"spec/associations/hash_proxy_spec.rb",
|
@@ -157,7 +159,8 @@ Gem::Specification.new do |s|
|
|
157
159
|
s.rubygems_version = %q{1.3.6}
|
158
160
|
s.summary = %q{ODM for MongoDB}
|
159
161
|
s.test_files = [
|
160
|
-
"spec/
|
162
|
+
"spec/array_including_argument_matcher.rb",
|
163
|
+
"spec/associations/collection_proxy_spec.rb",
|
161
164
|
"spec/associations/document_proxy_spec.rb",
|
162
165
|
"spec/associations/hash_proxy_spec.rb",
|
163
166
|
"spec/associations_spec.rb",
|
@@ -194,16 +197,16 @@ Gem::Specification.new do |s|
|
|
194
197
|
|
195
198
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
196
199
|
s.add_runtime_dependency(%q<activesupport>, [">= 2.3.4"])
|
197
|
-
s.add_runtime_dependency(%q<mongo>, ["= 0.19"])
|
198
|
-
s.add_runtime_dependency(%q<mongo_ext>, ["= 0.19"])
|
200
|
+
s.add_runtime_dependency(%q<mongo>, ["= 0.19.1"])
|
201
|
+
s.add_runtime_dependency(%q<mongo_ext>, ["= 0.19.1"])
|
199
202
|
s.add_runtime_dependency(%q<durran-validatable>, ["= 2.0.1"])
|
200
203
|
s.add_runtime_dependency(%q<leshill-will_paginate>, ["= 2.3.11"])
|
201
204
|
s.add_development_dependency(%q<rspec>, ["= 1.3.0"])
|
202
205
|
s.add_development_dependency(%q<cucumber>, ["= 0.6.2"])
|
203
206
|
else
|
204
207
|
s.add_dependency(%q<activesupport>, [">= 2.3.4"])
|
205
|
-
s.add_dependency(%q<mongo>, ["= 0.19"])
|
206
|
-
s.add_dependency(%q<mongo_ext>, ["= 0.19"])
|
208
|
+
s.add_dependency(%q<mongo>, ["= 0.19.1"])
|
209
|
+
s.add_dependency(%q<mongo_ext>, ["= 0.19.1"])
|
207
210
|
s.add_dependency(%q<durran-validatable>, ["= 2.0.1"])
|
208
211
|
s.add_dependency(%q<leshill-will_paginate>, ["= 2.3.11"])
|
209
212
|
s.add_dependency(%q<rspec>, ["= 1.3.0"])
|
@@ -211,8 +214,8 @@ Gem::Specification.new do |s|
|
|
211
214
|
end
|
212
215
|
else
|
213
216
|
s.add_dependency(%q<activesupport>, [">= 2.3.4"])
|
214
|
-
s.add_dependency(%q<mongo>, ["= 0.19"])
|
215
|
-
s.add_dependency(%q<mongo_ext>, ["= 0.19"])
|
217
|
+
s.add_dependency(%q<mongo>, ["= 0.19.1"])
|
218
|
+
s.add_dependency(%q<mongo_ext>, ["= 0.19.1"])
|
216
219
|
s.add_dependency(%q<durran-validatable>, ["= 2.0.1"])
|
217
220
|
s.add_dependency(%q<leshill-will_paginate>, ["= 2.3.11"])
|
218
221
|
s.add_dependency(%q<rspec>, ["= 1.3.0"])
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# From http://gist.github.com/62943
|
2
|
+
# Author http://github.com/trotter
|
3
|
+
module Spec
|
4
|
+
module Mocks
|
5
|
+
module ArgumentMatchers
|
6
|
+
|
7
|
+
class ArrayIncludingMatcher
|
8
|
+
# We'll allow an array of arguments to be passed in, so that you can do
|
9
|
+
# things like obj.should_receive(:blah).with(array_including('a', 'b'))
|
10
|
+
def initialize(*expected)
|
11
|
+
@expected = expected
|
12
|
+
end
|
13
|
+
|
14
|
+
# actual is the array (hopefully) passed to the method by the user.
|
15
|
+
# We'll check that it includes all the expected values, and return false
|
16
|
+
# if it doesn't or if we blow up because #include? is not defined.
|
17
|
+
def ==(actual)
|
18
|
+
@expected.each do |expected|
|
19
|
+
return false unless actual.include?(expected)
|
20
|
+
end
|
21
|
+
true
|
22
|
+
rescue NoMethodError => ex
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
def description
|
27
|
+
"array_including(#{@expected.join(', ')})"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ArrayNotIncludingMatcher
|
32
|
+
def initialize(*expected)
|
33
|
+
@expected = expected
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(actual)
|
37
|
+
@expected.each do |expected|
|
38
|
+
return false if actual.include?(expected)
|
39
|
+
end
|
40
|
+
true
|
41
|
+
rescue NoMethodError => ex
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
|
45
|
+
def description
|
46
|
+
"array_not_including(#{@expected.join(', ')})"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# array_including is a helpful wrapper that allows us to actually type
|
51
|
+
# #with(array_including(...)) instead of ArrayIncludingMatcher.new(...)
|
52
|
+
def array_including(*args)
|
53
|
+
ArrayIncludingMatcher.new(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def array_not_including(*args)
|
57
|
+
ArrayNotIncludingMatcher.new(*args)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -7,10 +7,20 @@ describe MongoDoc::Associations::CollectionProxy do
|
|
7
7
|
attr_accessor :name
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:root) {
|
10
|
+
let(:root) { CollectionProxyTest.new }
|
11
11
|
let(:proxy) { MongoDoc::Associations::CollectionProxy.new(:assoc_name => 'embed_many_name', :assoc_class => CollectionProxyTest, :root => root, :parent => root) }
|
12
12
|
let(:item) { CollectionProxyTest.new }
|
13
13
|
|
14
|
+
describe "#_path_to_root" do
|
15
|
+
it "inserts the association name and '$' when not a selector" do
|
16
|
+
proxy._path_to_root(CollectionProxyTest.new, 'name' => 'value').should == {"embed_many_name.$.name" => 'value'}
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inserts the association name when a selector" do
|
20
|
+
proxy._path_to_root(CollectionProxyTest.new, {'name' => 'value'}, true).should == {"embed_many_name.name" => 'value'}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
14
24
|
context "#<<" do
|
15
25
|
it "appends the item to the collection" do
|
16
26
|
(proxy << item).should include(item)
|
@@ -7,11 +7,16 @@ describe MongoDoc::Associations::HashProxy do
|
|
7
7
|
attr_accessor :name
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:root) {
|
10
|
+
let(:root) { HashProxyTest.new }
|
11
11
|
let(:proxy) { MongoDoc::Associations::HashProxy.new(:assoc_name => 'embed_hash_name', :assoc_class => HashProxyTest, :root => root, :parent => root) }
|
12
12
|
let(:item) { HashProxyTest.new }
|
13
13
|
let(:other_item) {[1,2]}
|
14
14
|
|
15
|
+
it "inserts the association name and key into the _path_to_root" do
|
16
|
+
proxy.stub(:index).and_return('key')
|
17
|
+
proxy._path_to_root(HashProxyTest.new, 'name' => 'value').should == {"embed_hash_name.key.name" => 'value'}
|
18
|
+
end
|
19
|
+
|
15
20
|
context "#[]=" do
|
16
21
|
it "adds the item to the hash" do
|
17
22
|
proxy['new'] = item
|
data/spec/connection_spec.rb
CHANGED
@@ -105,12 +105,12 @@ describe "MongoDoc::Connection.Connections" do
|
|
105
105
|
let(:connection) { stub('connection') }
|
106
106
|
|
107
107
|
it "raises when the server version is unsupported" do
|
108
|
-
connection.stub(:server_version).and_return(Mongo::ServerVersion.new('1.3.
|
108
|
+
connection.stub(:server_version).and_return(Mongo::ServerVersion.new('1.3.2'))
|
109
109
|
lambda { MongoDoc::Connection.send(:verify_server_version, connection) }.should raise_error(MongoDoc::UnsupportedServerVersionError)
|
110
110
|
end
|
111
111
|
|
112
112
|
it "returns when the server version is supported" do
|
113
|
-
connection.stub(:server_version).and_return(Mongo::ServerVersion.new('1.3.
|
113
|
+
connection.stub(:server_version).and_return(Mongo::ServerVersion.new('1.3.4'))
|
114
114
|
lambda { MongoDoc::Connection.send(:verify_server_version, connection) }.should_not raise_error(MongoDoc::UnsupportedServerVersionError)
|
115
115
|
end
|
116
116
|
end
|
data/spec/document_spec.rb
CHANGED
@@ -258,219 +258,114 @@ describe "MongoDoc::Document" do
|
|
258
258
|
end
|
259
259
|
|
260
260
|
context "updating attributes" do
|
261
|
-
class
|
261
|
+
class UpdateAttributesChild
|
262
262
|
include MongoDoc::Document
|
263
263
|
|
264
|
-
|
264
|
+
attr_accessor :child_data
|
265
265
|
end
|
266
266
|
|
267
|
-
class
|
267
|
+
class UpdateAttributes
|
268
268
|
include MongoDoc::Document
|
269
269
|
|
270
270
|
attr_accessor :data
|
271
|
+
embed :child
|
271
272
|
end
|
272
273
|
|
273
|
-
let(:
|
274
|
+
let(:collection) { stub(:update => nil) }
|
274
275
|
|
275
|
-
let(:
|
276
|
+
let(:new_doc) { UpdateAttributes.new }
|
276
277
|
|
277
|
-
let(:
|
278
|
-
|
279
|
-
|
280
|
-
doc
|
281
|
-
doc._id = 'id'
|
282
|
-
doc.stub(:_naive_update_attributes)
|
278
|
+
let(:existing_doc) do
|
279
|
+
doc = UpdateAttributes.new
|
280
|
+
doc._id = 'exists'
|
281
|
+
doc.stub(:_collection).and_return(collection)
|
283
282
|
doc
|
284
283
|
end
|
285
284
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
285
|
+
let(:child) do
|
286
|
+
child = UpdateAttributesChild.new
|
287
|
+
child._id = 'child exists'
|
288
|
+
existing_doc.child = child
|
289
|
+
child
|
290
290
|
end
|
291
291
|
|
292
|
-
|
293
|
-
it "delegates to save if the
|
294
|
-
|
295
|
-
|
296
|
-
doc.should_receive(:save).and_return(check)
|
297
|
-
doc.update_attributes(attrs).should == check
|
292
|
+
describe "#update_attributes" do
|
293
|
+
it "delegates to save if the doc is a new record" do
|
294
|
+
new_doc.should_receive(:save)
|
295
|
+
new_doc.update_attributes(:data => 'data')
|
298
296
|
end
|
299
297
|
|
300
|
-
|
301
|
-
doc.update_attributes(attrs)
|
302
|
-
doc.data.should == data
|
303
|
-
end
|
298
|
+
context "with an existing doc" do
|
304
299
|
|
305
|
-
|
306
|
-
doc.should_receive(:_path_to_root)
|
307
|
-
doc.update_attributes(attrs)
|
308
|
-
end
|
300
|
+
subject { existing_doc.update_attributes(:data => 'data') }
|
309
301
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
302
|
+
it "sets the attributes" do
|
303
|
+
subject
|
304
|
+
existing_doc.data.should == 'data'
|
305
|
+
end
|
314
306
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
307
|
+
it "validates the doc" do
|
308
|
+
existing_doc.should_receive(:valid?)
|
309
|
+
subject
|
310
|
+
end
|
319
311
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
strict_attrs = attrs.merge(:__strict__ => true)
|
324
|
-
doc.should_receive(:_strict_update_attributes).with(path_attrs, false)
|
325
|
-
doc.update_attributes(strict_attrs)
|
326
|
-
end
|
312
|
+
it "returns false if the doc is not valid" do
|
313
|
+
existing_doc.stub(:valid?).and_return(false)
|
314
|
+
should be_false
|
327
315
|
end
|
328
316
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
doc.update_attributes(attrs)
|
333
|
-
end
|
317
|
+
it "delegates to collection update" do
|
318
|
+
collection.should_receive(:update).with({'_id' => existing_doc._id}, {'$set' => {:data => 'data'}}, :safe => false)
|
319
|
+
subject
|
334
320
|
end
|
335
321
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
322
|
+
context "that is embedded" do
|
323
|
+
it "delegates to the root's collection update" do
|
324
|
+
collection.should_receive(:update).with({'_id' => existing_doc._id, 'child._id' => child._id}, {'$set' => {'child.child_data' => 'data'}}, :safe => false)
|
325
|
+
child.update_attributes(:child_data => 'data')
|
326
|
+
end
|
340
327
|
end
|
341
328
|
end
|
342
329
|
end
|
343
330
|
|
344
|
-
|
345
|
-
it "delegates to save! if the
|
346
|
-
|
347
|
-
|
348
|
-
doc.should_receive(:save!).and_return(check)
|
349
|
-
doc.update_attributes!(attrs).should == check
|
350
|
-
end
|
351
|
-
|
352
|
-
it "sets the attributes" do
|
353
|
-
doc.update_attributes!(attrs)
|
354
|
-
doc.data.should == data
|
331
|
+
describe "#update_attributes!" do
|
332
|
+
it "delegates to save! if the doc is a new record" do
|
333
|
+
new_doc.should_receive(:save!)
|
334
|
+
new_doc.update_attributes!(:data => 'data')
|
355
335
|
end
|
356
336
|
|
357
|
-
|
358
|
-
doc.should_receive(:_path_to_root)
|
359
|
-
doc.update_attributes!(attrs)
|
360
|
-
end
|
361
|
-
|
362
|
-
it "validates" do
|
363
|
-
doc.should_receive(:valid?).and_return(true)
|
364
|
-
doc.update_attributes!(attrs)
|
365
|
-
end
|
337
|
+
context "with an existing doc" do
|
366
338
|
|
367
|
-
|
368
|
-
doc.stub(:valid?).and_return(false)
|
369
|
-
expect do
|
370
|
-
doc.update_attributes!(attrs)
|
371
|
-
end.should raise_error(MongoDoc::DocumentInvalidError)
|
372
|
-
end
|
339
|
+
subject { existing_doc.update_attributes!(:data => 'data') }
|
373
340
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
strict_attrs = attrs.merge(:__strict__ => true)
|
378
|
-
doc.should_receive(:_strict_update_attributes).with(path_attrs, true)
|
379
|
-
doc.update_attributes!(strict_attrs)
|
380
|
-
end
|
341
|
+
it "sets the attributes" do
|
342
|
+
subject
|
343
|
+
existing_doc.data.should == 'data'
|
381
344
|
end
|
382
345
|
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
doc.update_attributes!(attrs)
|
387
|
-
end
|
346
|
+
it "validates the doc" do
|
347
|
+
existing_doc.should_receive(:valid?).and_return(true)
|
348
|
+
subject
|
388
349
|
end
|
389
350
|
|
390
|
-
it "
|
391
|
-
|
392
|
-
|
393
|
-
|
351
|
+
it "raises if not valid" do
|
352
|
+
existing_doc.stub(:valid?).and_return(false)
|
353
|
+
expect do
|
354
|
+
subject
|
355
|
+
end.should raise_error(MongoDoc::DocumentInvalidError)
|
394
356
|
end
|
395
|
-
end
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
context "#_naive_update_attributes" do
|
400
|
-
class NaiveUpdateAttributes
|
401
|
-
include MongoDoc::Document
|
402
|
-
end
|
403
|
-
|
404
357
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
let(:safe) { false }
|
410
|
-
|
411
|
-
let(:doc) do
|
412
|
-
doc = NaiveUpdateAttributes.new
|
413
|
-
doc.stub(:_id).and_return(id)
|
414
|
-
doc
|
415
|
-
end
|
416
|
-
|
417
|
-
it "without a root delegates to _update" do
|
418
|
-
doc.should_receive(:_update).with({}, attrs, safe)
|
419
|
-
doc.send(:_naive_update_attributes, attrs, safe)
|
420
|
-
end
|
421
|
-
|
422
|
-
it "with a root, calls _naive_update_attributes on the root" do
|
423
|
-
root = NaiveUpdateAttributes.new
|
424
|
-
doc.stub(:_root).and_return(root)
|
425
|
-
root.should_receive(:_naive_update_attributes).with(attrs, safe)
|
426
|
-
doc.send(:_naive_update_attributes, attrs, safe)
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
context "#_strict_update_attributes" do
|
431
|
-
class StrictUpdateAttributes
|
432
|
-
include MongoDoc::Document
|
433
|
-
end
|
434
|
-
|
435
|
-
let(:id) { 'id' }
|
436
|
-
|
437
|
-
let(:attrs) { {:data => 'data'} }
|
438
|
-
|
439
|
-
let(:selector) { {:selector => 'selector'} }
|
440
|
-
|
441
|
-
let(:safe) { false }
|
442
|
-
|
443
|
-
let(:doc) do
|
444
|
-
doc = StrictUpdateAttributes.new
|
445
|
-
doc.stub(:_id).and_return(id)
|
446
|
-
doc
|
447
|
-
end
|
448
|
-
|
449
|
-
context "without a root" do
|
450
|
-
it "without a root delegates to _update" do
|
451
|
-
doc.should_receive(:_update).with(selector, attrs, safe)
|
452
|
-
doc.send(:_strict_update_attributes, attrs, safe, selector)
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
context "with a root" do
|
457
|
-
let(:root) { StrictUpdateAttributes.new }
|
458
|
-
|
459
|
-
before do
|
460
|
-
doc.stub(:_root).and_return(root)
|
461
|
-
end
|
462
|
-
|
463
|
-
it "calls _path_to_root on our id" do
|
464
|
-
root.stub(:_strict_update_attributes)
|
465
|
-
doc.should_receive(:_path_to_root).with(doc, '_id' => id)
|
466
|
-
doc.send(:_strict_update_attributes, attrs, safe)
|
467
|
-
end
|
358
|
+
it "delegates to collection update" do
|
359
|
+
collection.should_receive(:update).with({'_id' => existing_doc._id}, {'$set' => {:data => 'data'}}, :safe => true)
|
360
|
+
subject
|
361
|
+
end
|
468
362
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
363
|
+
context "that is embedded" do
|
364
|
+
it "delegates to the root's collection update" do
|
365
|
+
collection.should_receive(:update).with({'_id' => existing_doc._id, 'child._id' => child._id}, {'$set' => {'child.child_data' => 'data'}}, :safe => true)
|
366
|
+
child.update_attributes!(:child_data => 'data')
|
367
|
+
end
|
368
|
+
end
|
474
369
|
end
|
475
370
|
end
|
476
371
|
end
|
data/spec/embedded_save_spec.rb
CHANGED
@@ -41,17 +41,17 @@ describe "Saving embedded documents" do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
context "update_attributes
|
44
|
+
context "update_attributes" do
|
45
45
|
context "with no embed_many, update_attributes" do
|
46
46
|
let(:root) { NestedChild.new(:leaf => leaf) }
|
47
47
|
|
48
|
-
it "calls the root document's
|
49
|
-
root.should_receive(:
|
48
|
+
it "calls the root document's _update with a full attribute path and not safe" do
|
49
|
+
root.should_receive(:_update).with({"leaf._id"=>"id"}, {'leaf.data' => data}, false)
|
50
50
|
leaf.update_attributes(:data => data)
|
51
51
|
end
|
52
52
|
|
53
|
-
it "(with bang!) calls the root document's
|
54
|
-
root.should_receive(:
|
53
|
+
it "(with bang!) calls the root document's _update with a full attribute path and safe" do
|
54
|
+
root.should_receive(:_update).with({"leaf._id"=>"id"}, {'leaf.data' => data}, true)
|
55
55
|
leaf.update_attributes!(:data => data)
|
56
56
|
end
|
57
57
|
end
|
@@ -59,51 +59,15 @@ describe "Saving embedded documents" do
|
|
59
59
|
context "with embed_many, update_attributes" do
|
60
60
|
let(:root) { NestedDocsRoot.new(:nested_children => [NestedChild.new(:leaf => leaf)]) }
|
61
61
|
|
62
|
-
it "calls the root document's
|
63
|
-
root.should_receive(:
|
62
|
+
it "calls the root document's _update with a full attribute path and not safe" do
|
63
|
+
root.should_receive(:_update).with({"nested_children.leaf._id"=>"id"}, {'nested_children.$.leaf.data' => data}, false)
|
64
64
|
leaf.update_attributes(:data => data)
|
65
65
|
end
|
66
66
|
|
67
|
-
it "(with bang!) calls the root document's
|
68
|
-
root.should_receive(:
|
67
|
+
it "(with bang!) calls the root document's _update with a full attribute path and safe" do
|
68
|
+
root.should_receive(:_update).with({"nested_children.leaf._id"=>"id"}, {'nested_children.$.leaf.data' => data}, true)
|
69
69
|
leaf.update_attributes!(:data => data)
|
70
70
|
end
|
71
71
|
end
|
72
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 embed_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 embed_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
73
|
end
|
data/spec/index_spec.rb
CHANGED
@@ -51,12 +51,12 @@ describe MongoDoc::Index do
|
|
51
51
|
context "Compound index" do
|
52
52
|
|
53
53
|
it "creates a compound index" do
|
54
|
-
collection.should_receive(:create_index).with([
|
54
|
+
collection.should_receive(:create_index).with(array_including([:first_name, Mongo::ASCENDING], [:last_name, Mongo::ASCENDING]), false)
|
55
55
|
IndexTest.index(:first_name => :asc, :last_name => :asc)
|
56
56
|
end
|
57
57
|
|
58
58
|
it "creates a unique compound index" do
|
59
|
-
collection.should_receive(:create_index).with([
|
59
|
+
collection.should_receive(:create_index).with(array_including([:first_name, Mongo::ASCENDING], [:last_name, Mongo::ASCENDING]), true)
|
60
60
|
IndexTest.index(:first_name => :asc, :last_name => :asc, :unique => true)
|
61
61
|
end
|
62
62
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 4
|
8
|
-
-
|
9
|
-
version: 0.4.
|
8
|
+
- 2
|
9
|
+
version: 0.4.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Les Hill
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-23 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -41,7 +41,8 @@ dependencies:
|
|
41
41
|
segments:
|
42
42
|
- 0
|
43
43
|
- 19
|
44
|
-
|
44
|
+
- 1
|
45
|
+
version: 0.19.1
|
45
46
|
type: :runtime
|
46
47
|
version_requirements: *id002
|
47
48
|
- !ruby/object:Gem::Dependency
|
@@ -54,7 +55,8 @@ dependencies:
|
|
54
55
|
segments:
|
55
56
|
- 0
|
56
57
|
- 19
|
57
|
-
|
58
|
+
- 1
|
59
|
+
version: 0.19.1
|
58
60
|
type: :runtime
|
59
61
|
version_requirements: *id003
|
60
62
|
- !ruby/object:Gem::Dependency
|
@@ -126,6 +128,7 @@ extra_rdoc_files:
|
|
126
128
|
files:
|
127
129
|
- .document
|
128
130
|
- .gitignore
|
131
|
+
- HISTORY.md
|
129
132
|
- LICENSE
|
130
133
|
- README.textile
|
131
134
|
- Rakefile
|
@@ -226,6 +229,7 @@ files:
|
|
226
229
|
- perf/mongo_doc_runner.rb
|
227
230
|
- perf/ruby_driver_runner.rb
|
228
231
|
- script/console
|
232
|
+
- spec/array_including_argument_matcher.rb
|
229
233
|
- spec/associations/collection_proxy_spec.rb
|
230
234
|
- spec/associations/document_proxy_spec.rb
|
231
235
|
- spec/associations/hash_proxy_spec.rb
|
@@ -287,6 +291,7 @@ signing_key:
|
|
287
291
|
specification_version: 3
|
288
292
|
summary: ODM for MongoDB
|
289
293
|
test_files:
|
294
|
+
- spec/array_including_argument_matcher.rb
|
290
295
|
- spec/associations/collection_proxy_spec.rb
|
291
296
|
- spec/associations/document_proxy_spec.rb
|
292
297
|
- spec/associations/hash_proxy_spec.rb
|