mongo_mapper 0.14.0 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +5 -5
  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/connection.rb +16 -38
  10. data/lib/mongo_mapper/extensions/object_id.rb +5 -1
  11. data/lib/mongo_mapper/plugins/accessible.rb +1 -1
  12. data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
  13. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
  14. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +36 -6
  15. data/lib/mongo_mapper/plugins/associations/in_foreign_array_proxy.rb +136 -0
  16. data/lib/mongo_mapper/plugins/associations/many_association.rb +4 -2
  17. data/lib/mongo_mapper/plugins/associations/proxy.rb +5 -1
  18. data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -4
  19. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  20. data/lib/mongo_mapper/plugins/document.rb +1 -1
  21. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
  22. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
  23. data/lib/mongo_mapper/plugins/embedded_document.rb +1 -1
  24. data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
  25. data/lib/mongo_mapper/plugins/indexes.rb +13 -6
  26. data/lib/mongo_mapper/plugins/keys/key.rb +13 -8
  27. data/lib/mongo_mapper/plugins/keys.rb +9 -2
  28. data/lib/mongo_mapper/plugins/modifiers.rb +39 -14
  29. data/lib/mongo_mapper/plugins/persistence.rb +6 -2
  30. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +6 -6
  31. data/lib/mongo_mapper/plugins/querying.rb +9 -3
  32. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  33. data/lib/mongo_mapper/plugins/stats.rb +1 -3
  34. data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
  35. data/lib/mongo_mapper/railtie.rb +1 -0
  36. data/lib/mongo_mapper/utils.rb +2 -2
  37. data/lib/mongo_mapper/version.rb +1 -1
  38. data/lib/mongo_mapper.rb +3 -0
  39. data/spec/examples.txt +1717 -0
  40. data/spec/functional/accessible_spec.rb +7 -1
  41. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
  42. data/spec/functional/associations/belongs_to_proxy_spec.rb +22 -5
  43. data/spec/functional/associations/in_array_proxy_spec.rb +149 -14
  44. data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
  45. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  46. data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
  47. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
  48. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  49. data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
  50. data/spec/functional/associations/one_proxy_spec.rb +8 -8
  51. data/spec/functional/associations_spec.rb +3 -3
  52. data/spec/functional/binary_spec.rb +2 -2
  53. data/spec/functional/caching_spec.rb +15 -22
  54. data/spec/functional/callbacks_spec.rb +2 -2
  55. data/spec/functional/counter_cache_spec.rb +10 -10
  56. data/spec/functional/dirty_spec.rb +27 -10
  57. data/spec/functional/document_spec.rb +5 -8
  58. data/spec/functional/dumpable_spec.rb +1 -1
  59. data/spec/functional/embedded_document_spec.rb +5 -5
  60. data/spec/functional/identity_map_spec.rb +8 -8
  61. data/spec/functional/indexes_spec.rb +19 -18
  62. data/spec/functional/keys_spec.rb +51 -33
  63. data/spec/functional/logger_spec.rb +2 -2
  64. data/spec/functional/modifiers_spec.rb +81 -19
  65. data/spec/functional/partial_updates_spec.rb +8 -8
  66. data/spec/functional/protected_spec.rb +1 -1
  67. data/spec/functional/querying_spec.rb +70 -22
  68. data/spec/functional/safe_spec.rb +23 -27
  69. data/spec/functional/sci_spec.rb +7 -7
  70. data/spec/functional/scopes_spec.rb +1 -1
  71. data/spec/functional/static_keys_spec.rb +2 -2
  72. data/spec/functional/stats_spec.rb +28 -12
  73. data/spec/functional/strong_parameters_spec.rb +49 -0
  74. data/spec/functional/validations_spec.rb +8 -16
  75. data/spec/quality_spec.rb +1 -1
  76. data/spec/spec_helper.rb +32 -8
  77. data/spec/support/matchers.rb +1 -1
  78. data/spec/unit/associations/proxy_spec.rb +1 -5
  79. data/spec/unit/clone_spec.rb +1 -1
  80. data/spec/unit/document_spec.rb +3 -3
  81. data/spec/unit/embedded_document_spec.rb +4 -5
  82. data/spec/unit/extensions_spec.rb +3 -4
  83. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  84. data/spec/unit/key_spec.rb +16 -17
  85. data/spec/unit/keys_spec.rb +17 -8
  86. data/spec/unit/mongo_mapper_spec.rb +41 -88
  87. data/spec/unit/rails_spec.rb +2 -2
  88. data/spec/unit/validations_spec.rb +18 -18
  89. metadata +41 -24
  90. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
