mongo_mapper 0.14.0.rc1 → 0.15.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +5 -13
  2. data/LICENSE +1 -1
  3. data/{README.rdoc → README.md} +26 -21
  4. data/examples/keys.rb +1 -1
  5. data/examples/modifiers/set.rb +1 -1
  6. data/examples/querying.rb +1 -1
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +3 -0
  10. data/lib/mongo_mapper/connection.rb +16 -38
  11. data/lib/mongo_mapper/extensions/object_id.rb +5 -1
  12. data/lib/mongo_mapper/plugins/accessible.rb +1 -1
  13. data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
  14. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
  15. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +6 -0
  16. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +36 -6
  17. data/lib/mongo_mapper/plugins/associations/in_foreign_array_proxy.rb +136 -0
  18. data/lib/mongo_mapper/plugins/associations/many_association.rb +4 -2
  19. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +3 -1
  20. data/lib/mongo_mapper/plugins/associations/proxy.rb +11 -3
  21. data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -4
  22. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  23. data/lib/mongo_mapper/plugins/document.rb +1 -1
  24. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
  25. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
  26. data/lib/mongo_mapper/plugins/embedded_document.rb +2 -2
  27. data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
  28. data/lib/mongo_mapper/plugins/indexes.rb +13 -6
  29. data/lib/mongo_mapper/plugins/keys.rb +12 -7
  30. data/lib/mongo_mapper/plugins/keys/key.rb +13 -8
  31. data/lib/mongo_mapper/plugins/modifiers.rb +39 -14
  32. data/lib/mongo_mapper/plugins/persistence.rb +6 -2
  33. data/lib/mongo_mapper/plugins/querying.rb +9 -3
  34. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +6 -6
  35. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  36. data/lib/mongo_mapper/plugins/scopes.rb +19 -3
  37. data/lib/mongo_mapper/plugins/stats.rb +1 -3
  38. data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
  39. data/lib/mongo_mapper/railtie.rb +1 -0
  40. data/lib/mongo_mapper/utils.rb +2 -2
  41. data/lib/mongo_mapper/version.rb +1 -1
  42. data/spec/examples.txt +1729 -0
  43. data/spec/functional/accessible_spec.rb +7 -1
  44. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
  45. data/spec/functional/associations/belongs_to_proxy_spec.rb +55 -5
  46. data/spec/functional/associations/in_array_proxy_spec.rb +149 -14
  47. data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
  48. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  49. data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
  50. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
  51. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  52. data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
  53. data/spec/functional/associations/one_embedded_proxy_spec.rb +28 -0
  54. data/spec/functional/associations/one_proxy_spec.rb +19 -9
  55. data/spec/functional/associations_spec.rb +3 -3
  56. data/spec/functional/binary_spec.rb +2 -2
  57. data/spec/functional/caching_spec.rb +15 -22
  58. data/spec/functional/callbacks_spec.rb +2 -2
  59. data/spec/functional/counter_cache_spec.rb +10 -10
  60. data/spec/functional/dirty_spec.rb +48 -10
  61. data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
  62. data/spec/functional/document_spec.rb +5 -8
  63. data/spec/functional/dumpable_spec.rb +1 -1
  64. data/spec/functional/embedded_document_spec.rb +5 -5
  65. data/spec/functional/identity_map_spec.rb +8 -8
  66. data/spec/functional/indexes_spec.rb +19 -18
  67. data/spec/functional/keys_spec.rb +51 -33
  68. data/spec/functional/logger_spec.rb +2 -2
  69. data/spec/functional/modifiers_spec.rb +81 -19
  70. data/spec/functional/partial_updates_spec.rb +8 -8
  71. data/spec/functional/protected_spec.rb +1 -1
  72. data/spec/functional/querying_spec.rb +70 -22
  73. data/spec/functional/safe_spec.rb +23 -27
  74. data/spec/functional/sci_spec.rb +7 -7
  75. data/spec/functional/scopes_spec.rb +89 -1
  76. data/spec/functional/static_keys_spec.rb +2 -2
  77. data/spec/functional/stats_spec.rb +28 -12
  78. data/spec/functional/strong_parameters_spec.rb +49 -0
  79. data/spec/functional/validations_spec.rb +8 -16
  80. data/spec/quality_spec.rb +1 -1
  81. data/spec/spec_helper.rb +39 -8
  82. data/spec/support/matchers.rb +1 -1
  83. data/spec/unit/associations/proxy_spec.rb +13 -5
  84. data/spec/unit/clone_spec.rb +1 -1
  85. data/spec/unit/document_spec.rb +3 -3
  86. data/spec/unit/embedded_document_spec.rb +4 -5
  87. data/spec/unit/extensions_spec.rb +2 -2
  88. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  89. data/spec/unit/key_spec.rb +16 -17
  90. data/spec/unit/keys_spec.rb +17 -8
  91. data/spec/unit/mongo_mapper_spec.rb +41 -88
  92. data/spec/unit/rails_spec.rb +2 -2
  93. data/spec/unit/validations_spec.rb +18 -18
  94. metadata +53 -31
  95. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
