mongo_mapper-unstable 2010.1.18 → 2010.1.19

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2010.01.18
1
+ 2010.01.19
@@ -22,6 +22,7 @@ module MongoMapper
22
22
  plugin Plugins::Serialization
23
23
  plugin Plugins::Validations
24
24
  plugin Plugins::Callbacks # for now callbacks needs to be after validations
25
+ plugin Plugins::IdentityMap
25
26
 
26
27
  extend Plugins::Validations::DocumentMacros
27
28
  end
@@ -45,29 +46,28 @@ module MongoMapper
45
46
  MongoMapper.ensure_index(self, keys_to_index, options)
46
47
  end
47
48
 
48
- def find!(*args)
49
+ def find(*args)
50
+ find_all_first_last_error(args)
49
51
  options = args.extract_options!
50
- case args.first
51
- when :first then first(options)
52
- when :last then last(options)
53
- when :all then find_every(options)
54
- when Array then find_some(args, options)
55
- else
56
- case args.size
57
- when 0
58
- raise DocumentNotFound, "Couldn't find without an ID"
59
- when 1
60
- find_one!(options.merge({:_id => args[0]}))
61
- else
62
- find_some(args, options)
63
- end
52
+ return nil if args.size == 0
53
+
54
+ if args.first.is_a?(Array) || args.size > 1
55
+ find_some(args, options)
56
+ else
57
+ find_one(options.merge({:_id => args[0]}))
64
58
  end
65
59
  end
66
-
67
- def find(*args)
68
- find!(*args)
69
- rescue DocumentNotFound
70
- nil
60
+
61
+ def find!(*args)
62
+ find_all_first_last_error(args)
63
+ options = args.extract_options!
64
+ raise DocumentNotFound, "Couldn't find without an ID" if args.size == 0
65
+
66
+ if args.first.is_a?(Array) || args.size > 1
67
+ find_some!(args, options)
68
+ else
69
+ find_one(options.merge({:_id => args[0]})) || raise(DocumentNotFound, "Document match #{options.inspect} does not exist in #{collection.name} collection")
70
+ end
71
71
  end
72
72
 
73
73
  def first(options={})
@@ -80,7 +80,7 @@ module MongoMapper
80
80
  end
81
81
 
82
82
  def all(options={})
83
- find_every(options)
83
+ find_many(options)
84
84
  end
85
85
 
86
86
  def find_by_id(id)
@@ -121,7 +121,7 @@ module MongoMapper
121
121
  end
122
122
 
123
123
  def destroy(*ids)
124
- find_some(ids.flatten).each(&:destroy)
124
+ find_some!(ids.flatten).each(&:destroy)
125
125
  end
126
126
 
127
127
  def destroy_all(options={})
@@ -168,20 +168,6 @@ module MongoMapper
168
168
  def pop(*args)
169
169
  modifier_update('$pop', args)
170
170
  end
171
-
172
- def modifier_update(modifier, args)
173
- criteria, keys = criteria_and_keys_from_args(args)
174
- modifiers = {modifier => keys}
175
- collection.update(criteria, modifiers, :multi => true)
176
- end
177
- private :modifier_update
178
-
179
- def criteria_and_keys_from_args(args)
180
- keys = args.pop
181
- criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
182
- [to_criteria(criteria), keys]
183
- end
184
- private :criteria_and_keys_from_args
185
171
 
186
172
  def embeddable?
187
173
  false
@@ -257,17 +243,33 @@ module MongoMapper
257
243
  instances.size == 1 ? instances[0] : instances
258
244
  end
259
245
 
260
- def find_every(options)
261
- criteria, options = to_finder_options(options)
262
- collection.find(criteria, options).to_a.map do |doc|
263
- load(doc)
246
+ def modifier_update(modifier, args)
247
+ criteria, keys = criteria_and_keys_from_args(args)
248
+ modifiers = {modifier => keys}
249
+ collection.update(criteria, modifiers, :multi => true)
250
+ end
251
+
252
+ def criteria_and_keys_from_args(args)
253
+ keys = args.pop
254
+ criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
255
+ [to_criteria(criteria), keys]
256
+ end
257
+
258
+ def find_all_first_last_error(args)
259
+ if args[0] == :first || args[0] == :last || args[0] == :all
260
+ raise ArgumentError, "#{self}.find(:#{args}) is no longer supported, use #{self}.#{args} instead."
264
261
  end
265
262
  end
266
263
 
267
264
  def find_some(ids, options={})