@@ -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
@@ -1,11 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Logger" do
4
- context "with connection that has logger" do
4
+ context "with connection that has logger", without_connection: true do
5
5
  before do
6
6
  @output = StringIO.new
7
7
  @logger = Logger.new(@output)
8
- MongoMapper.connection = Mongo::MongoClient.new('127.0.0.1', 27017, :logger => @logger)
8
+ MongoMapper.connection = Mongo::Client.new(['127.0.0.1:27017'], :logger => @logger)
9
9
  end
10
10
 
11
11
  it "should be able to get access to that logger" do
@@ -4,7 +4,7 @@ module Modifiers
4
4
  describe "Modifiers" do
5
5
  let(:page_class_with_compound_key) {
6
6
  Doc do
7
- key :_id, BSON::OrderedHash, :default => lambda { BSON::OrderedHash['n', 42, 'i', BSON::ObjectId.new] }
7
+ key :_id, Hash, :default => lambda { Hash['n', 42, 'i', BSON::ObjectId.new] }
8
8
  key :title, String
9
9
  key :day_count, Integer, :default => 0
10
10
  key :week_count, Integer, :default => 0
@@ -24,7 +24,7 @@ module Modifiers
24
24
  }
25
25
 
26
26
  def assert_page_counts(page, day_count, week_count, month_count)
27
- doc = page.collection.find_one({:_id => page.id})
27
+ doc = page.collection.find({:_id => page.id}).first
28
28
  doc.should be_present, "Could not find document"
29
29
  doc.fetch('day_count').should == day_count
30
30
  doc.fetch('week_count').should == week_count
@@ -32,7 +32,7 @@ module Modifiers
32
32
  end
33
33
 
34
34
  def assert_keys_removed(page, *keys)
35
- page.class.collection.find_one({:_id => page.id}).tap do |doc|
35
+ page.class.collection.find({:_id => page.id}).first.tap do |doc|
36
36
  doc.should be_present, "Could not find document"
37
37
  (doc.keys & keys).should be_empty, "Expected to not have keys #{keys.inspect}, got #{(keys & doc.keys).inspect}"
38
38
  end
@@ -69,10 +69,10 @@ module Modifiers
69
69
  it "should be able to pass safe option" do
70
70
  page_class.create(:title => "Better Be Safe than Sorry")
71
71
 
