mongo_mapper 0.9.2 → 0.10.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 (40) hide show
  1. data/UPGRADES +6 -0
  2. data/lib/mongo_mapper.rb +1 -2
  3. data/lib/mongo_mapper/document.rb +0 -1
  4. data/lib/mongo_mapper/embedded_document.rb +0 -1
  5. data/lib/mongo_mapper/extensions/float.rb +1 -1
  6. data/lib/mongo_mapper/plugins.rb +2 -8
  7. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +2 -0
  8. data/lib/mongo_mapper/plugins/associations/many_association.rb +4 -4
  9. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +9 -1
  10. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
  11. data/lib/mongo_mapper/plugins/associations/one_association.rb +29 -1
  12. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +0 -1
  13. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +43 -16
  14. data/lib/mongo_mapper/plugins/clone.rb +1 -1
  15. data/lib/mongo_mapper/plugins/dirty.rb +6 -15
  16. data/lib/mongo_mapper/plugins/document.rb +5 -5
  17. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +3 -3
  18. data/lib/mongo_mapper/plugins/keys.rb +0 -19
  19. data/lib/mongo_mapper/plugins/keys/key.rb +0 -4
  20. data/lib/mongo_mapper/railtie.rb +1 -2
  21. data/lib/mongo_mapper/version.rb +1 -1
  22. data/test/functional/associations/test_belongs_to_proxy.rb +15 -0
  23. data/test/functional/associations/test_many_documents_proxy.rb +161 -0
  24. data/test/functional/associations/test_one_as_proxy.rb +485 -0
  25. data/test/functional/associations/test_one_proxy.rb +188 -27
  26. data/test/functional/test_dirty.rb +9 -0
  27. data/test/functional/test_document.rb +5 -0
  28. data/test/support/railtie.rb +4 -0
  29. data/test/support/railtie/autoloaded.rb +2 -0
  30. data/test/support/railtie/not_autoloaded.rb +3 -0
  31. data/test/support/railtie/parent.rb +3 -0
  32. data/test/unit/associations/test_one_association.rb +18 -0
  33. data/test/unit/test_extensions.rb +4 -0
  34. data/test/unit/test_keys.rb +0 -22
  35. data/test/unit/test_plugins.rb +1 -46
  36. data/test/unit/test_railtie.rb +61 -0
  37. metadata +18 -14
  38. data/lib/mongo_mapper/support/descendant_appends.rb +0 -45
  39. data/test/functional/test_string_id_compatibility.rb +0 -75
  40. data/test/unit/test_descendant_appends.rb +0 -63
@@ -85,6 +85,122 @@ class OneProxyTest < Test::Unit::TestCase
85
85
  post.author.name.should == 'Emily'
86
86
  end
87
87
  end
88
+
89
+ context "with :dependent" do
90
+ context "=> delete" do
91
+ setup do
92
+ @post_class.one :author, :class => @author_class, :dependent => :delete
93
+
94
+ @post = @post_class.create
95
+ @author = @author_class.new
96
+ @post.author = @author
97
+ end
98
+
99
+ should "call delete on the existing document" do
100
+ @author_class.any_instance.expects(:delete).once
101
+ @post.author = @author_class.new
102
+ end
103
+
104
+ should "remove the existing document from the database" do
105
+ @post.author = @author_class.new
106
+ lambda { @author.reload }.should raise_error(MongoMapper::DocumentNotFound)
107
+ end
108
+
109
+ should "do nothing if it's the same document" do
110
+ @author_class.any_instance.expects(:delete).never
111
+ @post.author = @author
112
+ end
113
+ end
114
+
115
+ context "=> destory" do
116
+ setup do
117
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
118
+
119
+ @post = @post_class.create
120
+ @author = @author_class.new
121
+ @post.author = @author
122
+ end
123
+
124
+ should "call destroy the existing document" do
125
+ @author_class.any_instance.expects(:destroy).once
126
+ @post.author = @author_class.new
127
+ end
128
+
129
+ should "remove the existing document from the database" do
130
+ @post.author = @author_class.new
131
+ lambda { @author.reload }.should raise_error(MongoMapper::DocumentNotFound)
132
+ end
133
+
134
+ should "do nothing if it's the same document" do
135
+ @author_class.any_instance.expects(:destroy).never
136
+ @post.author = @author
137
+ end
138
+ end
139
+
140
+ context "=> nullify" do
141
+ setup do
142
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
143
+
144
+ @post = @post_class.create
145
+ @author = @author_class.new
146
+ @post.author = @author
147
+ end
148
+
149
+ should "nullify the existing document" do
150
+ @author.reload
151
+ @author.post_id.should == @post.id
152
+
153
+ @post.author = @author_class.new
154
+
155
+ @author.reload
156
+ @author.post_id.should be_nil
157
+ end
158
+
159
+ should "work when it's the same document" do
160
+ old_author = @post.author
161
+ @post.author = @author
162
+ old_author.should == @post.author
163
+ end
164
+ end
165
+
166
+ context "unspecified" do
167
+ should "nullify the existing document" do
168
+ @post_class.one :author, :class => @author_class
169
+
170
+ post = @post_class.create
171
+ author = @author_class.new
172
+ post.author = author
173
+ author.reload
174
+ author.post_id.should == post.id
175
+
176
+ post.author = @author_class.new
177
+
178
+ author.reload
179
+ author.post_id.should be_nil
180
+ end
181
+ end
182
+ end
183
+
184
+ context "with nil" do
185
+ setup do
186
+ @post_class.one :author, :class => @author_class
187
+
188
+ @post = @post_class.new
189
+ @author = @author_class.new(:name => 'Frank')
190
+ @post.author = @author
191
+ end
192
+
193
+ should "nullify the existing document" do
194
+ @post.author = nil
195
+ @author.reload
196
+ @author.post_id.should be_nil
197
+ end
198
+
199
+ should "set the target to nil" do
200
+ @post.author = nil
201
+ @post.author.should == nil
202
+ end
203
+ end
88
204
  end
