mongo_mapper 0.13.0.beta2 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +64 -0
  4. data/examples/keys.rb +3 -3
  5. data/examples/modifiers/set.rb +2 -2
  6. data/examples/querying.rb +3 -3
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +5 -0
  10. data/lib/mongo_mapper/connection.rb +16 -37
  11. data/lib/mongo_mapper/document.rb +4 -0
  12. data/lib/mongo_mapper/extensions/array.rb +14 -6
  13. data/lib/mongo_mapper/extensions/hash.rb +15 -3
  14. data/lib/mongo_mapper/extensions/object.rb +4 -0
  15. data/lib/mongo_mapper/extensions/object_id.rb +5 -1
  16. data/lib/mongo_mapper/extensions/string.rb +13 -5
  17. data/lib/mongo_mapper/extensions/symbol.rb +18 -0
  18. data/lib/mongo_mapper/plugins/accessible.rb +14 -4
  19. data/lib/mongo_mapper/plugins/associations.rb +7 -6
  20. data/lib/mongo_mapper/plugins/associations/base.rb +18 -13
  21. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +10 -1
  22. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +9 -8
  23. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +12 -11
  24. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +4 -4
  25. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +24 -23
  26. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +18 -16
  27. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +55 -48
  28. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +14 -13
  29. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +7 -6
  30. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +7 -5
  31. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +17 -14
  32. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +14 -13
  33. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +9 -9
  34. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +27 -26
  35. data/lib/mongo_mapper/plugins/associations/proxy.rb +31 -28
  36. data/lib/mongo_mapper/plugins/callbacks.rb +14 -1
  37. data/lib/mongo_mapper/plugins/counter_cache.rb +97 -0
  38. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  39. data/lib/mongo_mapper/plugins/document.rb +1 -1
  40. data/lib/mongo_mapper/plugins/dynamic_querying.rb +10 -9
  41. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +18 -17
  42. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +2 -1
  43. data/lib/mongo_mapper/plugins/embedded_document.rb +1 -1
  44. data/lib/mongo_mapper/plugins/identity_map.rb +1 -1
  45. data/lib/mongo_mapper/plugins/indexes.rb +37 -2
  46. data/lib/mongo_mapper/plugins/keys.rb +202 -142
  47. data/lib/mongo_mapper/plugins/keys/key.rb +22 -13
  48. data/lib/mongo_mapper/plugins/keys/static.rb +45 -0
  49. data/lib/mongo_mapper/plugins/modifiers.rb +59 -28
  50. data/lib/mongo_mapper/plugins/partial_updates.rb +86 -0
  51. data/lib/mongo_mapper/plugins/persistence.rb +13 -8
  52. data/lib/mongo_mapper/plugins/protected.rb +6 -5
  53. data/lib/mongo_mapper/plugins/querying.rb +85 -42
  54. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +32 -9
  55. data/lib/mongo_mapper/plugins/rails.rb +1 -0
  56. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  57. data/lib/mongo_mapper/plugins/sci.rb +4 -1
  58. data/lib/mongo_mapper/plugins/scopes.rb +78 -7
  59. data/lib/mongo_mapper/plugins/stats.rb +17 -0
  60. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  61. data/lib/mongo_mapper/plugins/touch.rb +1 -1
  62. data/lib/mongo_mapper/plugins/validations.rb +7 -2
  63. data/lib/mongo_mapper/railtie.rb +20 -0
  64. data/lib/mongo_mapper/railtie/database.rake +1 -1
  65. data/lib/mongo_mapper/utils.rb +2 -2
  66. data/lib/mongo_mapper/version.rb +1 -1
  67. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +12 -13
  68. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +9 -9
  69. data/spec/examples.txt +1643 -0
  70. data/spec/functional/accessible_spec.rb +13 -13
  71. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +13 -13
  72. data/spec/functional/associations/belongs_to_proxy_spec.rb +18 -19
  73. data/spec/functional/associations/in_array_proxy_spec.rb +10 -10
  74. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  75. data/spec/functional/associations/many_documents_proxy_spec.rb +85 -14
  76. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +13 -13
  77. data/spec/functional/associations/many_embedded_proxy_spec.rb +1 -1
  78. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  79. data/spec/functional/associations/one_as_proxy_spec.rb +10 -10
  80. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +9 -9
  81. data/spec/functional/associations/one_embedded_proxy_spec.rb +3 -3
  82. data/spec/functional/associations/one_proxy_spec.rb +10 -10
  83. data/spec/functional/associations_spec.rb +3 -3
  84. data/spec/functional/binary_spec.rb +2 -2
  85. data/spec/functional/caching_spec.rb +8 -15
  86. data/spec/functional/callbacks_spec.rb +89 -2
  87. data/spec/functional/counter_cache_spec.rb +235 -0
  88. data/spec/functional/dirty_spec.rb +63 -46
  89. data/spec/functional/document_spec.rb +30 -2
  90. data/spec/functional/dumpable_spec.rb +1 -1
  91. data/spec/functional/embedded_document_spec.rb +18 -18
  92. data/spec/functional/identity_map_spec.rb +27 -14
  93. data/spec/functional/indexes_spec.rb +44 -19
  94. data/spec/functional/keys_spec.rb +117 -15
  95. data/spec/functional/logger_spec.rb +3 -3
  96. data/spec/functional/modifiers_spec.rb +67 -19
  97. data/spec/functional/partial_updates_spec.rb +577 -0
  98. data/spec/functional/protected_spec.rb +14 -14
  99. data/spec/functional/querying_spec.rb +55 -28
  100. data/spec/functional/safe_spec.rb +23 -27
  101. data/spec/functional/sci_spec.rb +49 -14
  102. data/spec/functional/scopes_spec.rb +235 -2
  103. data/spec/functional/static_keys_spec.rb +153 -0
  104. data/spec/functional/stats_spec.rb +86 -0
  105. data/spec/functional/touch_spec.rb +6 -6
  106. data/spec/functional/validations_spec.rb +51 -57
  107. data/spec/quality_spec.rb +51 -0
  108. data/spec/spec_helper.rb +37 -9
  109. data/spec/support/matchers.rb +5 -14
  110. data/spec/unit/associations/base_spec.rb +12 -12
  111. data/spec/unit/associations/belongs_to_association_spec.rb +2 -2
  112. data/spec/unit/associations/many_association_spec.rb +2 -2
  113. data/spec/unit/associations/one_association_spec.rb +2 -2
  114. data/spec/unit/associations/proxy_spec.rb +19 -16
  115. data/spec/unit/clone_spec.rb +1 -1
  116. data/spec/unit/document_spec.rb +8 -8
  117. data/spec/unit/dynamic_finder_spec.rb +8 -8
  118. data/spec/unit/embedded_document_spec.rb +18 -19
  119. data/spec/unit/extensions_spec.rb +41 -17
  120. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  121. data/spec/unit/inspect_spec.rb +4 -4
  122. data/spec/unit/key_spec.rb +28 -26
  123. data/spec/unit/keys_spec.rb +10 -10
  124. data/spec/unit/model_generator_spec.rb +2 -4
  125. data/spec/unit/mongo_mapper_spec.rb +38 -85
  126. data/spec/unit/rails_spec.rb +5 -0
  127. data/spec/unit/serialization_spec.rb +1 -1
  128. data/spec/unit/time_zones_spec.rb +2 -2
  129. data/spec/unit/validations_spec.rb +28 -15
  130. metadata +188 -161
  131. data/README.rdoc +0 -55
  132. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