268
- ids = ids.flatten.compact.uniq
269
- documents = find_every(options.merge(:_id => ids))
270
-
265
+ ids = ids.flatten.compact.uniq
266
+ find_many(options.merge(:_id => ids)).compact
267
+ end
268
+
269
+ def find_some!(ids, options={})
270
+ ids = ids.flatten.compact.uniq
271
+ documents = find_some(ids, options)
272
+
271
273
  if ids.size == documents.size
272
274
  documents
273
275
  else
@@ -282,8 +284,11 @@ module MongoMapper
282
284
  end
283
285
  end
284
286
 
285
- def find_one!(options={})
286
- find_one(options) || raise(DocumentNotFound, "Document match #{options.inspect} does not exist in #{collection.name} collection")
287
+ def find_many(options)
288
+ criteria, options = to_finder_options(options)
289
+ collection.find(criteria, options).to_a.map do |doc|
290
+ load(doc)
291
+ end
287
292
  end
288
293
 
289
294
  def invert_order_clause(order)
@@ -365,10 +370,13 @@ module MongoMapper
365
370
  end
366
371
 
367
372
  def reload
368
- doc = self.class.find(_id)
369
- self.class.associations.each { |name, assoc| send(name).reset if respond_to?(name) }
370
- self.attributes = doc.attributes
371
- self
373
+ if attrs = collection.find_one({:_id => _id})
374
+ self.class.associations.each { |name, assoc| send(name).reset if respond_to?(name) }
375
+ self.attributes = attrs
376
+ self
377
+ else
378
+ raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
379
+ end
372
380
  end
373
381
 
374
382
  private
@@ -9,7 +9,7 @@ module MongoMapper
9
9
 
10
10
  options = args.extract_options!.merge(attributes)
11
11
 
12
- if result = find(finder.finder, options)
12
+ if result = send(finder.finder, options)
13
13
  result
14
14
  else
15
15
  if finder.raise?
@@ -2,6 +2,8 @@ module MongoMapper
2
2
  module Plugins
3
3
  module Associations
4
4
  class BelongsToPolymorphicProxy < Proxy
5
+ undef_method :object_id
6
+
5
7
  def replace(doc)
6
8
  if doc
7
9
  doc.save if doc.new?
@@ -16,7 +18,7 @@ module MongoMapper
16
18
  protected
17
19
  def find_target
18
20
  return nil if association_class.nil? || owner[reflection.foreign_key].nil?
19
- association_class.first(:id => owner[reflection.foreign_key])
21
+ association_class.find_by_id(owner[reflection.foreign_key])
20
22
  end
21
23
 
22
24
  def association_class
@@ -2,6 +2,8 @@ module MongoMapper
2
2
  module Plugins
3
3
  module Associations
4
4
  class BelongsToProxy < Proxy
5
+ undef_method :object_id
6
+
5
7
  def replace(doc)
6
8
  if doc
7
9
  doc.save if doc.new?
@@ -15,7 +17,7 @@ module MongoMapper
15
17
  protected
16
18
  def find_target
17
19
  return nil if owner[reflection.foreign_key].nil?
18
- klass.first(:id => owner[reflection.foreign_key])
20
+ klass.find_by_id(owner[reflection.foreign_key])
19
21
  end
20
22
  end
21
23
  end
@@ -2,6 +2,8 @@ module MongoMapper
2
2
  module Plugins
3
3
  module Associations
4
4
  class OneProxy < Proxy
5
+ undef_method :object_id
6
+
5
7
  def build(attrs={})
6
8
  instantiate_target(:new, attrs)
7
9
  end
@@ -38,9 +38,9 @@ module MongoMapper
38
38
  changed.inject({}) { |h, key| h[key] = key_change(key); h }
39
39
  end
40
40
 
41
- def initialize(attrs={})
41
+ def initialize(*args)
42
42
  super
43
- changed_keys.clear if attrs.blank?
43
+ changed_keys.clear if args.first.blank? || !new?
44
44
  end
45
45
 
46
46
  def save(*args)
@@ -1,36 +1,41 @@
1
1
  module MongoMapper
2
2
  module Plugins
3
3
  module IdentityMap
4
+ def self.identity_map
5
+ Thread.current[:mongo_mapper_identity_map] ||= {}
6
+ end
7
+
8
+ def self.identity_map=(v)
9
+ Thread.current[:mongo_mapper_identity_map] = v
10
+ end
11
+
4
12
  module ClassMethods
5
13
  def identity_map
6
- Thread.current[:mongo_mapper_identity_map] ||= {}
14
+ IdentityMap.identity_map
7
15
  end
