mongo_mapper 0.14.0 → 0.15.4
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 +5 -5
- data/LICENSE +1 -1
- data/README.md +72 -0
- data/examples/keys.rb +1 -1
- data/examples/modifiers/set.rb +1 -1
- data/examples/querying.rb +1 -1
- data/examples/safe.rb +2 -2
- data/examples/scopes.rb +1 -1
- data/lib/mongo_mapper.rb +19 -17
- data/lib/mongo_mapper/connection.rb +16 -38
- data/lib/mongo_mapper/extensions/array.rb +1 -1
- data/lib/mongo_mapper/extensions/binary.rb +1 -1
- data/lib/mongo_mapper/extensions/date.rb +1 -1
- data/lib/mongo_mapper/extensions/float.rb +1 -1
- data/lib/mongo_mapper/extensions/hash.rb +1 -1
- data/lib/mongo_mapper/extensions/nil_class.rb +2 -2
- data/lib/mongo_mapper/extensions/object.rb +1 -1
- data/lib/mongo_mapper/extensions/object_id.rb +6 -2
- data/lib/mongo_mapper/extensions/set.rb +1 -1
- data/lib/mongo_mapper/extensions/string.rb +1 -1
- data/lib/mongo_mapper/plugins/accessible.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/many_association.rb +6 -5
- data/lib/mongo_mapper/plugins/associations/{belongs_to_polymorphic_proxy.rb → proxy/belongs_to_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{belongs_to_proxy.rb → proxy/belongs_to_proxy.rb} +6 -0
- data/lib/mongo_mapper/plugins/associations/proxy/collection.rb +55 -0
- data/lib/mongo_mapper/plugins/associations/{embedded_collection.rb → proxy/embedded_collection.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{in_array_proxy.rb → proxy/in_array_proxy.rb} +36 -6
- data/lib/mongo_mapper/plugins/associations/proxy/in_foreign_array_proxy.rb +136 -0
- data/lib/mongo_mapper/plugins/associations/{many_documents_as_proxy.rb → proxy/many_documents_as_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{many_documents_proxy.rb → proxy/many_documents_proxy.rb} +0 -4
- data/lib/mongo_mapper/plugins/associations/{many_embedded_polymorphic_proxy.rb → proxy/many_embedded_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{many_embedded_proxy.rb → proxy/many_embedded_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{many_polymorphic_proxy.rb → proxy/many_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{one_as_proxy.rb → proxy/one_as_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{one_embedded_polymorphic_proxy.rb → proxy/one_embedded_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{one_embedded_proxy.rb → proxy/one_embedded_proxy.rb} +3 -1
- data/lib/mongo_mapper/plugins/associations/{one_proxy.rb → proxy/one_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/proxy/proxy.rb +164 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -13
- data/lib/mongo_mapper/plugins/dirty.rb +29 -37
- data/lib/mongo_mapper/plugins/document.rb +1 -1
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +2 -2
- data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
- data/lib/mongo_mapper/plugins/indexes.rb +13 -6
- data/lib/mongo_mapper/plugins/keys.rb +12 -7
- data/lib/mongo_mapper/plugins/keys/key.rb +21 -13
- data/lib/mongo_mapper/plugins/modifiers.rb +39 -14
- data/lib/mongo_mapper/plugins/persistence.rb +6 -2
- data/lib/mongo_mapper/plugins/querying.rb +9 -3
- data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +6 -6
- data/lib/mongo_mapper/plugins/safe.rb +10 -4
- data/lib/mongo_mapper/plugins/scopes.rb +19 -3
- data/lib/mongo_mapper/plugins/stats.rb +1 -3
- data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
- data/lib/mongo_mapper/plugins/validations.rb +1 -1
- data/lib/mongo_mapper/railtie.rb +1 -0
- data/lib/mongo_mapper/utils.rb +2 -2
- data/lib/mongo_mapper/version.rb +1 -1
- data/spec/examples.txt +1731 -0
- data/spec/functional/accessible_spec.rb +7 -1
- data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
- data/spec/functional/associations/belongs_to_proxy_spec.rb +55 -5
- data/spec/functional/associations/in_array_proxy_spec.rb +149 -14
- data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
- data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
- data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
- data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
- data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
- data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
- data/spec/functional/associations/one_embedded_proxy_spec.rb +28 -0
- data/spec/functional/associations/one_proxy_spec.rb +19 -9
- data/spec/functional/associations_spec.rb +3 -3
- data/spec/functional/binary_spec.rb +2 -2
- data/spec/functional/caching_spec.rb +15 -22
- data/spec/functional/callbacks_spec.rb +2 -2
- data/spec/functional/counter_cache_spec.rb +10 -10
- data/spec/functional/dirty_spec.rb +48 -10
- data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
- data/spec/functional/document_spec.rb +5 -8
- data/spec/functional/dumpable_spec.rb +1 -1
- data/spec/functional/embedded_document_spec.rb +5 -5
- data/spec/functional/identity_map_spec.rb +8 -8
- data/spec/functional/indexes_spec.rb +19 -18
- data/spec/functional/keys_spec.rb +64 -33
- data/spec/functional/logger_spec.rb +2 -2
- data/spec/functional/modifiers_spec.rb +81 -19
- data/spec/functional/partial_updates_spec.rb +8 -8
- data/spec/functional/protected_spec.rb +1 -1
- data/spec/functional/querying_spec.rb +70 -22
- data/spec/functional/safe_spec.rb +23 -27
- data/spec/functional/sci_spec.rb +7 -7
- data/spec/functional/scopes_spec.rb +89 -1
- data/spec/functional/static_keys_spec.rb +2 -2
- data/spec/functional/stats_spec.rb +28 -12
- data/spec/functional/strong_parameters_spec.rb +49 -0
- data/spec/functional/validations_spec.rb +8 -16
- data/spec/quality_spec.rb +1 -1
- data/spec/spec_helper.rb +39 -8
- data/spec/support/matchers.rb +1 -1
- data/spec/unit/associations/proxy_spec.rb +18 -10
- data/spec/unit/clone_spec.rb +1 -1
- data/spec/unit/document_spec.rb +3 -3
- data/spec/unit/embedded_document_spec.rb +4 -5
- data/spec/unit/extensions_spec.rb +12 -7
- data/spec/unit/identity_map_middleware_spec.rb +65 -96
- data/spec/unit/inspect_spec.rb +1 -1
- data/spec/unit/key_spec.rb +23 -18
- data/spec/unit/keys_spec.rb +17 -8
- data/spec/unit/mongo_mapper_spec.rb +41 -88
- data/spec/unit/rails_spec.rb +2 -2
- data/spec/unit/validations_spec.rb +18 -18
- metadata +70 -38
- data/README.rdoc +0 -56
- data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
- data/lib/mongo_mapper/plugins/associations/collection.rb +0 -29
- data/lib/mongo_mapper/plugins/associations/proxy.rb +0 -141
@@ -148,11 +148,11 @@ describe "Callbacks" do
|
|
148
148
|
@root_class.define_callbacks :after_publish
|
149
149
|
@root_class.after_save { |d| d.run_callbacks(:after_publish) }
|
150
150
|
|
151
|
-
|
151
|
+
lambda {
|
152
152
|
child = @child_class.new(:name => 'Child')
|
153
153
|
root = @root_class.create(:name => 'Parent', :children => [child])
|
154
154
|
child.history.should_not include(:after_publish)
|
155
|
-
}.
|
155
|
+
}.should_not raise_error
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
@@ -171,42 +171,42 @@ describe MongoMapper::Plugins::CounterCache do
|
|
171
171
|
end
|
172
172
|
|
173
173
|
it "should update the counter cache on save" do
|
174
|
-
|
174
|
+
lambda {
|
175
175
|
@comment.save!
|
176
176
|
@article.reload
|
177
|
-
}.
|
177
|
+
}.should change(@article, :commentable_count).by(1)
|
178
178
|
end
|
179
179
|
|
180
180
|
it "should increment with a second object" do
|
181
181
|
@comment.save!
|
182
182
|
|
183
|
-
|
183
|
+
lambda {
|
184
184
|
second_comment = CounterCacheFixtureModels::Comment.new
|
185
185
|
second_comment.commentable = @article
|
186
186
|
second_comment.save!
|
187
187
|
@article.reload
|
188
|
-
}.
|
188
|
+
}.should change(@article, :commentable_count).by(1)
|
189
189
|
end
|
190
190
|
|
191
191
|
it "should decrement the counter cache on destroy" do
|
192
192
|
@comment.save!
|
193
193
|
|
194
|
-
|
194
|
+
lambda {
|
195
195
|
@comment.destroy
|
196
196
|
@article.reload
|
197
|
-
}.
|
197
|
+
}.should change(@article, :commentable_count).by(-1)
|
198
198
|
end
|
199
199
|
|
200
200
|
it "should increment with a different type of object" do
|
201
201
|
@comment.save!
|
202
202
|
|
203
|
-
|
203
|
+
lambda {
|
204
204
|
second_comment = CounterCacheFixtureModels::Comment.new
|
205
205
|
second_comment.commentable = @article
|
206
206
|
second_comment.save!
|
207
207
|
|
208
208
|
@article.reload
|
209
|
-
}.
|
209
|
+
}.should change(@article, :commentable_count).by(1)
|
210
210
|
end
|
211
211
|
|
212
212
|
describe "without a counter cache field" do
|
@@ -226,9 +226,9 @@ describe MongoMapper::Plugins::CounterCache do
|
|
226
226
|
it "should raise at save (runtime) if there is no counter cache field" do
|
227
227
|
@comment.commentable = @obj
|
228
228
|
|
229
|
-
|
229
|
+
lambda {
|
230
230
|
@comment.save!
|
231
|
-
}.
|
231
|
+
}.should raise_error(MongoMapper::Plugins::CounterCache::InvalidCounterCacheError)
|
232
232
|
end
|
233
233
|
end
|
234
234
|
end
|
@@ -9,6 +9,13 @@ describe "Dirty" do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
context "marking changes" do
|
12
|
+
it "should have the changed? methods" do
|
13
|
+
obj = @document.new
|
14
|
+
obj.should respond_to(:changed?)
|
15
|
+
obj.should respond_to(:phrase_changed?)
|
16
|
+
obj.should respond_to(:paragraph_changed?)
|
17
|
+
end
|
18
|
+
|
12
19
|
it "should not happen if there are none" do
|
13
20
|
doc = @document.new
|
14
21
|
doc.phrase_changed?.should be_falsey
|
@@ -48,8 +55,8 @@ describe "Dirty" do
|
|
48
55
|
|
49
56
|
it "should not happen when loading from database" do
|
50
57
|
doc = @document.create(:phrase => 'Foo')
|
51
|
-
|
52
|
-
|
58
|
+
@document.any_instance.should_receive(:attribute_will_change!).never
|
59
|
+
@document.any_instance.should_receive(:attribute_changed?).never
|
53
60
|
doc = @document.find(doc.id)
|
54
61
|
doc.changed?.should be_falsey
|
55
62
|
end
|
@@ -220,19 +227,25 @@ describe "Dirty" do
|
|
220
227
|
doc.a = "d"
|
221
228
|
doc.a_change.should == ["b","d"]
|
222
229
|
end
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
230
|
+
|
231
|
+
# TODO: ? Is this consistent with how ActiveRecord now works with changes?
|
232
|
+
# it "should reset changes when set back to the original value" do
|
233
|
+
# doc = @document.create(:a=>"b")
|
234
|
+
# doc.a = "c"
|
235
|
+
# doc.a = "b"
|
236
|
+
# doc.changed?.should be_falsey
|
237
|
+
# end
|
229
238
|
end
|
230
239
|
|
231
240
|
context "reset_attribute!" do
|
232
241
|
it "should reset the attribute back to the previous value" do
|
233
242
|
doc = @document.create(:a=>"b")
|
234
243
|
doc.a = "c"
|
235
|
-
doc.
|
244
|
+
if doc.respond_to?(:restore_a!)
|
245
|
+
doc.restore_a!
|
246
|
+
else
|
247
|
+
doc.reset_a!
|
248
|
+
end
|
236
249
|
doc.changed?.should be_falsey
|
237
250
|
doc.a.should == "b"
|
238
251
|
end
|
@@ -241,7 +254,11 @@ describe "Dirty" do
|
|
241
254
|
doc.a = "c"
|
242
255
|
doc.a = "d"
|
243
256
|
doc.a = "e"
|
244
|
-
doc.
|
257
|
+
if doc.respond_to?(:restore_a!)
|
258
|
+
doc.restore_a!
|
259
|
+
else
|
260
|
+
doc.reset_a!
|
261
|
+
end
|
245
262
|
doc.changed?.should be_falsey
|
246
263
|
doc.a.should == "b"
|
247
264
|
end
|
@@ -263,6 +280,27 @@ describe "Dirty" do
|
|
263
280
|
end
|
264
281
|
end
|
265
282
|
|
283
|
+
context "Document having Array key with typecast option" do
|
284
|
+
before do
|
285
|
+
@author_id = BSON::ObjectId.new
|
286
|
+
@doc = Doc('Book') { key :author_ids, Array, typecast: "ObjectId" }
|
287
|
+
@doc.plugin MongoMapper::Plugins::Dirty
|
288
|
+
@book = @doc.create!(author_ids: [@author_id])
|
289
|
+
end
|
290
|
+
|
291
|
+
context "changed" do
|
292
|
+
it "should be empty if assigned the same array" do
|
293
|
+
@book.author_ids = [@author_id]
|
294
|
+
@book.changed.should be_empty
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should be empty if assigned the same but before-typecasted array" do
|
298
|
+
@book.author_ids = [@author_id.to_s]
|
299
|
+
@book.changed.should be_empty
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
266
304
|
context "Embedded documents" do
|
267
305
|
before do
|
268
306
|
@edoc = EDoc('Duck') { key :name, String }
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'DirtyWithCallbacks' do
|
4
|
+
it 'should update its changes/previous_changes before after_create/after_update callbacks' do
|
5
|
+
history = {}
|
6
|
+
|
7
|
+
document = Doc {
|
8
|
+
key :x, String
|
9
|
+
|
10
|
+
after_save {
|
11
|
+
history[:after_save] = {
|
12
|
+
changes: changes,
|
13
|
+
previous_changes: previous_changes,
|
14
|
+
}
|
15
|
+
}
|
16
|
+
after_create {
|
17
|
+
history[:after_create] = {
|
18
|
+
changes: changes,
|
19
|
+
previous_changes: previous_changes,
|
20
|
+
}
|
21
|
+
}
|
22
|
+
after_update {
|
23
|
+
history[:after_update] = {
|
24
|
+
changes: changes,
|
25
|
+
previous_changes: previous_changes,
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
d = document.new(x: 'hello')
|
31
|
+
d.save
|
32
|
+
|
33
|
+
history.should == {
|
34
|
+
after_save: {
|
35
|
+
changes: {},
|
36
|
+
previous_changes: {'x' => [nil, 'hello']},
|
37
|
+
},
|
38
|
+
after_create: {
|
39
|
+
changes: {},
|
40
|
+
previous_changes: {'x' => [nil, 'hello']},
|
41
|
+
},
|
42
|
+
}
|
43
|
+
history.clear
|
44
|
+
|
45
|
+
d.x = 'world'
|
46
|
+
d.save!
|
47
|
+
|
48
|
+
history.should == {
|
49
|
+
after_save: {
|
50
|
+
changes: {},
|
51
|
+
previous_changes: {'x' => ['hello', 'world']},
|
52
|
+
},
|
53
|
+
after_update: {
|
54
|
+
changes: {},
|
55
|
+
previous_changes: {'x' => ['hello', 'world']},
|
56
|
+
},
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
@@ -240,8 +240,8 @@ describe "Document" do
|
|
240
240
|
end
|
241
241
|
|
242
242
|
it "should reset many associations" do
|
243
|
-
|
244
|
-
|
243
|
+
@instance.foos.should_receive(:reset).at_least(1).times
|
244
|
+
@instance.bars.should_receive(:reset).at_least(1).times
|
245
245
|
@instance.reload
|
246
246
|
end
|
247
247
|
|
@@ -257,9 +257,6 @@ describe "Document" do
|
|
257
257
|
@instance.bar.should_not be_nil
|
258
258
|
end
|
259
259
|
|
260
|
-
it "should reset nil one association" do
|
261
|
-
end
|
262
|
-
|
263
260
|
it "should reinstantiate embedded associations" do
|
264
261
|
@instance.reload
|
265
262
|
@instance.bars.first.name.should == '1'
|
@@ -271,7 +268,7 @@ describe "Document" do
|
|
271
268
|
|
272
269
|
it "should raise DocumentNotFound if not found" do
|
273
270
|
@instance.destroy
|
274
|
-
|
271
|
+
lambda { @instance.reload }.should raise_error(MongoMapper::DocumentNotFound)
|
275
272
|
end
|
276
273
|
|
277
274
|
it "should clear keys that were removed from the database" do
|
@@ -283,7 +280,7 @@ describe "Document" do
|
|
283
280
|
context "database has keys not defined in model" do
|
284
281
|
before do
|
285
282
|
@id = BSON::ObjectId.new
|
286
|
-
@document.collection.
|
283
|
+
@document.collection.insert_one({
|
287
284
|
:_id => @id,
|
288
285
|
:first_name => 'John',
|
289
286
|
:last_name => 'Nunemaker',
|
@@ -304,7 +301,7 @@ describe "Document" do
|
|
304
301
|
end
|
305
302
|
|
306
303
|
it "should not walk ObjectSpace when creating a model" do
|
307
|
-
|
304
|
+
ObjectSpace.should_receive(:each_object).never
|
308
305
|
Doc()
|
309
306
|
end
|
310
307
|
end
|
@@ -7,7 +7,7 @@ describe "Documents with the Dumpable plugin" do
|
|
7
7
|
let(:store) { ActiveSupport::Cache::MemoryStore.new(:size => 1.megabyte) }
|
8
8
|
|
9
9
|
it "should be able to be marshalled" do
|
10
|
-
|
10
|
+
lambda { Marshal.dump(answer) }.should_not raise_error
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should be able to be unmarshalled" do
|
@@ -227,7 +227,7 @@ describe "EmbeddedDocument" do
|
|
227
227
|
person.pets << pet
|
228
228
|
pet.should be_new
|
229
229
|
|
230
|
-
|
230
|
+
person.should_receive(:save!)
|
231
231
|
pet.save!
|
232
232
|
end
|
233
233
|
|
@@ -272,8 +272,8 @@ describe "EmbeddedDocument" do
|
|
272
272
|
pet = person.pets.first
|
273
273
|
|
274
274
|
attributes = {:name => 'koda'}
|
275
|
-
|
276
|
-
|
275
|
+
pet.should_receive(:attributes=).with(attributes)
|
276
|
+
pet.should_receive(:save!)
|
277
277
|
pet.update_attributes!(attributes)
|
278
278
|
end
|
279
279
|
|
@@ -288,8 +288,8 @@ describe "EmbeddedDocument" do
|
|
288
288
|
end
|
289
289
|
|
290
290
|
it "should not fail if the source document contains nils in the embedded document list" do
|
291
|
-
@klass.collection.
|
292
|
-
|
291
|
+
@klass.collection.insert_one(:pets => [nil, {:name => "Sasha"}])
|
292
|
+
lambda { @klass.all.first.pets }.should_not raise_error
|
293
293
|
@klass.all.first.pets.tap do |pets|
|
294
294
|
pets.length.should == 1
|
295
295
|
pets[0].name.should == "Sasha"
|
@@ -14,12 +14,12 @@ describe "IdentityMap" do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def expect_no_queries
|
17
|
-
|
18
|
-
|
17
|
+
Mongo::Collection.any_instance.should_receive(:find_one).never
|
18
|
+
Mongo::Collection.any_instance.should_receive(:find).never
|
19
19
|
end
|
20
20
|
|
21
21
|
def expects_one_query
|
22
|
-
|
22
|
+
Mongo::Collection.any_instance.should_receive(:find).once.and_call_original
|
23
23
|
end
|
24
24
|
|
25
25
|
def clear_identity_map
|
@@ -185,11 +185,11 @@ describe "IdentityMap" do
|
|
185
185
|
key :created_at, Time
|
186
186
|
end
|
187
187
|
|
188
|
-
|
188
|
+
lambda do
|
189
189
|
loaded = person_with_time_class.load({'_id' => @id, 'name' => 'Frank', 'created_at' => '2014-12-07T20:36:45.529-08:00'}, true)
|
190
190
|
loaded.should be_present
|
191
191
|
loaded.created_at.should be_an_instance_of(Time)
|
192
|
-
end.
|
192
|
+
end.should_not raise_error
|
193
193
|
end
|
194
194
|
end
|
195
195
|
|
@@ -420,7 +420,7 @@ describe "IdentityMap" do
|
|
420
420
|
belongs_to :parent, :class_name => 'Item'
|
421
421
|
one :blog, :class_name => 'Blog', :foreign_key => 'parent_id'
|
422
422
|
end
|
423
|
-
Item.collection.
|
423
|
+
Item.collection.drop
|
424
424
|
|
425
425
|
class ::Blog < ::Item; end
|
426
426
|
|
@@ -461,7 +461,7 @@ describe "IdentityMap" do
|
|
461
461
|
|
462
462
|
blog = Blog.create(:title => 'Jill', :parent => root)
|
463
463
|
assert_in_map(blog)
|
464
|
-
root.should equal(blog.parent
|
464
|
+
root.should equal(blog.parent)
|
465
465
|
end
|
466
466
|
|
467
467
|
it "should work correctly with one proxy" do
|
@@ -470,7 +470,7 @@ describe "IdentityMap" do
|
|
470
470
|
|
471
471
|
root = Item.create(:title => 'Root', :blog => blog)
|
472
472
|
assert_in_map(root)
|
473
|
-
blog.should equal(root.blog
|
473
|
+
blog.should equal(root.blog)
|
474
474
|
end
|
475
475
|
|
476
476
|
it "should work correctly with one proxy create" do
|
@@ -13,22 +13,25 @@ describe "Indexing" do
|
|
13
13
|
|
14
14
|
context "against a known collection" do
|
15
15
|
before do
|
16
|
-
|
16
|
+
@document.stub(:collection).and_return(double(:name => :foo, :indexes => double()))
|
17
17
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
18
|
+
|
19
|
+
it "should delegate create_index to collection#create_one" do
|
20
|
+
@document.collection.indexes.should_receive(:create_one).with({:arg => 1}, {})
|
21
|
+
@document.create_index(:arg)
|
23
22
|
end
|
24
23
|
|
24
|
+
it "should delegate ensure_index to collection#create_one" do
|
25
|
+
@document.collection.indexes.should_receive(:create_one).with({:arg => 1}, {})
|
26
|
+
@document.create_index(:arg)
|
27
|
+
end
|
25
28
|
it "should delegate drop_index to collection" do
|
26
|
-
|
29
|
+
@document.collection.indexes.should_receive(:drop_one).with(:arg)
|
27
30
|
@document.drop_index(:arg)
|
28
31
|
end
|
29
32
|
|
30
33
|
it "should delegate drop_indexes to collection" do
|
31
|
-
|
34
|
+
@document.collection.indexes.should_receive(:drop_all)
|
32
35
|
@document.drop_indexes
|
33
36
|
end
|
34
37
|
end
|
@@ -48,6 +51,11 @@ describe "Indexing" do
|
|
48
51
|
@document.should have_index('last_name_1')
|
49
52
|
end
|
50
53
|
|
54
|
+
it "should allow specifying as a hash" do
|
55
|
+
@document.ensure_index({last_name: -1})
|
56
|
+
@document.should have_index('last_name_-1')
|
57
|
+
end
|
58
|
+
|
51
59
|
it "should allow creating unique index for a key" do
|
52
60
|
@document.ensure_index :first_name, :unique => true
|
53
61
|
@document.should have_index('fn_1')
|
@@ -55,18 +63,11 @@ describe "Indexing" do
|
|
55
63
|
|
56
64
|
it "should allow creating index on multiple keys" do
|
57
65
|
@document.ensure_index [[:first_name, 1], [:last_name, -1]]
|
58
|
-
|
59
|
-
# order is different for different versions of ruby so instead of
|
60
|
-
# just checking have_index('first_name_1_last_name_-1') I'm checking
|
61
|
-
# the values of the indexes to make sure the index creation was successful
|
62
|
-
@document.collection.index_information.detect do |index|
|
63
|
-
keys = index[0]
|
64
|
-
keys.include?('fn_1') && keys.include?('last_name_-1')
|
65
|
-
end.should_not be_nil
|
66
|
+
@document.should have_index('fn_1_last_name_-1')
|
66
67
|
end
|
67
68
|
|
68
69
|
it "should work with :index shortcut when defining key" do
|
69
|
-
|
70
|
+
suppress_stderr { @document.key :father, String, :index => true }
|
70
71
|
@document.should have_index('father_1')
|
71
72
|
end
|
72
|
-
end
|
73
|
+
end
|
@@ -34,28 +34,46 @@ describe "Keys" do
|
|
34
34
|
instance.foo.should == 'baz'
|
35
35
|
end
|
36
36
|
|
37
|
-
context "when persisting
|
38
|
-
TypecastedKeyModel = Doc do
|
39
|
-
key :people, Array, :typecast => "Person"
|
40
|
-
end
|
41
|
-
|
37
|
+
context "when persisting typecasts" do
|
42
38
|
Person = Struct.new(:name) do
|
43
39
|
def self.to_mongo(value)
|
44
40
|
value.name
|
45
41
|
end
|
46
42
|
|
47
43
|
def self.from_mongo(value)
|
48
|
-
|
44
|
+
new(value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when persisting a typecast Array" do
|
49
|
+
typecast_key_model = Doc do
|
50
|
+
key :people, Array, :typecast => "Person"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not mutate the model's state" do
|
54
|
+
person = Person.new "Bob"
|
55
|
+
doc = typecast_key_model.new(:people => [person])
|
56
|
+
|
57
|
+
doc.save!
|
58
|
+
|
59
|
+
doc.people.should == [person]
|
49
60
|
end
|
50
61
|
end
|
51
62
|
|
52
|
-
|
53
|
-
|
54
|
-
|
63
|
+
context "when persisting a typecast Set" do
|
64
|
+
typecast_key_model = Doc do
|
65
|
+
key :people, Set, :typecast => "Person"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should not mutate the model's state" do
|
69
|
+
person = Person.new "Bob"
|
70
|
+
|
71
|
+
doc = typecast_key_model.new(:people => Set.new([person]))
|
55
72
|
|
56
|
-
|
73
|
+
doc.save!
|
57
74
|
|
58
|
-
|
75
|
+
doc.people.should == Set.new([person])
|
76
|
+
end
|
59
77
|
end
|
60
78
|
end
|
61
79
|
|
@@ -70,7 +88,7 @@ describe "Keys" do
|
|
70
88
|
end
|
71
89
|
end
|
72
90
|
|
73
|
-
|
91
|
+
lambda { doc.new }.should_not raise_error
|
74
92
|
end
|
75
93
|
|
76
94
|
it "should not bomb if a key is read before Keys#initialize gets to get called" do
|
@@ -84,7 +102,7 @@ describe "Keys" do
|
|
84
102
|
end
|
85
103
|
end
|
86
104
|
|
87
|
-
|
105
|
+
lambda { doc.new }.should_not raise_error
|
88
106
|
end
|
89
107
|
|
90
108
|
it "should permit for key overrides" do
|
@@ -93,7 +111,7 @@ describe "Keys" do
|
|
93
111
|
key :class, String, :accessors => :skip
|
94
112
|
end
|
95
113
|
|
96
|
-
doc.collection.
|
114
|
+
doc.collection.insert_one('class' => 'String')
|
97
115
|
doc.all.first.tap do |d|
|
98
116
|
d.class.should == doc
|
99
117
|
d["class"].should == "String"
|
@@ -109,7 +127,7 @@ describe "Keys" do
|
|
109
127
|
}
|
110
128
|
|
111
129
|
before do
|
112
|
-
doc.collection.
|
130
|
+
doc.collection.insert_one(:dynamic => "foo")
|
113
131
|
doc.first
|
114
132
|
end
|
115
133
|
|
@@ -129,7 +147,7 @@ describe "Keys" do
|
|
129
147
|
describe "with invalid names" do
|
130
148
|
it "should warn when key names start with an uppercase letter" do
|
131
149
|
doc = Doc {}
|
132
|
-
|
150
|
+
Kernel.should_receive(:warn).once.with(/may not start with uppercase letters/)
|
133
151
|
doc.class_eval do
|
134
152
|
key :NotConstant
|
135
153
|
end
|
@@ -137,30 +155,30 @@ describe "Keys" do
|
|
137
155
|
|
138
156
|
it "should handle keys that start with uppercase letters by translating their first letter to lowercase" do
|
139
157
|
doc = Doc {}
|
140
|
-
|
158
|
+
Kernel.stub(:warn)
|
141
159
|
doc.class_eval do
|
142
160
|
key :NotConstant
|
143
161
|
end
|
144
|
-
doc.collection.
|
162
|
+
doc.collection.insert_one("NotConstant" => "Just data!")
|
145
163
|
doc.first.notConstant.should == "Just data!"
|
146
164
|
end
|
147
165
|
|
148
166
|
it "should not create accessors for bad keys" do
|
149
167
|
doc = Doc {}
|
150
|
-
|
168
|
+
doc.should_not_receive(:create_accessors_for)
|
151
169
|
doc.class_eval do
|
152
170
|
key :"bad-name", :__dynamic => true
|
153
171
|
end
|
154
|
-
|
172
|
+
lambda { doc.new.method(:"bad-name") }.should raise_error(NameError)
|
155
173
|
end
|
156
174
|
|
157
175
|
it "should not create accessors for reserved keys" do
|
158
176
|
doc = Doc {}
|
159
|
-
|
177
|
+
doc.should_not_receive(:create_accessors_for)
|
160
178
|
doc.class_eval do
|
161
179
|
key :"class", :__dynamic => true
|
162
180
|
end
|
163
|
-
|
181
|
+
doc.new.class.should == doc
|
164
182
|
end
|
165
183
|
|
166
184
|
it "should create accessors for good keys" do
|
@@ -168,13 +186,13 @@ describe "Keys" do
|
|
168
186
|
key :good_name
|
169
187
|
}
|
170
188
|
doc.new.good_name.should be_nil
|
171
|
-
|
189
|
+
lambda { doc.new.method("good_name") }.should_not raise_error
|
172
190
|
end
|
173
191
|
end
|
174
192
|
|
175
193
|
it "should handle loading dynamic fields from the database that have bad names" do
|
176
194
|
doc = Doc {}
|
177
|
-
doc.collection.
|
195
|
+
doc.collection.insert_one("foo-bar" => "baz-bin")
|
178
196
|
|
179
197
|
doc.first["foo-bar"].should == "baz-bin"
|
180
198
|
end
|
@@ -195,7 +213,7 @@ describe "Keys" do
|
|
195
213
|
end
|
196
214
|
|
197
215
|
it "should serialize with aliased keys" do
|
198
|
-
AliasedKeyModel.collection.
|
216
|
+
AliasedKeyModel.collection.find.first.keys.should =~ %w(_id f bar)
|
199
217
|
|
200
218
|
AliasedKeyModel.first.tap do |d|
|
201
219
|
d.foo.should == "whee!"
|
@@ -219,15 +237,15 @@ describe "Keys" do
|
|
219
237
|
it "should permit dealiasing of atomic operations" do
|
220
238
|
m = AliasedKeyModel.first
|
221
239
|
m.set(:foo => 1)
|
222
|
-
AliasedKeyModel.collection.
|
223
|
-
AliasedKeyModel.collection.
|
240
|
+
AliasedKeyModel.collection.find.first["f"].should == 1
|
241
|
+
AliasedKeyModel.collection.find.first["foo"].should be_nil
|
224
242
|
end
|
225
243
|
|
226
244
|
it "should permit dealiasing of update operations" do
|
227
245
|
m = AliasedKeyModel.first
|
228
246
|
m.update_attributes(:foo => 1)
|
229
|
-
AliasedKeyModel.collection.
|
230
|
-
AliasedKeyModel.collection.
|
247
|
+
AliasedKeyModel.collection.find.first["f"].should == 1
|
248
|
+
AliasedKeyModel.collection.find.first["foo"].should be_nil
|
231
249
|
end
|
232
250
|
|
233
251
|
it "should not break when unaliasing non-keys" do
|
@@ -246,7 +264,7 @@ describe "Keys" do
|
|
246
264
|
before { AliasedKeyModel.create(:with_underscores => "foobar") }
|
247
265
|
it "should work" do
|
248
266
|
AliasedKeyModel.first.with_underscores.should == "foobar"
|
249
|
-
AliasedKeyModel.collection.
|
267
|
+
AliasedKeyModel.collection.find.first["with-hyphens"].should == "foobar"
|
250
268
|
end
|
251
269
|
end
|
252
270
|
|
@@ -254,7 +272,7 @@ describe "Keys" do
|
|
254
272
|
before { AliasedKeyModel.create(:field_name => "foobar") }
|
255
273
|
it "should work" do
|
256
274
|
AliasedKeyModel.first.field_name.should == "foobar"
|
257
|
-
AliasedKeyModel.collection.
|
275
|
+
AliasedKeyModel.collection.find.first["alternate_field_name"].should == "foobar"
|
258
276
|
end
|
259
277
|
end
|
260
278
|
|
@@ -291,7 +309,7 @@ describe "Keys" do
|
|
291
309
|
owner.reload
|
292
310
|
owner.associated_documents.to_a.should =~ associated_documents.to_a
|
293
311
|
|
294
|
-
AssociatedKeyWithAlias.collection.
|
312
|
+
AssociatedKeyWithAlias.collection.find.first.keys.should =~ %w(_id n aid)
|
295
313
|
end
|
296
314
|
|
297
315
|
it "should work with embedded documents" do
|
@@ -301,7 +319,7 @@ describe "Keys" do
|
|
301
319
|
|
302
320
|
owner.reload
|
303
321
|
owner.other_documents[0].embedded_name.should == "Underling"
|
304
|
-
owner.collection.
|
322
|
+
owner.collection.find.first["other_documents"][0]["en"].should == "Underling"
|
305
323
|
end
|
306
324
|
end
|
307
325
|
end
|
@@ -334,6 +352,19 @@ describe "Keys" do
|
|
334
352
|
it 'should remove the key' do
|
335
353
|
DocWithRemovedKey.keys.should_not have_key "_something"
|
336
354
|
end
|
355
|
+
end
|
337
356
|
|
357
|
+
describe "default with no type" do
|
358
|
+
it "should work (regression)" do
|
359
|
+
doc = Doc do
|
360
|
+
key :a_num, default: 0
|
361
|
+
end
|
362
|
+
|
363
|
+
instance = doc.new
|
364
|
+
instance.a_num.should == 0
|
365
|
+
|
366
|
+
instance = doc.new(a_num: 10)
|
367
|
+
instance.a_num.should == 10
|
368
|
+
end
|
338
369
|
end
|
339
370
|
end
|