mongo_mapper 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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