89
205
 
90
206
  should "have boolean method for testing presence" do
@@ -118,44 +234,89 @@ class OneProxyTest < Test::Unit::TestCase
118
234
  post.author = nil
119
235
  post.author.nil?.should be_true
120
236
  end
237
+
238
+ context "destroying parent with :dependent" do
239
+ context "=> destroy" do
240
+ setup do
241
+ @post_class.one :author, :class => @author_class, :dependent => :destroy
242
+
243
+ @post = @post_class.create
244
+ @author = @author_class.new
245
+ @post.author = @author
246
+ end
121
247
 
122
- should "work with :dependent delete" do
123
- @post_class.one :author, :class => @author_class, :dependent => :delete
248
+ should "should call destroy on the associated documents" do
249
+ @author_class.any_instance.expects(:destroy).once
250
+ @post.destroy
251
+ end
252
+
253
+ should "should remove the associated documents" do
254
+ @author_class.count.should == 1
255
+ @post.destroy
256
+ @post.author.should == nil
257
+ @author_class.count.should == 0
258
+ end
259
+ end
124
260
 
125
- post = @post_class.create
126
- author = @author_class.new
127
- post.author = author
128
- post.reload
261
+ context "=> delete" do
262
+ setup do
263
+ @post_class.one :author, :class => @author_class, :dependent => :delete
129
264
 
130
- @author_class.any_instance.expects(:delete).once
131
- post.author = @author_class.new
132
- end
265
+ @post = @post_class.create
266
+ @author = @author_class.new
267
+ @post.author = @author
268
+ end
133
269
 
134
- should "work with :dependent destroy" do
135
- @post_class.one :author, :class => @author_class, :dependent => :destroy
270
+ should "should call delete the associated documents" do
271
+ @author_class.any_instance.expects(:delete).once
272
+ @post.destroy
273
+ end
136
274
 
137
- post = @post_class.create
138
- author = @author_class.new
139
- post.author = author
140
- post.reload
275
+ should "remove the associated documents" do
276
+ @author_class.count.should == 1
277
+ @post.destroy
278
+ @post.author.should == nil
279
+ @author_class.count.should == 0
280
+ end
281
+ end
141
282
 
142
- @author_class.any_instance.expects(:destroy).once
143
- post.author = @author_class.new
144
- end
283
+ context "=> nullify" do
284
+ should "should nullify the relationship but not destroy the associated document" do
285
+ @post_class.one :author, :class => @author_class, :dependent => :nullify
145
286
 
146
- should "work with :dependent nullify" do
147
- @post_class.one :author, :class => @author_class, :dependent => :nullify
287
+ post = @post_class.create
288
+ author = @author_class.new
289
+ post.author = author
148
290
 
149
- post = @post_class.create
150
- author = @author_class.new
151
- post.author = author
152
- post.reload
291
+ @author_class.count.should == 1
292
+ post.destroy
293
+ post.author.should == nil
294
+ @author_class.count.should == 1
153
295
 