8
16
 
9
17
  def identity_map=(v)
10
- Thread.current[:mongo_mapper_identity_map] = v
18
+ IdentityMap.identity_map = v
11
19
  end
12
20
 
13
21
  def identity_map_key(id)
14
- "#{self}:#{id}"
22
+ "#{collection.name}:#{id}"
15
23
  end
16
24
 
17
25
  def find_one(options={})
18
- criteria, options = to_finder_options(options)
26
+ criteria, finder_options = to_finder_options(options)
19
27
  key = identity_map_key(criteria[:_id])
20
-
21
- if document = identity_map[key]
28
+ if criteria.keys == [:_id] && document = identity_map[key]
22
29
  document
23
30
  else
24
31
  document = super
25
32
  end
26
-
33
+
27
34
  document
28
35
  end
29
36
 
30
37
  def load(attrs)
31
- id = attrs[:_id] || attrs[:id] || attrs['_id'] || attrs['id']
32
- key = identity_map_key(id)
33
-
38
+ key = identity_map_key(attrs['_id'])
34
39
  unless document = identity_map[key]
35
40
  document = super
36
41
  identity_map[document.identity_map_key] = document
@@ -49,7 +54,7 @@ module MongoMapper
49
54
  self.class.identity_map
50
55
  end
51
56
 
52
- def save
57
+ def save(*args)
53
58
  if result = super
54
59
  identity_map[identity_map_key] = self
55
60
  end
@@ -42,16 +42,13 @@ module MongoMapper
42
42
  value.is_a?(self) ? value : load(value)
43
43
  end
44
44
 
45
+ # load is overridden in identity map to ensure same objects are loaded
45
46
  def load(attrs)
46
47
  begin
47
48
  klass = attrs['_type'].present? ? attrs['_type'].constantize : self
48
- doc = klass.new(attrs)
49
- doc.instance_variable_set("@new", false)
50
- doc
49
+ klass.new(attrs, true)
51
50
  rescue NameError
52
- doc = new(attrs)
53
- doc.instance_variable_set("@new", false)
54
- doc
51
+ new(attrs, true)
55
52
  end
56
53
  end
57
54
 
@@ -140,7 +137,7 @@ module MongoMapper
140
137
  model.key :_id, ObjectId
141
138
  end
142
139
 
143
- def initialize(attrs={})
140
+ def initialize(attrs={}, from_db=false)
144
141
  unless attrs.nil?
145
142
  provided_keys = attrs.keys.map { |k| k.to_s }
146
143
  unless provided_keys.include?('_id') || provided_keys.include?('id')
@@ -148,7 +145,7 @@ module MongoMapper
148
145
  end
149
146
  end
150
147
 
151
- @new = true
148
+ @new = from_db ? false : true
152
149
  self._type = self.class.name if respond_to?(:_type=)
153
150
  self.attributes = attrs
154
151
  end
@@ -13,7 +13,7 @@ module MongoMapper
13
13
  pagination = Pagination::PaginationProxy.new(total_entries, page, per_page)
14
14
 
15
15
  options.merge!(:limit => pagination.limit, :skip => pagination.skip)
16
- pagination.subject = find_every(options)
16
+ pagination.subject = find_many(options)
17
17
  pagination
18
18
  end
19
19
  end
@@ -131,23 +131,6 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
131
131
  @post2.save
132
132
  end
133
133
 
134
- context "with :all" do
135
- should "work" do
136
- @post.comments.find(:all).should include(@comment1)
137
- @post.comments.find(:all).should include(@comment2)
138
- end
139
-
140
- should "work with conditions" do
141
- comments = @post.comments.find(:all, :body => 'comment1')
142
- comments.should == [@comment1]
143
- end
144
-
145
- should "work with order" do
146
- comments = @post.comments.find(:all, :order => 'body desc')
147
- comments.should == [@comment2, @comment1]
148
- end
149
- end
150
-
151
134
  context "with #all" do
152
135
  should "work" do
153
136
  @post.comments.all.should include(@comment1)
@@ -171,9 +154,9 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
171
154
  end
172
155
 
173
156
  should "not work for id not in association" do
174
- lambda {
157
+ assert_raises(MongoMapper::DocumentNotFound) do
175
158
  @post.comments.find!(@comment5._id)
176
- }.should raise_error(MongoMapper::DocumentNotFound)
159
+ end
177
160
  end
178
161
  end
179
162
 
@@ -184,9 +167,9 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
184
167
  end
185
168
 
186
169
  should "not work for ids not in association" do