@@ -130,6 +130,34 @@ describe "Document" do
130
130
  end
131
131
  end
132
132
 
133
+ context "symbol key" do
134
+ before do
135
+ @document.key :foo, Symbol, :default => lambda { 123 }
136
+ end
137
+
138
+ it "should return default value" do
139
+ doc = @document.new
140
+ doc.foo.should == :'123'
141
+ end
142
+
143
+ it "should return symbol value" do
144
+ doc = @document.create :foo => 'qwerty'
145
+ doc.foo.should == :qwerty
146
+
147
+ doc.set :foo => 'poiuyt'
148
+ doc.reload
149
+ doc.foo.should == :poiuyt
150
+
151
+ doc.foo = 'asdf'
152
+ doc.foo.should == :asdf
153
+ end
154
+
155
+ it "should return typecasted value" do
156
+ doc = @document.new
157
+ (doc.foo = 'qwerty').should == 'qwerty'
158
+ end
159
+ end
160
+
133
161
  it "should have instance method for collection" do
134
162
  @document.new.collection.name.should == @document.collection.name
135
163
  end
@@ -243,7 +271,7 @@ describe "Document" do
243
271
 
244
272
  it "should raise DocumentNotFound if not found" do
245
273
  @instance.destroy
246
- expect { @instance.reload }.to raise_error(MongoMapper::DocumentNotFound)
274
+ lambda { @instance.reload }.should raise_error(MongoMapper::DocumentNotFound)
247
275
  end