154
- post.author = @author_class.new
296
+ @author_class.first.should == author
297
+ author.post_id.should == nil
298
+ end
299
+ end
300
+
301
+ context "unspecified" do
302
+ should "should nullify the relationship but not destroy the associated document" do
303
+ @post_class.one :author, :class => @author_class
155
304
 
156
- author.reload
157
- author.post_id.should be_nil
305
+ post = @post_class.create
306
+ author = @author_class.new
307
+ post.author = author
308
+
309
+ @author_class.count.should == 1
310
+ post.destroy
311
+ post.author.should == nil
312
+ @author_class.count.should == 1
313
+
314
+ @author_class.first.should == author
315
+ author.post_id.should == nil
316
+ end
317
+ end
158
318
  end
319
+
159
320
 
160
321
  should "be able to build" do
161
322
  @post_class.one :author, :class => @author_class
@@ -106,6 +106,15 @@ class DirtyTest < Test::Unit::TestCase
106
106
  doc = @document.new
107
107
  doc.value_changed?.should be_false
108
108
  end
109
+
110
+ should "be false if the same ObjectId was assigned in String format" do
111
+ @document.key :doc_id, ObjectId
112
+
113
+ doc = @document.create!(:doc_id => BSON::ObjectId.new)
114
+ doc.changed?.should be_false
115
+ doc.doc_id = doc.doc_id.to_s
116
+ doc.changed?.should be_false
117
+ end
109
118
  end
110
119
 
111
120
  context "changes" do
@@ -245,6 +245,11 @@ class DocumentTest < Test::Unit::TestCase
245
245
  @instance.destroy
246
246
  assert_raises(MongoMapper::DocumentNotFound) { @instance.reload }
247
247
  end
248
+
249
+ should "clear keys that were removed from the database" do
250
+ @instance.unset(:age)
251
+ @instance.reload.age.should be_nil
252
+ end
248
253
  end
249
254
 
250
255
  context "database has keys not defined in model" do
@@ -0,0 +1,4 @@
1
+ module Railtie
2
+ # We could get AS::Dependencies to autocreate this module
3
+ # but let's keep it simple
4
+ end
@@ -0,0 +1,2 @@
1
+ class Railtie::Autoloaded < Railtie::Parent
2
+ end
@@ -0,0 +1,3 @@
1
+ class Railtie::NotAutoloaded < Railtie::Parent
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Railtie::Parent
2
+ extend ActiveSupport::DescendantsTracker
3
+ end
@@ -15,4 +15,22 @@ class OneAssociationTest < Test::Unit::TestCase
15
15
  base.embeddable?.should be_false
16
16
  end
17
17
  end
18
+
19
+ context "proxy_class" do
20
+ should "be OneProxy for one" do
21
+ base = OneAssociation.new(:status)
22
+ base.proxy_class.should == OneProxy
23
+ end
24
+
25
+ should "be OneAsProxy for one with :as option" do
26
+ base = OneAssociation.new(:message, :as => :messagable)
27
+ base.proxy_class.should == OneAsProxy
28
+ end
29
+
30
+ should "be OneEmbeddedProxy for one embedded" do
31
+ base = OneAssociation.new(:media)
32
+ base.proxy_class.should == OneEmbeddedProxy
33
+ end
34
+ end
35
+
18
36
  end
@@ -137,6 +137,10 @@ class SupportTest < Test::Unit::TestCase
137
137
  should "leave nil values nil" do
138
138
  Float.to_mongo(nil).should == nil
139
139
  end
140
+
141
+ should "leave blank values nil" do
142
+ Float.to_mongo('').should == nil
143
+ end
140
144
  end
141
145
 
142
146
  context "Hash.from_mongo" do
@@ -14,28 +14,6 @@ class KeyTest < Test::Unit::TestCase
14
14
  end
15
15
  end
16
16
 
17
- context ".new with no id and _id of type string" do
18
- should "not error" do
19
- lambda {
20
- klass = Doc() do
21
- key :_id, String
22
- end
23
- silence_stderr { klass.new.id.should_not be_nil }
24
- }.should_not raise_error
25
- end
26
- end
27
-
28
- context ".new with no id and _id of type object id" do
29
- should "not error" do
30
- lambda {
31
- klass = Doc() do
32
- key :_id, ObjectId
33
- end
34
- silence_stderr { klass.new.should_not be_nil }
35
- }.should_not raise_error
36
- end
37
- end
38
-
39
17
  context ".key?(:symbol)" do