187
- lambda {
170
+ assert_raises(MongoMapper::DocumentNotFound) do
188
171
  @post.comments.find!(@comment1._id, @comment2._id, @comment4._id)
189
- }.should raise_error(MongoMapper::DocumentNotFound)
172
+ end
190
173
  end
191
174
  end
192
175
 
@@ -242,36 +242,30 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
242
242
 
243
243
  context "all" do
244
244
  should "work" do
245
- @project1.statuses.find(:all, :order => "position asc").should == [@brand_new, @complete]
246
245
  @project1.statuses.all(:order => "position asc").should == [@brand_new, @complete]
247
246
  end
248
247
 
249
248
  should "work with conditions" do
250
- @project1.statuses.find(:all, :name => 'Complete').should == [@complete]
251
249
  @project1.statuses.all(:name => 'Complete').should == [@complete]
252
250
  end
253
251
  end
254
252
 
255
253
  context "first" do
256
254
  should "work" do
257
- @project1.statuses.find(:first, :order => 'name').should == @complete
258
255
  @project1.statuses.first(:order => 'name').should == @complete
259
256
  end
260
257
 
261
258
  should "work with conditions" do
262
- @project1.statuses.find(:first, :name => 'Complete').should == @complete
263
259
  @project1.statuses.first(:name => 'Complete').should == @complete
264
260
  end
265
261
  end
266
262
 
267
263
  context "last" do
268
264
  should "work" do
269
- @project1.statuses.find(:last, :order => "position asc").should == @complete
270
265
  @project1.statuses.last(:order => "position asc").should == @complete
271
266
  end
272
267
 
273
268
  should "work with conditions" do
274
- @project1.statuses.find(:last, :order => 'position', :name => 'New').should == @brand_new
275
269
  @project1.statuses.last(:order => 'position', :name => 'New').should == @brand_new
276
270
  end
277
271
  end
@@ -295,9 +289,9 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
295
289
  end
296
290
 
297
291
  should "not work for ids not in association" do
298
- lambda {
292
+ assert_raises(MongoMapper::DocumentNotFound) do
299
293
  @project1.statuses.find!(@brand_new.id, @complete.id, @archived.id)
300
- }.should raise_error(MongoMapper::DocumentNotFound)
294
+ end
301
295
  end
302
296
  end
303
297
 
@@ -176,22 +176,6 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
176
176
  end
177
177
  end
178
178
 
179
- context "with :all" do
180
- should "work" do
181
- @lounge.messages.find(:all, :order => "position").should == [@lm1, @lm2]
182
- end
183
-
184
- should "work with conditions" do
185
- messages = @lounge.messages.find(:all, :body => 'Loungin!', :order => "position")
186
- messages.should == [@lm1]
187
- end
188
-
189
- should "work with order" do
190
- messages = @lounge.messages.find(:all, :order => 'position desc')
191
- messages.should == [@lm2, @lm1]
192
- end
193
- end
194
-
195
179
  context "with #all" do
196
180
  should "work" do
197
181
  @lounge.messages.all(:order => "position").should == [@lm1, @lm2]
@@ -208,17 +192,6 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
208
192
  end
209
193
  end
210
194
 
211
- context "with :first" do
212
- should "work" do
213
- @lounge.messages.find(:first, :order => "position asc").should == @lm1
214
- end
215
-
216
- should "work with conditions" do
217
- message = @lounge.messages.find(:first, :body => 'I love loungin!', :order => "position asc")
218
- message.should == @lm2
219
- end
220
- end
221
-
222
195
  context "with #first" do
223
196
  should "work" do
224
197
  @lounge.messages.first(:order => "position asc").should == @lm1
@@ -230,17 +203,6 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
230
203
  end
231
204
  end
232
205
 
233
- context "with :last" do
234
- should "work" do
235
- @lounge.messages.find(:last, :order => "position asc").should == @lm2
236
- end
237
-
238
- should "work with conditions" do
239
- message = @lounge.messages.find(:last, :body => 'Loungin!', :order => "position asc")
240
- message.should == @lm1
241
- end
242
- end
243
-
244
206
  context "with #last" do
245
207
  should "work" do
246
208
  @lounge.messages.last(:order => "position asc").should == @lm2
@@ -285,9 +247,9 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
285
247
  end
286
248
 
287
249
  should "not work for ids not in association" do
288
- lambda {
250
+ assert_raises(MongoMapper::DocumentNotFound) do
289
251
  @lounge.messages.find!(@lm1._id, @lm2._id, @hm2._id)
290
- }.should raise_error(MongoMapper::DocumentNotFound)
252
+ end
291
253
  end