72
- expect_any_instance_of(Mongo::Collection).to receive(:update).with(
72
+ Mongo::Collection.any_instance.should_receive(:update_many).with(
73
73
  {:title => "Better Be Safe than Sorry"},
74
74
  {'$unset' => {:tags => 1}},
75
- {:w => 1, :multi => true}
75
+ {:w => 1}
76
76
  )
77
77
  page_class.unset({:title => "Better Be Safe than Sorry"}, :tags, {:w => 1})
78
78
  end
@@ -166,17 +166,17 @@ module Modifiers
166
166
  it "should typecast values before querying" do
167
167
  page_class.key :tags, Set
168
168
 
169
- expect {
169
+ lambda {
170
170
  page_class.set(page.id, :tags => ['foo', 'bar'].to_set)
171
171
  page.reload
172
172
  page.tags.should == Set.new(['foo', 'bar'])
173
- }.to_not raise_error
173
+ }.should_not raise_error
174
174
  end
175
175
 
176
- it "should not typecast keys that are not defined in document" do
177
- expect {
176
+ it "should not typecast keys that are not defined in document and have no default typecasing" do
177
+ lambda {
178
178
  page_class.set(page.id, :colors => ['red', 'green'].to_set)
179
- }.to raise_error(BSON::InvalidDocument)
179
+ }.should raise_error(BSON::Error::UnserializableClass, /does not define its BSON serialized type/)
180
180
  end
181
181
 
182
182
  it "should set keys that are not defined in document" do
@@ -196,10 +196,10 @@ module Modifiers
196
196
  it "should be able to pass safe option" do
197
197
  page_class.create(:title => "Better Be Safe than Sorry")
198
198
 
199
- expect_any_instance_of(Mongo::Collection).to receive(:update).with(
199
+ Mongo::Collection.any_instance.should_receive(:update_many).with(
200
200
  {:title => "Better Be Safe than Sorry"},
201
201
  {'$set' => {:title => "I like safety."}},
202
- {:w => 1, :multi => true}
202
+ {:w => 1}
203
203
  )
204
204
  page_class.set({:title => "Better Be Safe than Sorry"}, {:title => "I like safety."}, {:safe => true})
205
205
  end
@@ -238,6 +238,15 @@ module Modifiers
238
238
  context "push_all" do
239
239
  let(:tags) { %w(foo bar) }
240
240
 
241
+ before do
242
+ Kernel.stub(:warn)
243
+ end
244
+
245
+ it "should issue a warning" do
246
+ Kernel.should_receive(:warn).with("push_all no longer supported. use $push with $each")
247
+ page_class.push_all({:title => 'Home'}, :tags => tags)
248
+ end
249
+
241
250
  it "should work with criteria and modifier hashes" do
242
251
  page_class.push_all({:title => 'Home'}, :tags => tags)
243
252
 
@@ -385,9 +394,9 @@ module Modifiers
385
394
  page_class.create(:title => "Better Be Safe than Sorry")
386
395
 
387
396
  # We are trying to increment a key of type string here which should fail
388
- expect {
397
+ lambda {
389
398
  page_class.increment({:title => "Better Be Safe than Sorry"}, {:title => 1}, {:safe => true})
390
- }.to raise_error(Mongo::OperationFailure)
399
+ }.should raise_error(Mongo::Error::OperationFailure)
391
400
  end
392
401
 
393
402
  it "should be able to pass both safe and upsert options" do
@@ -397,19 +406,51 @@ module Modifiers
397
406
  page_class.first(:title => new_key_value).day_count.should == 1
398
407
  end
399
408
  end
409
+
410
+ context "upsert" do
411
+ it "should insert document if not present" do
412
+ lambda {
413
+ page_class.upsert({:title => 'A new story'}, {:title => 'A new story', :day_count => 1})
414
+ }.should change {page_class.count}
415
+ page_class.first(title: 'A new story').day_count.should == 1
416
+ end
417
+
418
+ it "should update documents if present" do
419
+ lambda {
420
+ page_class.upsert({:_id => page2.id}, {tags: %w(foo bar)})
421
+ }.should_not change {page_class.count}
422
+ page2.reload.tags.should == %w(foo bar)
423
+ end
424
+ end
425
+
426
+ context "find_and_modify" do
427
+ it "should retrieve the document without the changes" do
428
+ page_class.find_and_modify(query: {_id: page2.id}, update: {title: 'A new title'})['title'].should == 'Home'
429
+ page2.reload.title.should == 'A new title'
430
+ end
431
+
432
+ it "should allow find_and_modify options" do
433
+ page_class.find_and_modify(query: {_id: page2.id}, update: {title: 'A new title'}, return_document: :after)['title'].should == 'A new title'
434
+ end
435
+ end
436
+
400
437
  end
401
438
 
402
439
  context "compound keys" do
403
440
  it "should create a document" do
404
- expect {
441
+ lambda {
405
442
  page_class_with_compound_key.create(:title => 'Foo', :tags => %w(foo))
406
- }.to change { page_class_with_compound_key.count }.by(1)
443
+ }.should change { page_class_with_compound_key.count }.by(1)
407
444
  doc = page_class_with_compound_key.first
408
445
  page_class_with_compound_key.find(doc._id).should == doc
409
446
  end
410
447
  end
411
448
 
412
449
  context "instance methods" do
450
+ before do
451
+ Kernel.stub(:warn)
452
+ end
453
+
413
454
  {
414
455
  :page_class_with_standard_key => "with standard key",
415
456
  :page_class_with_compound_key => "with compound key",
@@ -430,6 +471,13 @@ module Modifiers
430
471
  assert_page_counts page, 1, 2, 3
431
472
  end
432
473
 
474
+ it "should be able to increment with just the field name" do
475
+ page = page_class.create
476
+ page.increment :day_count
477
+
478
+ assert_page_counts page, 1, 0, 0
479
+ end
480
+
433
481
  it "should be able to decrement with modifier hashes" do
434
482
  page = page_class.create(:day_count => 1, :week_count => 2, :month_count => 3)
435
483
  page.decrement(:day_count => 1, :week_count => 2, :month_count => 3)
@@ -437,6 +485,13 @@ module Modifiers
437
485
  assert_page_counts page, 0, 0, 0
438
486
  end
439
487
 
488
+ it "should be able to decrement with just the field name" do
489
+ page = page_class.create
490
+ page.decrement :day_count
491
+
492
+ assert_page_counts page, -1, 0, 0
493
+ end
494
+
440
495
  it "should always decrement when decrement is called whether number is positive or negative" do
441
496
  page = page_class.create(:day_count => 1, :week_count => 2, :month_count => 3)
442
497
  page.decrement(:day_count => -1, :week_count => 2, :month_count => -3)
@@ -467,6 +522,13 @@ module Modifiers
467
522
  page.tags.should == %w(foo bar)
468
523
  end
469
524
 
525
+ it "should issue a warning with push_all" do
526
+ Kernel.should_receive(:warn).with("push_all no longer supported. use $push with $each")
527
+
528
+ page = page_class.create
529
+ page.push_all(:tags => %w(foo bar))
530
+ end
531
+
470
532
  it "should be able to pull with criteria and modifier hashes" do
471
533
  page = page_class.create(:tags => %w(foo bar))
472
534
  page.pull(:tags => 'foo')
@@ -531,9 +593,9 @@ module Modifiers
531
593
  page = page_class.create(:title => "Safe Page")
532
594
 
533
595
  # We are trying to increment a key of type string here which should fail
534
- expect {
596
+ lambda {
535
597
  page.increment({:title => 1}, {:safe => true})
536
- }.to raise_error(Mongo::OperationFailure)
598
+ }.should raise_error(Mongo::Error::OperationFailure)
537
599
  end
538
600
 
539
601
  it "should be able to pass upsert and safe options" do
@@ -547,4 +609,4 @@ module Modifiers
547
609
  end
548
610
  end
549
611
  end
550
- end
612
+ end
@@ -85,9 +85,9 @@ describe "Partial Updates" do
85
85
  @obj.save!
86
86
 
87
87
  mock_collection = double 'collection'
88
- allow(@obj).to receive(:collection).and_return mock_collection
88
+ @obj.stub(:collection).and_return mock_collection
89
89
 
90
- expect(@obj.collection).to receive(:update).with({:_id => @obj.id}, {
90
+ @obj.collection.should_receive(:update_one).with({:_id => @obj.id}, {
91
91
  '$set' => {
92
92
  "string_field" => "bar",
93
93
  "updated_at" => kind_of(Time),
@@ -126,16 +126,16 @@ describe "Partial Updates" do
126
126
  @obj.save!
127
127
 
128
128
  mock_collection = double 'collection'
129
- allow(@obj).to receive(:collection).and_return mock_collection
129
+ @obj.stub(:collection).and_return mock_collection
130
130
 
131
- expect(@obj.collection).to receive(:save).with({
131
+ @obj.collection.should_receive(:update_one).with({:_id => @obj.id}, {
132
132
  "_id" => @obj.id,
133
133
  "string_field" => "bar",
134
134
  "array_field" => [],
135
135
  "hash_field" => {},
136
136
  "created_at" => kind_of(Time),
137
137
  "updated_at" => kind_of(Time),
138
- }, {})
138
+ }, {upsert: true})
139
139
 
140
140
  @obj.string_field = "bar"
141
141
  @obj.save!
@@ -234,7 +234,7 @@ describe "Partial Updates" do
234
234
  attrs = @obj.attributes.dup
235
235
  attrs.delete("foo")
236
236
 
237
- allow(@obj).to receive(:attributes).and_return(attrs)
237
+ @obj.stub(:attributes).and_return(attrs)
238
238
 
239
239
  @obj.fields_for_partial_update.should == {
240
240
  :set_fields => [],
@@ -566,11 +566,11 @@ describe "Partial Updates" do
566
566
  updates[:unset_fields].should == []
567
567
 
568
568
  mock_collection = double('collection')
569
- allow(obj).to receive(:collection).and_return(mock_collection)
569
+ obj.stub(:collection).and_return(mock_collection)
570
570
 
571
571
  update_query_expectation = hash_including("$set"=> hash_including("boolean_field"))
572
572
 
573
- obj.collection.should_not receive(:update).with(anything, update_query_expectation, anything)
573
+ obj.collection.should_not_receive(:update_one).with(anything, update_query_expectation, anything)
574
574
  obj.save!
575
575
  end
576
576
  end
@@ -115,7 +115,7 @@ describe "Single collection inherited protected attributes" do
115
115
  key :site_id, ObjectId
116
116
  attr_protected :site_id
117
117
  end
118
- GrandParent.collection.remove
118
+ GrandParent.collection.drop
119
119
 
120
120
  class ::Child < ::GrandParent
121
121
  key :position, Integer