mongoid 4.0.1 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +1 -1
- data/lib/mongoid/contextual/memory.rb +5 -5
- data/lib/mongoid/contextual/mongo.rb +10 -0
- data/lib/mongoid/document.rb +2 -2
- data/lib/mongoid/extensions.rb +13 -0
- data/lib/mongoid/findable.rb +27 -5
- data/lib/mongoid/persistable/creatable.rb +2 -1
- data/lib/mongoid/persistable/settable.rb +1 -1
- data/lib/mongoid/persistable/updatable.rb +2 -1
- data/lib/mongoid/relations/many.rb +21 -0
- data/lib/mongoid/sessions/options.rb +7 -2
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +32 -0
- data/spec/app/models/contextable_item.rb +5 -0
- data/spec/mongoid/attributes/nested_spec.rb +139 -144
- data/spec/mongoid/contextual/memory_spec.rb +7 -2
- data/spec/mongoid/criteria/modifiable_spec.rb +5 -8
- data/spec/mongoid/document_spec.rb +7 -3
- data/spec/mongoid/extensions_spec.rb +14 -0
- data/spec/mongoid/findable_spec.rb +97 -9
- data/spec/mongoid/persistable/creatable_spec.rb +41 -0
- data/spec/mongoid/persistable/savable_spec.rb +37 -0
- data/spec/mongoid/persistable/settable_spec.rb +23 -0
- data/spec/mongoid/relations/embedded/many_spec.rb +74 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +130 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +49 -0
- data/spec/mongoid/sessions/options_spec.rb +2 -1
- data/spec/mongoid/sessions_spec.rb +30 -0
- metadata +5 -3
@@ -926,8 +926,13 @@ describe Mongoid::Contextual::Memory do
|
|
926
926
|
Address.new(street: "lenau", number: 5, name: "lenau")
|
927
927
|
end
|
928
928
|
|
929
|
+
let(:kampuchea_krom) do
|
930
|
+
Address.new(street: "kampuchea krom", number: 5, name: "kampuchea krom")
|
931
|
+
end
|
932
|
+
|
929
933
|
before do
|
930
934
|
criteria.documents.unshift(lenau)
|
935
|
+
criteria.documents.unshift(kampuchea_krom)
|
931
936
|
end
|
932
937
|
|
933
938
|
context "when the sort is ascending" do
|
@@ -937,7 +942,7 @@ describe Mongoid::Contextual::Memory do
|
|
937
942
|
end
|
938
943
|
|
939
944
|
it "sorts the documents" do
|
940
|
-
expect(context.entries).to eq([ friedel, lenau, pfluger, hobrecht ])
|
945
|
+
expect(context.entries).to eq([ friedel, kampuchea_krom, lenau, pfluger, hobrecht ])
|
941
946
|
end
|
942
947
|
|
943
948
|
it "returns the context" do
|
@@ -952,7 +957,7 @@ describe Mongoid::Contextual::Memory do
|
|
952
957
|
end
|
953
958
|
|
954
959
|
it "sorts the documents" do
|
955
|
-
expect(context.entries).to eq([ hobrecht, pfluger, lenau, friedel ])
|
960
|
+
expect(context.entries).to eq([ hobrecht, pfluger, lenau, kampuchea_krom, friedel ])
|
956
961
|
end
|
957
962
|
|
958
963
|
it "returns the context" do
|
@@ -934,12 +934,9 @@ describe Mongoid::Criteria::Modifiable do
|
|
934
934
|
|
935
935
|
context "when the relation is a references many" do
|
936
936
|
|
937
|
-
|
938
|
-
person.posts.create(title: "First")
|
939
|
-
|
940
|
-
|
941
|
-
let!(:post_two) do
|
942
|
-
person.posts.create(title: "Second")
|
937
|
+
before do
|
938
|
+
person.posts.create!(title: "First")
|
939
|
+
person.posts.create!(title: "Second")
|
943
940
|
end
|
944
941
|
|
945
942
|
context "when updating the relation directly" do
|
@@ -948,12 +945,12 @@ describe Mongoid::Criteria::Modifiable do
|
|
948
945
|
person.posts.update(title: "London")
|
949
946
|
end
|
950
947
|
|
951
|
-
let
|
948
|
+
let(:from_db) do
|
952
949
|
Person.first
|
953
950
|
end
|
954
951
|
|
955
952
|
it "updates the first document" do
|
956
|
-
expect(from_db.posts.
|
953
|
+
expect(from_db.posts.map(&:title)).to eq(["London", "Second"])
|
957
954
|
end
|
958
955
|
|
959
956
|
it "does not update the last document" do
|
@@ -529,11 +529,15 @@ describe Mongoid::Document do
|
|
529
529
|
context "when the document is not new" do
|
530
530
|
|
531
531
|
let(:person) do
|
532
|
-
Person.
|
532
|
+
Person.create!
|
533
533
|
end
|
534
534
|
|
535
535
|
it "returns the id in an array" do
|
536
|
-
expect(person.to_key).to eq([ person.id ])
|
536
|
+
expect(person.to_key).to eq([ person.id.to_s ])
|
537
|
+
end
|
538
|
+
|
539
|
+
it "can query using the key" do
|
540
|
+
expect(person.id).to eq Person.find(person.to_key).first.id
|
537
541
|
end
|
538
542
|
end
|
539
543
|
|
@@ -546,7 +550,7 @@ describe Mongoid::Document do
|
|
546
550
|
end
|
547
551
|
|
548
552
|
it "returns the id in an array" do
|
549
|
-
expect(person.to_key).to eq([ person.id ])
|
553
|
+
expect(person.to_key).to eq([ person.id.to_s ])
|
550
554
|
end
|
551
555
|
end
|
552
556
|
end
|
@@ -13,3 +13,17 @@ describe BSON::ObjectId do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
describe BSON::Document do
|
18
|
+
|
19
|
+
describe "#symbolize_keys" do
|
20
|
+
|
21
|
+
let(:doc) do
|
22
|
+
described_class.new("foo" => "bar")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns key as symbol" do
|
26
|
+
expect(doc.symbolize_keys.keys).to eq [:foo]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -53,6 +53,55 @@ describe Mongoid::Findable do
|
|
53
53
|
|
54
54
|
describe ".find_by" do
|
55
55
|
|
56
|
+
context "when collection is a embeds_many" do
|
57
|
+
|
58
|
+
let(:person) do
|
59
|
+
Person.create(title: "sir")
|
60
|
+
end
|
61
|
+
|
62
|
+
let!(:message) do
|
63
|
+
person.messages.create!(body: 'foo')
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when the document is found" do
|
67
|
+
|
68
|
+
it "returns the document" do
|
69
|
+
expect(person.messages.find_by(body: 'foo')).to eq(message)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when the document is not found" do
|
74
|
+
|
75
|
+
context "when raising a not found error" do
|
76
|
+
|
77
|
+
let!(:raise_option) { Mongoid.raise_not_found_error }
|
78
|
+
|
79
|
+
before { Mongoid.raise_not_found_error = true }
|
80
|
+
|
81
|
+
after { Mongoid.raise_not_found_error = raise_option }
|
82
|
+
|
83
|
+
it "raises an error" do
|
84
|
+
expect {
|
85
|
+
person.messages.find_by(body: 'bar')
|
86
|
+
}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when raising no error" do
|
91
|
+
|
92
|
+
let!(:raise_option) { Mongoid.raise_not_found_error }
|
93
|
+
|
94
|
+
before { Mongoid.raise_not_found_error = false }
|
95
|
+
|
96
|
+
after { Mongoid.raise_not_found_error = raise_option }
|
97
|
+
|
98
|
+
it "returns nil" do
|
99
|
+
expect(person.messages.find_by(body: 'bar')).to be_nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
56
105
|
context "when the document is found" do
|
57
106
|
|
58
107
|
let!(:person) do
|
@@ -84,9 +133,11 @@ describe Mongoid::Findable do
|
|
84
133
|
|
85
134
|
context "when raising a not found error" do
|
86
135
|
|
87
|
-
|
88
|
-
|
89
|
-
|
136
|
+
let!(:raise_option) { Mongoid.raise_not_found_error }
|
137
|
+
|
138
|
+
before { Mongoid.raise_not_found_error = true }
|
139
|
+
|
140
|
+
after { Mongoid.raise_not_found_error = raise_option }
|
90
141
|
|
91
142
|
it "raises an error" do
|
92
143
|
expect {
|
@@ -97,13 +148,11 @@ describe Mongoid::Findable do
|
|
97
148
|
|
98
149
|
context "when raising no error" do
|
99
150
|
|
100
|
-
|
101
|
-
Mongoid.raise_not_found_error = false
|
102
|
-
end
|
151
|
+
let!(:raise_option) { Mongoid.raise_not_found_error }
|
103
152
|
|
104
|
-
|
105
|
-
|
106
|
-
|
153
|
+
before { Mongoid.raise_not_found_error = false }
|
154
|
+
|
155
|
+
after { Mongoid.raise_not_found_error = raise_option }
|
107
156
|
|
108
157
|
context "when no block is provided" do
|
109
158
|
|
@@ -128,6 +177,45 @@ describe Mongoid::Findable do
|
|
128
177
|
end
|
129
178
|
end
|
130
179
|
|
180
|
+
describe "find_by!" do
|
181
|
+
|
182
|
+
context "when the document is found" do
|
183
|
+
|
184
|
+
let!(:person) do
|
185
|
+
Person.create(title: "sir")
|
186
|
+
end
|
187
|
+
|
188
|
+
context "when no block is provided" do
|
189
|
+
|
190
|
+
it "returns the document" do
|
191
|
+
expect(Person.find_by!(title: "sir")).to eq(person)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when a block is provided" do
|
196
|
+
|
197
|
+
let(:result) do
|
198
|
+
Person.find_by!(title: "sir") do |peep|
|
199
|
+
peep.age = 50
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
it "yields the returned document" do
|
204
|
+
expect(result.age).to eq(50)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "when the document is not found" do
|
210
|
+
|
211
|
+
it "raises an error" do
|
212
|
+
expect {
|
213
|
+
Person.find_by!(ssn: "333-22-1111")
|
214
|
+
}.to raise_error(Mongoid::Errors::DocumentNotFound)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
131
219
|
[ :first, :one ].each do |method|
|
132
220
|
|
133
221
|
describe "##{method}" do
|
@@ -394,6 +394,47 @@ describe Mongoid::Persistable::Creatable do
|
|
394
394
|
end
|
395
395
|
end
|
396
396
|
end
|
397
|
+
|
398
|
+
context "#find_or_create_by!" do
|
399
|
+
|
400
|
+
before do
|
401
|
+
container.vehicles.find_or_create_by!({ driver_id: driver.id }, Car)
|
402
|
+
end
|
403
|
+
|
404
|
+
it "creates the given type document" do
|
405
|
+
expect(container.vehicles.map(&:class)).to eq([ Car ])
|
406
|
+
end
|
407
|
+
|
408
|
+
it "creates with the given attributes" do
|
409
|
+
expect(container.vehicles.map(&:driver)).to eq([ driver ])
|
410
|
+
end
|
411
|
+
|
412
|
+
it "creates the correct number of documents" do
|
413
|
+
expect(container.vehicles.size).to eq(1)
|
414
|
+
end
|
415
|
+
|
416
|
+
context "when executing with a found document" do
|
417
|
+
|
418
|
+
before do
|
419
|
+
container.vehicles.find_or_create_by!({ driver_id: driver.id }, Car)
|
420
|
+
end
|
421
|
+
|
422
|
+
it "does not create an additional document" do
|
423
|
+
expect(container.vehicles.size).to eq(1)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
context "when executing with an additional new document" do
|
428
|
+
|
429
|
+
before do
|
430
|
+
container.vehicles.find_or_create_by!({ driver_id: driver.id }, Truck)
|
431
|
+
end
|
432
|
+
|
433
|
+
it "creates the new additional document" do
|
434
|
+
expect(container.vehicles.size).to eq(2)
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
397
438
|
end
|
398
439
|
end
|
399
440
|
|
@@ -8,6 +8,14 @@ describe Mongoid::Persistable::Savable do
|
|
8
8
|
Person.create
|
9
9
|
end
|
10
10
|
|
11
|
+
let(:contextable_item) do
|
12
|
+
ContextableItem.new
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:persisted_contextable_item) do
|
16
|
+
ContextableItem.create(title: 'sir')
|
17
|
+
end
|
18
|
+
|
11
19
|
context "when skipping validation" do
|
12
20
|
|
13
21
|
context "when no relations are involved" do
|
@@ -285,6 +293,35 @@ describe Mongoid::Persistable::Savable do
|
|
285
293
|
}.to raise_error(Mongoid::Errors::ReadonlyDocument)
|
286
294
|
end
|
287
295
|
end
|
296
|
+
|
297
|
+
context "when validation context isn't assigned" do
|
298
|
+
it "returns true" do
|
299
|
+
expect(contextable_item.save).to be true
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context "when validation context exists" do
|
304
|
+
context "on new document" do
|
305
|
+
it "returns true" do
|
306
|
+
contextable_item.title = "sir"
|
307
|
+
expect(contextable_item.save(context: :in_context)).to be true
|
308
|
+
end
|
309
|
+
it "returns false" do
|
310
|
+
expect(contextable_item.save(context: :in_context)).to be false
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context "on persisted document" do
|
315
|
+
it "returns true" do
|
316
|
+
persisted_contextable_item.title = "lady"
|
317
|
+
expect(persisted_contextable_item.save(context: :in_context)).to be true
|
318
|
+
end
|
319
|
+
it "returns false" do
|
320
|
+
persisted_contextable_item.title = nil
|
321
|
+
expect(persisted_contextable_item.save(context: :in_context)).to be false
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
288
325
|
end
|
289
326
|
|
290
327
|
describe "save!" do
|
@@ -136,4 +136,27 @@ describe Mongoid::Persistable::Settable do
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
end
|
139
|
+
|
140
|
+
context "when dynamic attributes are not enabled" do
|
141
|
+
let(:account) do
|
142
|
+
Account.create
|
143
|
+
end
|
144
|
+
|
145
|
+
it "raises exception for an unknown attribute " do
|
146
|
+
expect {
|
147
|
+
account.set(somethingnew: "somethingnew")
|
148
|
+
}.to raise_error(Mongoid::Errors::UnknownAttribute)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "when dynamic attributes enabled" do
|
153
|
+
let(:person) do
|
154
|
+
Person.create
|
155
|
+
end
|
156
|
+
|
157
|
+
it "updates non existing attribute" do
|
158
|
+
person.set(somethingnew: "somethingnew")
|
159
|
+
expect(person.reload.somethingnew).to eq "somethingnew"
|
160
|
+
end
|
161
|
+
end
|
139
162
|
end
|
@@ -2120,6 +2120,80 @@ describe Mongoid::Relations::Embedded::Many do
|
|
2120
2120
|
end
|
2121
2121
|
end
|
2122
2122
|
|
2123
|
+
describe "#find_or_create_by!" do
|
2124
|
+
|
2125
|
+
let(:person) do
|
2126
|
+
Person.create
|
2127
|
+
end
|
2128
|
+
|
2129
|
+
let!(:address) do
|
2130
|
+
person.addresses.build(street: "Bourke", city: "Melbourne")
|
2131
|
+
end
|
2132
|
+
|
2133
|
+
context "when the document exists" do
|
2134
|
+
|
2135
|
+
let(:found) do
|
2136
|
+
person.addresses.find_or_create_by!(street: "Bourke")
|
2137
|
+
end
|
2138
|
+
|
2139
|
+
it "returns the document" do
|
2140
|
+
expect(found).to eq(address)
|
2141
|
+
end
|
2142
|
+
end
|
2143
|
+
|
2144
|
+
context "when the document does not exist" do
|
2145
|
+
|
2146
|
+
let(:found) do
|
2147
|
+
person.addresses.find_or_create_by!(street: "King") do |address|
|
2148
|
+
address.state = "CA"
|
2149
|
+
end
|
2150
|
+
end
|
2151
|
+
|
2152
|
+
it "sets the new document attributes" do
|
2153
|
+
expect(found.street).to eq("King")
|
2154
|
+
end
|
2155
|
+
|
2156
|
+
it "returns a newly persisted document" do
|
2157
|
+
expect(found).to be_persisted
|
2158
|
+
end
|
2159
|
+
|
2160
|
+
it "calls the passed block" do
|
2161
|
+
expect(found.state).to eq("CA")
|
2162
|
+
end
|
2163
|
+
|
2164
|
+
context "when validation fails" do
|
2165
|
+
|
2166
|
+
it "raises an error" do
|
2167
|
+
expect {
|
2168
|
+
person.addresses.find_or_create_by!(street: "1")
|
2169
|
+
}.to raise_error(Mongoid::Errors::Validations)
|
2170
|
+
end
|
2171
|
+
end
|
2172
|
+
end
|
2173
|
+
|
2174
|
+
context "when the child belongs to another document" do
|
2175
|
+
|
2176
|
+
let(:product) do
|
2177
|
+
Product.create
|
2178
|
+
end
|
2179
|
+
|
2180
|
+
let(:purchase) do
|
2181
|
+
Purchase.create
|
2182
|
+
end
|
2183
|
+
|
2184
|
+
let(:line_item) do
|
2185
|
+
purchase.line_items.find_or_create_by(
|
2186
|
+
product_id: product.id,
|
2187
|
+
product_type: product.class.name
|
2188
|
+
)
|
2189
|
+
end
|
2190
|
+
|
2191
|
+
it "properly creates the document" do
|
2192
|
+
expect(line_item.product).to eq(product)
|
2193
|
+
end
|
2194
|
+
end
|
2195
|
+
end
|
2196
|
+
|
2123
2197
|
describe "#find_or_initialize_by" do
|
2124
2198
|
|
2125
2199
|
let(:person) do
|