292
254
  end
293
255
 
@@ -1,23 +1,17 @@
1
1
  require 'test_helper'
2
- require 'models'
3
2
 
4
3
  class DirtyTest < Test::Unit::TestCase
5
4
  def setup
6
- @document = Doc do
7
- key :phrase, String
8
- end
9
-
10
- Status.collection.remove
11
- Project.collection.remove
5
+ @document = Doc { key :phrase, String }
12
6
  end
13
-
7
+
14
8
  context "marking changes" do
15
9
  should "not happen if there are none" do
16
10
  doc = @document.new
17
11
  doc.phrase_changed?.should be_false
18
12
  doc.phrase_change.should be_nil
19
13
  end
20
-
14
+
21
15
  should "happen when change happens" do
22
16
  doc = @document.new
23
17
  doc.phrase = 'Golly Gee Willikers Batman'
@@ -25,12 +19,12 @@ class DirtyTest < Test::Unit::TestCase
25
19
  doc.phrase_was.should be_nil
26
20
  doc.phrase_change.should == [nil, 'Golly Gee Willikers Batman']
27
21
  end
28
-
22
+
29
23
  should "happen when initializing" do
30
24
  doc = @document.new(:phrase => 'Foo')
31
25
  doc.changed?.should be_true
32
26
  end
33
-
27
+
34
28
  should "clear changes on save" do
35
29
  doc = @document.new
36
30
  doc.phrase = 'Golly Gee Willikers Batman'
@@ -39,7 +33,7 @@ class DirtyTest < Test::Unit::TestCase
39
33
  doc.phrase_changed?.should_not be_true
40
34
  doc.phrase_change.should be_nil
41
35
  end
42
-
36
+
43
37
  should "clear changes on save!" do
44
38
  doc = @document.new
45
39
  doc.phrase = 'Golly Gee Willikers Batman'
@@ -48,15 +42,18 @@ class DirtyTest < Test::Unit::TestCase
48
42
  doc.phrase_changed?.should_not be_true
49
43
  doc.phrase_change.should be_nil
50
44
  end
51
-
45
+
52
46
  should "not happen when loading from database" do
53
47
  doc = @document.create(:phrase => 'Foo')
48
+ doc = @document.find(doc.id)
49
+
50
+ doc.changed?.should be_false
54
51
  doc.phrase = 'Fart'
55
52
  doc.changed?.should be_true
56
53
  doc.reload
57
54
  doc.changed?.should be_false
58
55
  end
59
-
56
+
60
57
  should "happen if changed after loading from database" do
61
58
  doc = @document.create(:phrase => 'Foo')
62
59
  doc.reload
@@ -65,7 +62,7 @@ class DirtyTest < Test::Unit::TestCase
65
62
  doc.changed?.should be_true
66
63
  end
67
64
  end
68
-
65
+
69
66
  context "blank new value and type integer" do
70
67
  should "not mark changes" do
71
68
  @document.key :age, Integer
@@ -147,10 +144,20 @@ class DirtyTest < Test::Unit::TestCase
147
144
 
148
145
  context "changing a foreign key through association" do
149
146
  should "mark changes" do
150
- status = Status.create(:name => 'Foo')
151
- status.project = Project.create(:name => 'Bar')
152
- status.changed?.should be_true
153
- status.changed.should == %w(project_id)
147
+ project_class = Doc do
148
+ key :name, String
149
+ end
150
+
151
+ milestone_class = Doc do
152
+ key :project_id, ObjectId
153
+ key :name, String
154
+ end
155
+ milestone_class.belongs_to :project, :class => project_class
156
+
157
+ milestone = milestone_class.create(:name => 'Launch')
158
+ milestone.project = project_class.create(:name => 'Harmony')
159
+ milestone.changed?.should be_true
160
+ milestone.changed.should == %w(project_id)
154
161
  end
155
162
  end
156
163
  end
@@ -239,7 +239,19 @@ class DocumentTest < Test::Unit::TestCase
239
239
  end
240
240
 
241
241
  should "raise document not found if nothing provided for find!" do
242
- lambda { @document.find! }.should raise_error(MongoMapper::DocumentNotFound)
242
+ assert_raises(MongoMapper::DocumentNotFound) do
243
+ @document.find!
244
+ end
245
+ end
246
+
247
+ should "raise error if trying to find with :all, :first, or :last" do
248
+ [:all, :first, :last].each do |m|
249
+ assert_raises(ArgumentError) { @document.find(m) }
250
+ end
251
+
252
+ [:all, :first, :last].each do |m|
253
+ assert_raises(ArgumentError) { @document.find!(m) }
254
+ end
243
255
  end
