mongo_mapper 0.13.0.beta2 → 0.15.0

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.
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