mongoid 4.0.1 → 4.0.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.
- 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
|