@@ -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
- expect {
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
- }.to_not raise_error
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
- expect {
174
+ lambda {
175
175
  @comment.save!
176
176
  @article.reload
177
- }.to change(@article, :commentable_count).by(1)
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
- expect {
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
- }.to change(@article, :commentable_count).by(1)
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
- expect {
194
+ lambda {
195
195
  @comment.destroy
196
196
  @article.reload
197
- }.to change(@article, :commentable_count).by(-1)
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
- expect {
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
- }.to change(@article, :commentable_count).by(1)
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
- expect {
229
+ lambda {
230
230
  @comment.save!
231
- }.to raise_error(MongoMapper::Plugins::CounterCache::InvalidCounterCacheError)
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
- expect_any_instance_of(@document).to receive(:attribute_will_change!).never
52
- expect_any_instance_of(@document).to receive(:attribute_changed?).never
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
- it "should reset changes when set back to the original value" do
224
- doc = @document.create(:a=>"b")
225
- doc.a = "c"
226
- doc.a = "b"
227
- doc.changed?.should be_falsey
228
- end
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.reset_a!
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.reset_a!
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
- expect(@instance.foos).to receive(:reset).at_least(1).times
244
- expect(@instance.bars).to receive(:reset).at_least(1).times
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
- expect { @instance.reload }.to raise_error(MongoMapper::DocumentNotFound)
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.insert({
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
- expect(ObjectSpace).to receive(:each_object).never
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
- expect { Marshal.dump(answer) }.to_not raise_error
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
- expect(person).to receive(:save!)
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
- expect(pet).to receive(:attributes=).with(attributes)
276
- expect(pet).to receive(:save!)
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.insert(:pets => [nil, {:name => "Sasha"}])
292
- expect { @klass.all.first.pets }.to_not raise_error
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
- expect_any_instance_of(Mongo::Collection).to receive(:find_one).never
18
- expect_any_instance_of(Mongo::Collection).to receive(:find).never
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
- expect_any_instance_of(Mongo::Collection).to receive(:find_one).once.and_return({})
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
- expect do
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.to_not raise_error
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.remove
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.target)
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.target)
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
- allow(@document).to receive(:collection).and_return(double(:name => :foo))
16
+ @document.stub(:collection).and_return(double(:name => :foo, :indexes => double()))
17
17
  end
18
- [:create_index, :ensure_index].each do |method|
19
- it "should delegate #{method} to collection" do
20
- expect(@document.collection).to receive(method).with(:arg, {})
21
- @document.send(method, :arg)
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
- expect(@document.collection).to receive(:drop_index).with(:arg)
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
- expect(@document.collection).to receive(:drop_indexes)
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
- silence_stderr { @document.key :father, String, :index => true }
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 an typecasted array" do
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
- Person.new value
44
+ new(value)
49
45
  end
50
46
  end
51
47
 
52
- it "should not mutate the model's state" do
53
- person = Person.new "Bob"
54
- doc = TypecastedKeyModel.new(:people => [person])
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])
55
56
 
56
- doc.save
57
+ doc.save!
58
+
59
+ doc.people.should == [person]
60
+ end
61
+ end
57
62
 
58
- doc.people.should == [person]
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]))
72
+
73
+ doc.save!
74
+
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
- expect { doc.new }.to_not raise_error
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
- expect { doc.new }.to_not raise_error
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.insert('class' => 'String')
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.insert(:dynamic => "foo")
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
- expect(Kernel).to receive(:warn).once.with(/may not start with uppercase letters/)
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
- allow(Kernel).to receive(:warn)
158
+ Kernel.stub(:warn)
141
159
  doc.class_eval do
142
160
  key :NotConstant
143
161
  end
144
- doc.collection.insert("NotConstant" => "Just data!")
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
- expect(doc).to_not receive(:create_accessors_for)
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
- expect { doc.new.method(:"bad-name") }.to raise_error(NameError)
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
- expect(doc).to_not receive(:create_accessors_for)
177
+ doc.should_not_receive(:create_accessors_for)
160
178
  doc.class_eval do
161
179
  key :"class", :__dynamic => true
162
180
  end
163
- expect(doc.new.class).to eq doc
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
- expect { doc.new.method("good_name") }.to_not raise_error
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.insert("foo-bar" => "baz-bin")
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.find_one.keys.should =~ %w(_id f bar)
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.find_one["f"].should == 1
223
- AliasedKeyModel.collection.find_one["foo"].should be_nil
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.find_one["f"].should == 1
230
- AliasedKeyModel.collection.find_one["foo"].should be_nil
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.find_one["with-hyphens"].should == "foobar"
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.find_one["alternate_field_name"].should == "foobar"
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.find_one.keys.should =~ %w(_id n aid)
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.find_one["other_documents"][0]["en"].should == "Underling"
322
+ owner.collection.find.first["other_documents"][0]["en"].should == "Underling"
305
323
  end
306
324
  end
307
325
  end