mongo_doc 0.4.1 → 0.4.2
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/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
|