244
256
 
245
257
  context "(with a single id)" do
@@ -252,9 +264,7 @@ class DocumentTest < Test::Unit::TestCase
252
264
  end
253
265
 
254
266
  should "raise error if document not found with find!" do
255
- lambda {
256
- @document.find!(123)
257
- }.should raise_error(MongoMapper::DocumentNotFound)
267
+ assert_raises(MongoMapper::DocumentNotFound) { @document.find!(123) }
258
268
  end
259
269
  end
260
270
 
@@ -267,7 +277,17 @@ class DocumentTest < Test::Unit::TestCase
267
277
  @document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
268
278
  end
269
279
 
270
- should "return array if array only has one element" do
280
+ should "compact not found when using find" do
281
+ @document.find(@doc1._id, 1234).should == [@doc1]
282
+ end
283
+
284
+ should "raise error if not all found when using find!" do
285
+ assert_raises(MongoMapper::DocumentNotFound) do
286
+ @document.find!(@doc1._id, 1234)
287
+ end
288
+ end
289
+
290
+ should "return array if array with one element" do
271
291
  @document.find([@doc1._id]).should == [@doc1]
272
292
  end
273
293
  end
@@ -277,43 +297,21 @@ class DocumentTest < Test::Unit::TestCase
277
297
  @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
278
298
  end
279
299
 
280
- context "(with :all)" do
281
- should "find all documents" do
282
- @document.find(:all, :order => 'first_name').should == [@doc1, @doc3, @doc2]
283
- end
284
-
285
- should "be able to add conditions" do
286
- @document.find(:all, :first_name => 'John').should == [@doc1]
287
- end
288
- end
289
-
290
- context "(with #all)" do
300
+ context "#all" do
291
301
  should "find all documents based on criteria" do
292
302
  @document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
293
303
  @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
294
304
  end
295
305
  end
296
306
 
297
- context "(with :first)" do
298
- should "find first document" do
299
- @document.find(:first, :order => 'first_name').should == @doc1
300
- end
301
- end
302
-
303
- context "(with #first)" do
307
+ context "#first" do
304
308
  should "find first document based on criteria" do
305
309
  @document.first(:order => 'first_name').should == @doc1
306
310
  @document.first(:age => 28).should == @doc2
307
311
  end
308
312
  end
309
313
 
310
- context "(with :last)" do
311
- should "find last document" do
312
- @document.find(:last, :order => 'age').should == @doc2
313
- end
314
- end
315
-
316
- context "(with #last)" do
314
+ context "#last" do
317
315
  should "find last document based on criteria" do
318
316
  @document.last(:order => 'age').should == @doc2
319
317
  @document.last(:order => 'age', :age => 28).should == @doc2
@@ -324,7 +322,7 @@ class DocumentTest < Test::Unit::TestCase
324
322
  end
325
323
  end
326
324
 
327
- context "(with :find_by)" do
325
+ context "#find_by..." do
328
326
  should "find document based on argument" do
329
327
  @document.find_by_first_name('John').should == @doc1
330
328
  @document.find_by_last_name('Nunemaker', :order => 'age desc').should == @doc1
@@ -340,7 +338,7 @@ class DocumentTest < Test::Unit::TestCase
340
338
  end
341
339
  end
342
340
 
343
- context "(with dynamic finders)" do
341
+ context "dynamic finders" do
344
342
  should "find document based on all arguments" do
345
343
  @document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
346
344
  end
@@ -393,7 +391,7 @@ class DocumentTest < Test::Unit::TestCase
393
391
  end
394
392
 
395
393
  should "return nil if document not found" do
396
- @document.find_by_id(1234).should be(nil)
394
+ @document.find_by_id(1234).should be_nil
397
395
  end
398
396
  end
399
397
 
@@ -835,7 +833,7 @@ class DocumentTest < Test::Unit::TestCase
835
833
  @parent.save
836
834
  @daughter.save
837
835
 
838
- collection = DocParent.find(:all)
836
+ collection = DocParent.all
839
837
  collection.size.should == 2
840
838
  collection.first.should be_kind_of(DocParent)
841
839
  collection.first.name.should == "Daddy Warbucks"
@@ -1104,6 +1102,11 @@ class DocumentTest < Test::Unit::TestCase
1104
1102
  should "return self" do
1105
1103
  @instance.reload.object_id.should == @instance.object_id