248
276
 
249
277
  it "should clear keys that were removed from the database" do
@@ -255,7 +283,7 @@ describe "Document" do
255
283
  context "database has keys not defined in model" do
256
284
  before do
257
285
  @id = BSON::ObjectId.new
258
- @document.collection.insert({
286
+ @document.collection.insert_one({
259
287
  :_id => @id,
260
288
  :first_name => 'John',
261
289
  :last_name => 'Nunemaker',
@@ -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
@@ -70,14 +70,14 @@ describe "EmbeddedDocument" do
70
70
  it "should be true until document is created" do
71
71
  address = @address_class.new(:city => 'South Bend', :state => 'IN')
72
72
  doc = @klass.new(:foo => address)
73
- address.new?.should be_true
73
+ address.new?.should be_truthy
74
74
  end
75
75
 
76
76
  it "should be false after document is saved" do
77
77
  address = @address_class.new(:city => 'South Bend', :state => 'IN')
78
78
  doc = @klass.new(:foo => address)
79
79
  doc.save
80
- doc.foo.new?.should be_false
80
+ doc.foo.new?.should be_falsey
81
81
  end
82
82
 
83
83
  it "should be false when loaded from database" do
@@ -86,7 +86,7 @@ describe "EmbeddedDocument" do
86
86
  doc.save
87
87
 
88
88
  doc.reload
89
- doc.foo.new?.should be_false
89
+ doc.foo.new?.should be_falsey
90
90
  end
91
91
  end
92
92
 
@@ -115,9 +115,9 @@ describe "EmbeddedDocument" do
115
115
  it "should be true until existing document is saved" do
116
116
  @doc.save
117
117
  pet = @doc.pets.build(:name => 'Rasmus')
118
- pet.new?.should be_true
118
+ pet.new?.should be_truthy
119
119
  @doc.save
120
- pet.new?.should be_false
120
+ pet.new?.should be_falsey
121
121
  end
122
122
  end
123
123
 
@@ -131,9 +131,9 @@ describe "EmbeddedDocument" do
131
131
 
132
132
  it "should be true until existing document is saved" do
133
133
  address = @doc.pets.first.addresses.build(:city => 'Holland', :state => 'MI')
134
- address.new?.should be_true
134
+ address.new?.should be_truthy
135
135
  @doc.save
136
- address.new?.should be_false
136
+ address.new?.should be_falsey
137
137
  end
138
138
  end
139
139
 
@@ -146,9 +146,9 @@ describe "EmbeddedDocument" do
146
146
  it "should be true until existing document is saved" do
147
147
  @doc.save
148
148
  @doc.build_address(:city => 'Holland', :state => 'MI')
149
- @doc.address.new?.should be_true
149
+ @doc.address.new?.should be_truthy
150
150
  @doc.save
151
- @doc.address.new?.should be_false
151
+ @doc.address.new?.should be_falsey
152
152
  end
153
153
  end
154
154
 
@@ -162,9 +162,9 @@ describe "EmbeddedDocument" do
162
162
 
163
163
  it "should be true until existing document is saved" do
164
164
  address = @doc.pets.first.build_address(:city => 'Holland', :stats => 'MI')
165
- address.new?.should be_true
165
+ address.new?.should be_truthy
166
166
  @doc.save
167
- address.new?.should be_false
167
+ address.new?.should be_falsey
168
168
  end
169
169
  end
170
170
 
@@ -248,7 +248,7 @@ describe "EmbeddedDocument" do
248
248
  person.reload
249
249
  pet = person.pets.first
250
250
 
251
- pet.update_attribute('name', 'koda').should be_true
251
+ pet.update_attribute('name', 'koda').should be_truthy
252
252
  person.reload
253
253
  person.pets.first._id.should == pet._id
254
254
  person.pets.first.name.should == 'koda'
@@ -260,7 +260,7 @@ describe "EmbeddedDocument" do
260
260
  person.reload
261
261
  pet = person.pets.first
262
262
 
263
- pet.update_attributes(:name => 'koda').should be_true
263
+ pet.update_attributes(:name => 'koda').should be_truthy
264
264
  person.reload
265
265
  person.pets.first._id.should == pet._id
266
266
  person.pets.first.name.should == 'koda'
@@ -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"
@@ -302,15 +302,15 @@ describe "EmbeddedDocument" do
302
302
  person.update_attributes!({"pets" => ["name" => "sparky", "flag" => "false"]})
303
303
  person.reload
304
304
  person.pets.first.name.should == "sparky"
305
- person.pets.first.flag.should be_false
305
+ person.pets.first.flag.should be_falsey
306
306
  end
307
307
 
308
308
  it "should update attributes with symbol keys" do
309
309
  person = @klass.create(:pets => [@pet_klass.new(:name => 'Rasmus', :flag => true)])
310
- person.update_attributes!({pets: [:name => "sparky", :flag => "false"]})
310
+ person.update_attributes!({:pets => [:name => "sparky", :flag => "false"]})
311
311
  person.reload
312
312
  person.pets.first.name.should == "sparky"
313
- person.pets.first.flag.should be_false
313
+ person.pets.first.flag.should be_falsey
314
314
  end
315
315
  end
316
316
  end
@@ -3,13 +3,13 @@ require 'spec_helper'
3
3
  describe "IdentityMap" do
4
4
  def assert_in_map(*resources)
5
5
  [resources].flatten.each do |resource|
6
- MongoMapper::Plugins::IdentityMap.include?(resource).should be_true
6
+ MongoMapper::Plugins::IdentityMap.include?(resource).should be_truthy
7
7
  end
8
8
  end
9
9
 
10
10
  def assert_not_in_map(*resources)
11
11
  [resources].flatten.each do |resource|
12
- MongoMapper::Plugins::IdentityMap.include?(resource).should be_false
12
+ MongoMapper::Plugins::IdentityMap.include?(resource).should be_falsey
13
13
  end
14
14
  end
15
15
 
@@ -19,7 +19,7 @@ describe "IdentityMap" do
19
19
  end
20
20
 
21
21
  def expects_one_query
22
- Mongo::Collection.any_instance.should_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
@@ -27,7 +27,7 @@ describe "IdentityMap" do
27
27
  end
28
28
 
29
29
  it "should default identity map to off" do
30
- MongoMapper::Plugins::IdentityMap.enabled?.should be_false
30
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_falsey
31
31
  end
32
32
 
33
33
  context "Document" do
@@ -84,16 +84,16 @@ describe "IdentityMap" do
84
84
  MongoMapper::Plugins::IdentityMap.use do
85
85
  @person_class.find(@person.id)
86
86
  end
87
- MongoMapper::Plugins::IdentityMap.repository.empty?.should be_true
87
+ MongoMapper::Plugins::IdentityMap.repository.empty?.should be_truthy
88
88
  end
89
89
 
90
90
  it "should set enabled back to original status" do
91
91
  MongoMapper::Plugins::IdentityMap.enabled = false
92
- MongoMapper::Plugins::IdentityMap.enabled?.should be_false
92
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_falsey
93
93
  MongoMapper::Plugins::IdentityMap.use do
94
- MongoMapper::Plugins::IdentityMap.enabled?.should be_true
94
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_truthy
95
95
  end
96
- MongoMapper::Plugins::IdentityMap.enabled?.should be_false
96
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_falsey
97
97
  end
98
98
  end
99
99
 
@@ -111,11 +111,11 @@ describe "IdentityMap" do
111
111
 
112
112
  it "should set enabled back to original value" do
113
113
  MongoMapper::Plugins::IdentityMap.enabled = true
114
- MongoMapper::Plugins::IdentityMap.enabled?.should be_true
114
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_truthy
115
115
  MongoMapper::Plugins::IdentityMap.without do
116
- MongoMapper::Plugins::IdentityMap.enabled?.should be_false
116
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_falsey
117
117
  end
118
- MongoMapper::Plugins::IdentityMap.enabled?.should be_true
118
+ MongoMapper::Plugins::IdentityMap.enabled?.should be_truthy
119
119
  end
120
120
  end
121
121
 
@@ -126,14 +126,14 @@ describe "IdentityMap" do
126
126
  it "should add key to map when saved" do
127
127
  person = @person_class.new
128
128
  assert_not_in_map(person)
129
- person.save.should be_true
129
+ person.save.should be_truthy
130
130
  assert_in_map(person)
131
131
  end
132
132
 
133
133
  it "should allow saving with options" do
134
134
  person = @person_class.new
135
135
  assert_not_in_map(person)
136
- person.save(:validate => false).should be_true
136
+ person.save(:validate => false).should be_truthy
137
137
  assert_in_map(person)
138
138
  end
139
139
 
@@ -178,6 +178,19 @@ describe "IdentityMap" do
178
178
  second_load = @person_class.load('_id' => @id, 'name' => 'Frank')
179
179
  first_load.should equal(second_load)
180
180
  end
181
+
182
+ it "should allow passing with_cast" do
183
+ person_with_time_class = Doc('PersonWithTime') do
184
+ key :name, String
185
+ key :created_at, Time
186
+ end
187
+
188
+ lambda do
189
+ loaded = person_with_time_class.load({'_id' => @id, 'name' => 'Frank', 'created_at' => '2014-12-07T20:36:45.529-08:00'}, true)
190
+ loaded.should be_present
191
+ loaded.created_at.should be_an_instance_of(Time)
192
+ end.should_not raise_error
193
+ end
181
194
  end
182
195
 
183
196
  context "#find (with one id)" do
@@ -407,7 +420,7 @@ describe "IdentityMap" do
407
420
  belongs_to :parent, :class_name => 'Item'
408
421
  one :blog, :class_name => 'Blog', :foreign_key => 'parent_id'
409
422
  end
410
- Item.collection.remove
423
+ Item.collection.drop
411
424
 
412
425
  class ::Blog < ::Item; end
413
426
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe "Indexing" do
4
4
  before do
5
5
  @document = Doc do
6
- key :first_name, String
6
+ key :first_name, String, :alias => :fn
7
7
  key :last_name, String
8
8
  key :age, Integer
9
9
  key :date, Date
@@ -11,38 +11,63 @@ describe "Indexing" do
11
11
  end
12
12
  after { drop_indexes(@document) }
13
13
 
14
- [:create_index, :ensure_index, :drop_index, :drop_indexes].each do |method|
15
- it "should delegate #{method} to collection" do
16
- @document.stub(:collection).and_return(double(:name => :foo))
17
- @document.collection.should_receive(method).with(:arg)
18
- @document.send(method, :arg)
14
+ context "against a known collection" do
15
+ before do
16
+ @document.stub(:collection).and_return(double(:name => :foo, :indexes => double()))
17
+ 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)
22
+ end
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
28
+ it "should delegate drop_index to collection" do
29
+ @document.collection.indexes.should_receive(:drop_one).with(:arg)
30
+ @document.drop_index(:arg)
31
+ end
32
+
33
+ it "should delegate drop_indexes to collection" do
34
+ @document.collection.indexes.should_receive(:drop_all)
35
+ @document.drop_indexes
19
36
  end
20
37
  end
21
38
 
22
- it "should allow creating index for a key" do
39
+ it "should allow creating index for an aliased key" do
23
40
  @document.ensure_index :first_name
24
- @document.should have_index('first_name_1')
41
+ @document.should have_index('fn_1')
42
+ end
43
+
44
+ it "should allow creating index for an aliased key without using the alias" do
45
+ @document.ensure_index :fn
46
+ @document.should have_index('fn_1')
47
+ end
48
+
49
+ it "should allow creating index for an unaliased key" do
50
+ @document.ensure_index :last_name
51
+ @document.should have_index('last_name_1')
52
+ end
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')
25
57
  end
26
58
 
27
59
  it "should allow creating unique index for a key" do
28
60
  @document.ensure_index :first_name, :unique => true
29
- @document.should have_index('first_name_1')
61
+ @document.should have_index('fn_1')
30
62
  end
31
63
 
32
64
  it "should allow creating index on multiple keys" do
33
65
  @document.ensure_index [[:first_name, 1], [:last_name, -1]]
34
-
35
- # order is different for different versions of ruby so instead of
36
- # just checking have_index('first_name_1_last_name_-1') I'm checking
37
- # the values of the indexes to make sure the index creation was successful
38
- @document.collection.index_information.detect do |index|
39
- keys = index[0]
40
- keys.include?('first_name_1') && keys.include?('last_name_-1')
41
- end.should_not be_nil
66
+ @document.should have_index('fn_1_last_name_-1')
42
67
  end
43
68
 
44
69
  it "should work with :index shortcut when defining key" do
45
- silence_stderr { @document.key :father, String, :index => true }
70
+ suppress_stderr { @document.key :father, String, :index => true }
46
71
  @document.should have_index('father_1')
47
72
  end
48
- end
73
+ end
@@ -24,6 +24,41 @@ describe "Keys" do
24
24
  instance.get_foo.should == instance.foo
25
25
  end
26
26
 
27
+ it "should return the value when set using send with the writer method" do
28
+ doc = Doc do
29
+ key :foo, String
30
+ end
31
+
32
+ instance = doc.new(:foo => 'bar')
33
+ instance.send("foo=", 'baz').should == 'baz'
34
+ instance.foo.should == 'baz'
35
+ end
36
+
37
+ context "when persisting an typecasted array" do
38
+ TypecastedKeyModel = Doc do
39
+ key :people, Array, :typecast => "Person"
40
+ end
41
+
42
+ Person = Struct.new(:name) do
43
+ def self.to_mongo(value)
44
+ value.name
45
+ end
46
+
47
+ def self.from_mongo(value)
48
+ Person.new value
49
+ end
50
+ end
51
+
52
+ it "should not mutate the model's state" do
53
+ person = Person.new "Bob"
54
+ doc = TypecastedKeyModel.new(:people => [person])
55
+
56
+ doc.save
57
+
58
+ doc.people.should == [person]
59
+ end
60
+ end
61
+
27
62
  it "should not bomb if a key is written before Keys#initialize gets to get called" do
28
63
  doc = Class.new do
29
64
  include MongoMapper::Document
@@ -35,7 +70,7 @@ describe "Keys" do
35
70
  end
36
71
  end
37
72
 
38
- expect { doc.new }.to_not raise_error
73
+ lambda { doc.new }.should_not raise_error
39
74
  end
40
75
 
41
76
  it "should not bomb if a key is read before Keys#initialize gets to get called" do
@@ -49,7 +84,7 @@ describe "Keys" do
49
84
  end
50
85
  end
51
86
 
52
- expect { doc.new }.to_not raise_error
87
+ lambda { doc.new }.should_not raise_error
53
88
  end
54
89
 
55
90
  it "should permit for key overrides" do
@@ -58,7 +93,7 @@ describe "Keys" do
58
93
  key :class, String, :accessors => :skip
59
94
  end
60
95
 
61
- doc.collection.insert('class' => 'String')
96
+ doc.collection.insert_one('class' => 'String')
62
97
  doc.all.first.tap do |d|
63
98
  d.class.should == doc
64
99
  d["class"].should == "String"
@@ -74,7 +109,7 @@ describe "Keys" do
74
109
  }
75
110
 
76
111
  before do
77
- doc.collection.insert(:dynamic => "foo")
112
+ doc.collection.insert_one(:dynamic => "foo")
78
113
  doc.first
79
114
  end
80
115
 
@@ -106,7 +141,7 @@ describe "Keys" do
106
141
  doc.class_eval do
107
142
  key :NotConstant
108
143
  end
109
- doc.collection.insert("NotConstant" => "Just data!")
144
+ doc.collection.insert_one("NotConstant" => "Just data!")
110
145
  doc.first.notConstant.should == "Just data!"
111
146
  end
112
147
 
@@ -116,7 +151,16 @@ describe "Keys" do
116
151
  doc.class_eval do
117
152
  key :"bad-name", :__dynamic => true
118
153
  end
119
- expect { doc.new.method(:"bad-name") }.to raise_error(NameError)
154
+ lambda { doc.new.method(:"bad-name") }.should raise_error(NameError)
155
+ end
156
+
157
+ it "should not create accessors for reserved keys" do
158
+ doc = Doc {}
159
+ doc.should_not_receive(:create_accessors_for)
160
+ doc.class_eval do
161
+ key :"class", :__dynamic => true
162
+ end
163
+ doc.new.class.should == doc
120
164
  end
121
165
 
122
166
  it "should create accessors for good keys" do
@@ -124,13 +168,13 @@ describe "Keys" do
124
168
  key :good_name
125
169
  }
126
170
  doc.new.good_name.should be_nil
127
- expect { doc.new.method("good_name") }.to_not raise_error
171
+ lambda { doc.new.method("good_name") }.should_not raise_error
128
172
  end
129
173
  end
130
174
 
131
175
  it "should handle loading dynamic fields from the database that have bad names" do
132
176
  doc = Doc {}
133
- doc.collection.insert("foo-bar" => "baz-bin")
177
+ doc.collection.insert_one("foo-bar" => "baz-bin")
134
178
 
135
179
  doc.first["foo-bar"].should == "baz-bin"
136
180
  end
@@ -151,7 +195,7 @@ describe "Keys" do
151
195
  end
152
196
 
153
197
  it "should serialize with aliased keys" do
154
- AliasedKeyModel.collection.find_one.keys.should =~ %w(_id f bar)
198
+ AliasedKeyModel.collection.find.first.keys.should =~ %w(_id f bar)
155
199
 
156
200
  AliasedKeyModel.first.tap do |d|
157
201
  d.foo.should == "whee!"
@@ -159,8 +203,35 @@ describe "Keys" do
159
203
  end
160
204
  end
161
205
 
162
- it "should permit querying via aliases" do
163
- AliasedKeyModel.where(AliasedKeyModel.abbr(:f) => "whee!").first.foo.should == "whee!"
206
+ it "should permit querying via direct field names" do
207
+ AliasedKeyModel.where(AliasedKeyModel.abbr(:foo) => "whee!").first.foo.should == "whee!"
208
+ end
209
+
210
+ it "should permit querying via direct field names" do
211
+ AliasedKeyModel.where(:foo => "whee!").criteria_hash.keys.should == ["f"]
212
+ AliasedKeyModel.where(:foo => "whee!").first.foo.should == "whee!"
213
+ end
214
+
215
+ it "should permit filtering via aliases" do
216
+ AliasedKeyModel.where(:foo => "whee!").fields(:foo).first.foo.should == "whee!"
217
+ end
218
+
219
+ it "should permit dealiasing of atomic operations" do
220
+ m = AliasedKeyModel.first
221
+ m.set(:foo => 1)
222
+ AliasedKeyModel.collection.find.first["f"].should == 1
223
+ AliasedKeyModel.collection.find.first["foo"].should be_nil
224
+ end
225
+
226
+ it "should permit dealiasing of update operations" do
227
+ m = AliasedKeyModel.first
228
+ m.update_attributes(:foo => 1)
229
+ AliasedKeyModel.collection.find.first["f"].should == 1
230
+ AliasedKeyModel.collection.find.first["foo"].should be_nil
231
+ end
232
+
233
+ it "should not break when unaliasing non-keys" do
234
+ AliasedKeyModel.where(:badkey => "whee!").criteria_hash.keys.should == [:badkey]
164
235
  end
165
236
 
166
237
  it "should serialize to JSON with full keys" do
@@ -175,7 +246,7 @@ describe "Keys" do
175
246
  before { AliasedKeyModel.create(:with_underscores => "foobar") }
176
247
  it "should work" do
177
248
  AliasedKeyModel.first.with_underscores.should == "foobar"
178
- AliasedKeyModel.collection.find_one["with-hyphens"].should == "foobar"
249
+ AliasedKeyModel.collection.find.first["with-hyphens"].should == "foobar"
179
250
  end
180
251
  end
181
252
 
@@ -183,7 +254,7 @@ describe "Keys" do
183
254
  before { AliasedKeyModel.create(:field_name => "foobar") }
184
255
  it "should work" do
185
256
  AliasedKeyModel.first.field_name.should == "foobar"
186
- AliasedKeyModel.collection.find_one["alternate_field_name"].should == "foobar"
257
+ AliasedKeyModel.collection.find.first["alternate_field_name"].should == "foobar"
187
258
  end
188
259
  end
189
260
 
@@ -220,7 +291,7 @@ describe "Keys" do
220
291
  owner.reload
221
292
  owner.associated_documents.to_a.should =~ associated_documents.to_a
222
293
 
223
- AssociatedKeyWithAlias.collection.find_one.keys.should =~ %w(_id n aid)
294
+ AssociatedKeyWithAlias.collection.find.first.keys.should =~ %w(_id n aid)
224
295
  end
225
296
 
226
297
  it "should work with embedded documents" do
@@ -230,8 +301,39 @@ describe "Keys" do
230
301
 
231
302
  owner.reload
232
303
  owner.other_documents[0].embedded_name.should == "Underling"
233
- owner.collection.find_one["other_documents"][0]["en"].should == "Underling"
304
+ owner.collection.find.first["other_documents"][0]["en"].should == "Underling"
234
305
  end
235
306
  end
236
307
  end
308
+
309
+ describe "removing keys" do
310
+ DocWithRemovedKey = Doc do
311
+ key :something
312
+ validates_uniqueness_of :something
313
+ remove_key :something
314
+ end
315
+
316
+ it 'should remove the key' do
317
+ DocWithRemovedKey.keys.should_not have_key "_something"
318
+ end
319
+
320
+ it 'should remove validations' do
321
+ DocWithRemovedKey._validate_callbacks.should be_empty
322
+ end
323
+ end
324
+
325
+ describe "removing keys in the presence of a validation method" do
326
+ DocWithRemovedValidator = Doc do
327
+ key :something
328
+ validate :something_valid?
329
+ remove_key :something
330
+
331
+ def something_valid?; true; end
332
+ end
333
+
334
+ it 'should remove the key' do
335
+ DocWithRemovedKey.keys.should_not have_key "_something"
336
+ end
337
+
338
+ end
237
339
  end