40
18
  should "be true if document has key" do
41
19
  Address.key?(:city).should be_true
@@ -5,7 +5,7 @@ class PluginsTest < Test::Unit::TestCase
5
5
  Class.new { extend MongoMapper::Plugins }.plugins.should == []
6
6
  end
7
7
 
8
- context "ActiveSupport::Concern" do
8
+ context "a plugin" do
9
9
  module MyConcern
10
10
  extend ActiveSupport::Concern
11
11
 
@@ -88,49 +88,4 @@ class PluginsTest < Test::Unit::TestCase
88
88
  end
89
89
  end
90
90
  end
91
-
92
- context "deprecated plugin" do
93
- module DeprecatedPlugin
94
- def self.configure(model)
95
- model.class_eval { attr_accessor :from_configure }
96
- end
97
-
98
- module ClassMethods
99
- def class_foo
100
- 'class_foo'
101
- end
102
- end
103
-
104
- module InstanceMethods
105
- def instance_foo
106
- 'instance_foo'
107
- end
108
- end
109
- end
110
-
111
- setup do
112
- silence_stderr do
113
- @document = Class.new do
114
- extend MongoMapper::Plugins
115
- plugin DeprecatedPlugin
116
- end
117
- end
118
- end
119
-
120
- should "include instance methods" do
121
- @document.new.instance_foo.should == 'instance_foo'
122
- end
123
-
124
- should "extend class methods" do
125
- @document.class_foo.should == 'class_foo'
126
- end
127
-
128
- should "pass model to configure" do
129
- @document.new.should respond_to(:from_configure)
130
- end
131
-
132
- should "add plugin to plugins" do
133
- @document.plugins.should include(DeprecatedPlugin)
134
- end
135
- end
136
91
  end
@@ -0,0 +1,61 @@
1
+ require 'test_helper'
2
+ require "rails"
3
+ require 'mongo_mapper/railtie'
4
+
5
+ class TestRailtie < Test::Unit::TestCase
6
+
7
+ def expect_descendants(expectation)
8
+ # Keep expectation a string so we don't accidentally load in a class
9
+ Railtie::Parent.descendants.map(&:to_s).sort.should == expectation.sort
10
+ end
11
+
12
+ def run_initializer(mod, name)
13
+ initializer = mod.initializers.detect do |i|
14
+ i.name == name
15
+ end
16
+ initializer.block.arity == -1 ? initializer.run : initializer.run(FakeRails)
17
+ # mongo_mapper.prepare_dispatcher takes a Rails app as its one arg,
18
+ # set_clear_dependencies_hook takes no args
19
+ end
20
+
21
+ def load_autoloaded_class
22
+ Railtie::Autoloaded.presence
23
+ end
24
+
25
+ class FakeRails
26
+ def self.config
27
+ return Class.new { def cache_classes ; false ; end }.new
28
+ end
29
+ end
30
+
31
+ context "Railtie" do
32
+ include Rails::Application::Bootstrap
33
+
34
+ setup do
35
+ require 'support/railtie'
36
+ require 'support/railtie/parent'
37
+ require 'support/railtie/not_autoloaded'
38
+
39
+ ActiveSupport::Dependencies.autoload_paths << File.join(File.dirname(__FILE__), '..', 'support')
40
+
41
+ # These initializers don't actually run anything, they just register cleanup and prepare hooks
42
+ run_initializer Rails::Application::Bootstrap, :set_clear_dependencies_hook
43
+ run_initializer MongoMapper::Railtie, 'mongo_mapper.prepare_dispatcher'
44
+ end
45
+
46
+ should "not clear ActiveSupport::DescendantsTracker" do
47
+ expect_descendants %w( Railtie::NotAutoloaded )
48
+ load_autoloaded_class
49
+ expect_descendants %w( Railtie::NotAutoloaded Railtie::Autoloaded )
50
+
51
+ ActionDispatch::Reloader.cleanup! # cleanup 'last request'
52
+
53
+ expect_descendants %w( Railtie::NotAutoloaded )
54
+ load_autoloaded_class
55
+ expect_descendants %w( Railtie::NotAutoloaded Railtie::Autoloaded )
56
+
57
+ ActionDispatch::Reloader.prepare! # prepare 'next request'
58
+ expect_descendants %w( Railtie::NotAutoloaded Railtie::Autoloaded )
59
+ end
60
+ end
61
+ end