1106
1104
  end
1105
+
1106
+ should "raise DocumentNotFound if not found" do
1107
+ @instance.destroy
1108
+ assert_raises(MongoMapper::DocumentNotFound) { @instance.reload }
1109
+ end
1107
1110
  end
1108
1111
 
1109
1112
  context "Loading a document from the database with keys that are not defined" do
@@ -14,17 +14,21 @@ class IdentityMapTest < Test::Unit::TestCase
14
14
  context "Document" do
15
15
  setup do
16
16
  @person_class = Doc('Person') do
17
+ set_collection_name 'people'
17
18
  key :name, String
18
- plugin MongoMapper::Plugins::IdentityMap
19
19
  end
20
20
 
21
21
  @post_class = Doc('Post') do
22
+ set_collection_name 'posts'
22
23
  key :title, String
23
- plugin MongoMapper::Plugins::IdentityMap
24
+ key :person_id, ObjectId
24
25
  end
25
26
 
26
- @person_class.identity_map = {}
27
- @post_class.identity_map = {}
27
+ @post_class.belongs_to :person, :class => @person_class
28
+ @person_class.many :posts, :class => @post_class
29
+
30
+ @person_class.identity_map.clear
31
+ @post_class.identity_map.clear
28
32
  end
29
33
 
30
34
  should "default identity map to hash" do
@@ -40,11 +44,11 @@ class IdentityMapTest < Test::Unit::TestCase
40
44
 
41
45
  should "have identity map key that is always unique per document and class" do
42
46
  person = @person_class.new
43
- person.identity_map_key.should == "Person:#{person.id}"
47
+ person.identity_map_key.should == "people:#{person.id}"
44
48
  @person_class.identity_map_key(person.id).should == person.identity_map_key
45
49
 
46
50
  post = @post_class.new
47
- post.identity_map_key.should == "Post:#{post.id}"
51
+ post.identity_map_key.should == "posts:#{post.id}"
48
52
  @post_class.identity_map_key(post.id).should == post.identity_map_key
49
53
 
50
54
  person.identity_map_key.should_not == post.identity_map_key
@@ -56,6 +60,13 @@ class IdentityMapTest < Test::Unit::TestCase
56
60
  person.save.should be_true
57
61
  assert_in_map(person)
58
62
  end
63
+
64
+ should "allow saving with options" do
65
+ person = @person_class.new
66
+ assert_nothing_raised do
67
+ person.save(:validate => false).should be_true
68
+ end
69
+ end
59
70
 
60
71
  should "remove key from map when deleted" do
61
72
  person = @person_class.create(:name => 'Fred')
@@ -64,35 +75,39 @@ class IdentityMapTest < Test::Unit::TestCase
64
75
  assert_not_in_map(person)
65
76
  end
66
77
 
67
- context "#load" do
78
+ context "reload" do
68
79
  setup do
69
- @id = Mongo::ObjectID.new
80
+ @person = @person_class.create(:name => 'Fred')
70
81
  end
71
-
72
- should "add document to map with _id key as symbol" do
73
- loaded = @person_class.load({:_id => @id, :name => 'Frank'})
74
- assert_in_map(loaded)
82
+
83
+ should "remove object from identity and re-query" do
84
+ assert_in_map(@person)
85
+ Mongo::Collection.any_instance.expects(:find_one).once.returns({})
86
+ @person.reload
75
87
  end
76
88
 
77
- should "add document to map with _id key as string" do
78
- loaded = @person_class.load({'_id' => @id, :name => 'Frank'})
79
- assert_in_map(loaded)
89
+ should "add object back into map" do
90
+ assert_in_map(@person)
91
+ object_id = @person.object_id
92
+ @person.reload.object_id.should == object_id
93
+ assert_in_map(@person)
80
94
  end
81
-
82
- should "add document to map with id key as symbol" do
83
- loaded = @person_class.load({:id => @id, :name => 'Frank'})
84
- assert_in_map(loaded)
95
+ end
96
+
97
+ context "#load" do
98
+ setup do
99
+ @id = Mongo::ObjectID.new
85
100
  end
86
-
87
- should "add document to map with id key as string" do
88
- loaded = @person_class.load({'id' => @id, :name => 'Frank'})
101
+
102
+ should "add document to map" do
103
+ loaded = @person_class.load({'_id' => @id, 'name' => 'Frank'})
89
104
  assert_in_map(loaded)
90
105
  end
91
-
106
+
92
107
  should "return document if already in map" do
93
- first_load = @person_class.load({:_id => @id, :name => 'Frank'})
108
+ first_load = @person_class.load({'_id' => @id, 'name' => 'Frank'})
94
109
  @person_class.identity_map.expects(:[]=).never
95
- second_load = @person_class.load({:_id => @id, :name => 'Frank'})
110
+ second_load = @person_class.load({'_id' => @id, 'name' => 'Frank'})
96
111
  first_load.object_id.should == second_load.object_id
97
112
  end
98
113
  end
@@ -132,6 +147,32 @@ class IdentityMapTest < Test::Unit::TestCase
132
147
  found_person = @person_class.find(@person.id)
133
148
  found_person.object_id.should == @person.object_id
134
149
  end
150
+ end
151
+ end
152
+
153
+ context "#find (with one id and options)" do
154
+ setup do
155
+ @person = @person_class.create(:name => 'Fred')
156
+ @post1 = @person.posts.create(:title => 'I Love Mongo')
157
+ @post2 = @person.posts.create(:title => 'Migrations Suck!')
158
+ end
159
+
160
+ # There are times when even though the id matches, other criteria doesn't
161
+ # so we need to do the query to ensure that when criteria doesn't match
162
+ # the document is in fact not found.
163
+ #
164
+ # I'm open to not making this query if someone can figure out reliable
165
+ # way to check if document matches criteria without querying.
166
+ should "query the database" do
167
+ assert_in_map(@post1)
168
+ Mongo::Collection.any_instance.expects(:find_one)
169
+ @person.posts.find(@post1.id)
170
+ end
171
+
172
+ should "return exact object" do
173
+ assert_in_map(@post1)
174
+ @person.posts.find(@post1.id)
175
+ assert_in_map(@post1)
135
176
  end
136
177
  end
137
178
 
@@ -229,5 +270,69 @@ class IdentityMapTest < Test::Unit::TestCase
229
270
  end
230
271
  end
231
272
 
273
+ context "#find_by_id" do
274
+ setup do
275
+ @person = @person_class.create(:name => 'Bill')
276
+ end
277
+
278
+ should "return nil for document id not found in collection" do
279
+ assert_in_map(@person)
280
+ @person_class.find_by_id(1234).should be_nil
281
+ end
282
+ end
283
+
284
+ context "single collection inheritance" do
285
+ setup do
286
+ class ::DocParent
287
+ include MongoMapper::Document
288
+ key :_type, String
289
+ key :name, String
290
+ key :parent_id, ObjectId
291
+
292
+ belongs_to :parent, :class_name => 'DocParent'
293
+ one :child, :class_name => 'DocDaughter'
294
+ end
295
+ DocParent.collection.remove
296
+ DocParent.identity_map.clear
297
+
298
+ class ::DocDaughter < ::DocParent; end
299
+ end
300
+
301
+ teardown do
302
+ Object.send :remove_const, 'DocParent' if defined?(::DocParent)
303
+ Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
304
+ end
305
+
306
+ should "share the same identity map 4eva" do
307
+ @daughter = DocDaughter.create(:name => 'Jill')
308
+ assert_in_map(@daughter)
309
+ DocParent.identity_map_key(@daughter).should == DocDaughter.identity_map_key(@daughter)
310
+ DocParent.identity_map.object_id.should == DocDaughter.identity_map.object_id
311
+ end
312
+
313
+ should "load from map when using parent collection inherited class" do
314
+ @daughter = DocDaughter.create(:name => 'Jill')
315
+ DocParent.find(@daughter.id).object_id.should == @daughter.object_id
316
+ end
317
+
318
+ should "work correctly with belongs to proxy" do
319
+ @parent = DocParent.create(:name => 'Dad')
320
+ assert_in_map(@parent)
321
+
322
+ @daughter = DocDaughter.create(:name => 'Jill', :parent => @parent)
323
+ assert_in_map(@daughter)
324
+ @parent.object_id.should == @daughter.parent.object_id
325
+ end
326
+
327
+ should "work correctly with one proxy" do
328
+ @daughter = DocDaughter.create(:name => 'Jill')
329
+ assert_in_map(@daughter)
330
+
331
+ @parent = DocParent.create(:name => 'Dad', :child => @daughter)
332
+ assert_in_map(@parent)
333
+
334
+ @parent.child.object_id.should == @daughter.object_id
335
+ end
336
+ end
232
337
  end
233
338
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo_mapper-unstable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2010.1.18
4
+ version: 2010.1.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-18 00:00:00 -05:00
12
+ date: 2010-01-19 00:00:00 -05:00
13
13
  default_executable: mmconsole
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency