djsun-mongomapper 0.3.1.1 → 0.3.3

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 (34) hide show
  1. data/History +20 -1
  2. data/Rakefile +5 -3
  3. data/VERSION +1 -1
  4. data/lib/mongomapper/associations/base.rb +3 -5
  5. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +5 -3
  6. data/lib/mongomapper/associations/belongs_to_proxy.rb +4 -4
  7. data/lib/mongomapper/associations/many_documents_proxy.rb +32 -14
  8. data/lib/mongomapper/associations/proxy.rb +2 -6
  9. data/lib/mongomapper/associations.rb +38 -15
  10. data/lib/mongomapper/document.rb +165 -95
  11. data/lib/mongomapper/dynamic_finder.rb +38 -0
  12. data/lib/mongomapper/embedded_document.rb +116 -88
  13. data/lib/mongomapper/finder_options.rb +3 -14
  14. data/lib/mongomapper/key.rb +12 -16
  15. data/lib/mongomapper/serializers/json_serializer.rb +15 -12
  16. data/lib/mongomapper/support.rb +30 -0
  17. data/lib/mongomapper.rb +7 -33
  18. data/mongomapper.gemspec +10 -7
  19. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +14 -0
  20. data/test/functional/associations/test_belongs_to_proxy.rb +10 -0
  21. data/test/functional/associations/test_many_polymorphic_proxy.rb +46 -52
  22. data/test/functional/associations/test_many_proxy.rb +71 -12
  23. data/test/functional/test_associations.rb +9 -2
  24. data/test/functional/test_document.rb +281 -20
  25. data/test/functional/test_rails_compatibility.rb +2 -3
  26. data/test/models.rb +39 -8
  27. data/test/unit/serializers/test_json_serializer.rb +46 -12
  28. data/test/unit/test_association_base.rb +10 -2
  29. data/test/unit/test_document.rb +7 -9
  30. data/test/unit/test_embedded_document.rb +180 -24
  31. data/test/unit/test_finder_options.rb +7 -38
  32. data/test/unit/test_key.rb +54 -24
  33. metadata +5 -5
  34. data/test/unit/test_mongo_id.rb +0 -35
@@ -1,36 +1,36 @@
1
1
  require 'observer'
2
2
 
3
3
  module MongoMapper
4
- module EmbeddedDocument
4
+ module EmbeddedDocument
5
5
  def self.included(model)
6
6
  model.class_eval do
7
7
  extend ClassMethods
8
8
  include InstanceMethods
9
-
9
+
10
10
  extend Associations::ClassMethods
11
11
  include Associations::InstanceMethods
12
-
12
+
13
13
  include RailsCompatibility::EmbeddedDocument
14
14
  include Validatable
15
15
  include Serialization
16
16
 
17
- key :_id, MongoID
17
+ key :_id, String
18
18
  end
19
19
  end
20
-
20
+
21
21
  module ClassMethods
22
22
  def inherited(subclass)
23
23
  unless subclass.embeddable?
24
24
  subclass.collection(self.collection.name)
25
25
  end
26
-
26
+
27
27
  (@subclasses ||= []) << subclass
28
28
  end
29
-
29
+
30
30
  def subclasses
31
31
  @subclasses
32
32
  end
33
-
33
+
34
34
  def keys
35
35
  @keys ||= if parent = parent_model
36
36
  parent.keys.dup
@@ -38,90 +38,104 @@ module MongoMapper
38
38
  HashWithIndifferentAccess.new
39
39
  end
40
40
  end
41
-
42
- def key(name, type, options={})
43
- key = Key.new(name, type, options)
44
- keys[key.name] = key
45
-
46
- create_accessors_for(key)
47
- add_to_subclasses(name, type, options)
48
- apply_validations_for(key)
49
- create_indexes_for(key)
50
-
51
- key
52
- end
53
-
54
- def create_accessors_for(key)
55
- define_method(key.name) do
56
- read_attribute(key.name)
57
- end
58
-
59
- define_method("#{key.name}_before_typecast") do
60
- read_attribute_before_typecast(key.name)
61
- end
62
-
63
- define_method("#{key.name}=") do |value|
64
- write_attribute(key.name, value)
65
- end
41
+
42
+ def key(*args)
43
+ key = Key.new(*args)
66
44
 
67
- define_method("#{key.name}?") do
68
- read_attribute(key.name).present?
45
+ if keys[key.name].blank?
46
+ keys[key.name] = key
47
+
48
+ create_accessors_for(key)
49
+ add_to_subclasses(*args)
50
+ apply_validations_for(key)
51
+ create_indexes_for(key)
52
+
53
+ key
69
54
  end
70
55
  end
71
-
72
- def add_to_subclasses(name, type, options)
56
+
57
+ def add_to_subclasses(*args)
73
58
  return if subclasses.blank?
74
-
59
+
75
60
  subclasses.each do |subclass|
76
- subclass.key name, type, options
61
+ subclass.key(*args)
77
62
  end
78
63
  end
79
-
64
+
80
65
  def ensure_index(name_or_array, options={})
81
66
  keys_to_index = if name_or_array.is_a?(Array)
82
67
  name_or_array.map { |pair| [pair[0], pair[1]] }
83
68
  else
84
69
  name_or_array
85
70
  end
86
-
71
+
87
72
  collection.create_index(keys_to_index, options.delete(:unique))
88
73
  end
89
-
74
+
90
75
  def embeddable?
91
76
  !self.ancestors.include?(Document)
92
77
  end
93
-
78
+
94
79
  def parent_model
95
- if parent = ancestors[1]
96
- parent if parent.ancestors.include?(EmbeddedDocument)
80
+ (ancestors - [self,EmbeddedDocument]).find do |parent_class|
81
+ parent_class.ancestors.include?(EmbeddedDocument)
97
82
  end
98
83
  end
99
-
84
+
100
85
  private
86
+ def accessors_module
87
+ if const_defined?('MongoMapperKeys') && constants.include?( 'MongoMapperKeys' )
88
+ const_get 'MongoMapperKeys'
89
+ else
90
+ const_set 'MongoMapperKeys', Module.new
91
+ end
92
+ end
93
+
94
+ def create_accessors_for(key)
95
+ accessors_module.module_eval <<-end_eval
96
+ def #{key.name}
97
+ read_attribute( :'#{key.name}' )
98
+ end
99
+
100
+ def #{key.name}_before_typecast
101
+ read_attribute_before_typecast(:'#{key.name}')
102
+ end
103
+
104
+ def #{key.name}=(value)
105
+ write_attribute(:'#{key.name}', value)
106
+ end
107
+
108
+ def #{key.name}?
109
+ read_attribute(:#{key.name}).present?
110
+ end
111
+ end_eval
112
+ include accessors_module
113
+ end
114
+
101
115
  def create_indexes_for(key)
102
116
  ensure_index key.name if key.options[:index]
103
117
  end
104
-
118
+
105
119
  def apply_validations_for(key)
106
120
  attribute = key.name.to_sym
107
-
121
+
108
122
  if key.options[:required]
109
123
  validates_presence_of(attribute)
110
124
  end
111
-
125
+
112
126
  if key.options[:unique]
113
127
  validates_uniqueness_of(attribute)
114
128
  end
115
-
129
+
116
130
  if key.options[:numeric]
117
131
  number_options = key.type == Integer ? {:only_integer => true} : {}
118
132
  validates_numericality_of(attribute, number_options)
119
133
  end
120
-
134
+
121
135
  if key.options[:format]
122
136
  validates_format_of(attribute, :with => key.options[:format])
123
137
  end
124
-
138
+
125
139
  if key.options[:length]
126
140
  length_options = case key.options[:length]
127
141
  when Integer
@@ -135,7 +149,7 @@ module MongoMapper
135
149
  end
136
150
  end
137
151
  end
138
-
152
+
139
153
  module InstanceMethods
140
154
  def initialize(attrs={})
141
155
  unless attrs.nil?
@@ -144,90 +158,104 @@ module MongoMapper
144
158
  send("#{association.name}=", collection)
145
159
  end
146
160
  end
147
-
161
+
148
162
  self.attributes = attrs
149
163
  end
150
-
164
+
151
165
  if self.class.embeddable? && read_attribute(:_id).blank?
152
- write_attribute :_id, XGen::Mongo::Driver::ObjectID.new
166
+ write_attribute :_id, XGen::Mongo::Driver::ObjectID.new.to_s
153
167
  end
154
168
  end
155
-
169
+
156
170
  def attributes=(attrs)
157
171
  return if attrs.blank?
158
- attrs.each_pair do |method, value|
159
- self.send("#{method}=", value)
172
+ attrs.each_pair do |name, value|
173
+ writer_method = "#{name}="
174
+
175
+ if respond_to?(writer_method)
176
+ self.send(writer_method, value)
177
+ else
178
+ self[name.to_s] = value
179
+ end
160
180
  end
161
181
  end
162
-
182
+
163
183
  def attributes
164
- returning HashWithIndifferentAccess.new do |attributes|
165
- self.class.keys.each_pair do |name, key|
166
- value = value_for_key(key)
167
- attributes[name] = value unless value.nil?
168
- end
184
+ attrs = HashWithIndifferentAccess.new
185
+ self.class.keys.each_pair do |name, key|
186
+ value =
187
+ if key.native?
188
+ read_attribute(key.name)
189
+ else
190
+ if embedded_document = read_attribute(key.name)
191
+ embedded_document.attributes
192
+ end
193
+ end
169
194
 
170
- attributes.merge!(embedded_association_attributes)
195
+ attrs[name] = value unless value.nil?
171
196
  end
197
+ attrs.merge!(embedded_association_attributes)
172
198
  end
173
-
199
+
174
200
  def [](name)
175
201
  read_attribute(name)
176
202
  end
177
-
203
+
178
204
  def []=(name, value)
205
+ ensure_key_exists(name)
179
206
  write_attribute(name, value)
180
207
  end
181
-
208
+
182
209
  def ==(other)
183
210
  other.is_a?(self.class) && id == other.id
184
211
  end
185
-
212
+
186
213
  def id
187
- self._id.to_s
214
+ read_attribute(:_id)
188
215
  end
189
-
216
+
190
217
  def id=(value)
191
- self._id = value
218
+ @using_custom_id = true
219
+ write_attribute :_id, value
192
220
  end
193
221
 
222
+ def using_custom_id?
223
+ !!@using_custom_id
224
+ end
225
+
194
226
  def inspect
195
227
  attributes_as_nice_string = self.class.keys.keys.collect do |name|
196
228
  "#{name}: #{read_attribute(name)}"
197
229
  end.join(", ")
198
230
  "#<#{self.class} #{attributes_as_nice_string}>"
199
231
  end
200
-
232
+
201
233
  private
202
- def value_for_key(key)
203
- if key.native?
204
- read_attribute(key.name)
205
- else
206
- embedded_document = read_attribute(key.name)
207
- embedded_document && embedded_document.attributes
208
- end
234
+ def ensure_key_exists(name)
235
+ self.class.key(name) unless respond_to?("#{name}=")
209
236
  end
210
-
237
+
211
238
  def read_attribute(name)
212
- val = self.class.keys[name].get(instance_variable_get("@#{name}"))
213
- instance_variable_set "@#{name}", val
239
+ value = self.class.keys[name].get(instance_variable_get("@#{name}"))
240
+ instance_variable_set "@#{name}", value if !frozen?
241
+ value
214
242
  end
215
-
243
+
216
244
  def read_attribute_before_typecast(name)
217
245
  instance_variable_get("@#{name}_before_typecast")
218
246
  end
219
-
247
+
220
248
  def write_attribute(name, value)
221
249
  instance_variable_set "@#{name}_before_typecast", value
222
250
  instance_variable_set "@#{name}", self.class.keys[name].set(value)
223
251
  end
224
-
252
+
225
253
  def embedded_association_attributes
226
254
  returning HashWithIndifferentAccess.new do |attrs|
227
255
  self.class.associations.each_pair do |name, association|
228
256
  next unless association.embeddable?
229
257
  next unless documents = instance_variable_get(association.ivar)
230
-
258
+
231
259
  attrs[name] = documents.collect { |doc| doc.attributes }
232
260
  end
233
261
  end
@@ -7,26 +7,15 @@ module MongoMapper
7
7
  conditions.each_pair do |field, value|
8
8
  case value
9
9
  when Array
10
- operator_present = field.to_s =~ /^\$/
11
-
12
- dealing_with_ids = field.to_s == '_id' ||
13
- (parent_key && parent_key.to_s == '_id')
14
-
15
- criteria[field] = if dealing_with_ids
16
- ids = value.map { |id| MongoID.mm_typecast(id) }
17
- operator_present ? ids : {'$in' => ids}
18
- elsif operator_present
10
+ operator_present = field.to_s =~ /^\$/
11
+ criteria[field] = if operator_present
19
12
  value
20
13
  else
21
14
  {'$in' => value}
22
15
  end
23
16
  when Hash
24
17
  criteria[field] = to_mongo_criteria(value, field)
25
- else
26
- if field.to_s == '_id'
27
- value = MongoID.mm_typecast(value)
28
- end
29
-
18
+ else
30
19
  criteria[field] = value
31
20
  end
32
21
  end
@@ -1,12 +1,13 @@
1
1
  module MongoMapper
2
2
  class Key
3
3
  # DateTime and Date are currently not supported by mongo's bson so just use Time
4
- NativeTypes = [String, Float, Time, Integer, Boolean, Array, Hash, MongoID]
4
+ NativeTypes = [String, Float, Time, Integer, Boolean, Array, Hash]
5
5
 
6
6
  attr_accessor :name, :type, :options, :default_value
7
-
8
- def initialize(name, type, options={})
9
- @name, @type = name.to_s, type
7
+
8
+ def initialize(*args)
9
+ options = args.extract_options!
10
+ @name, @type = args.shift.to_s, args.shift
10
11
  self.options = (options || {}).symbolize_keys
11
12
  self.default_value = self.options.delete(:default)
12
13
  end
@@ -20,11 +21,11 @@ module MongoMapper
20
21
  end
21
22
 
22
23
  def native?
23
- @native ||= NativeTypes.include?(type)
24
+ @native ||= NativeTypes.include?(type) || type.nil?
24
25
  end
25
26
 
26
27
  def embedded_document?
27
- type.ancestors.include?(EmbeddedDocument) && !type.ancestors.include?(Document)
28
+ type.respond_to?(:embeddable?) && type.embeddable?
28
29
  end
29
30
 
30
31
  def get(value)
@@ -40,26 +41,21 @@ module MongoMapper
40
41
 
41
42
  private
42
43
  def typecast(value)
44
+ return value if type.nil?
43
45
  return HashWithIndifferentAccess.new(value) if value.is_a?(Hash) && type == Hash
46
+ return value.utc if type == Time && value.kind_of?(type)
44
47
  return value if value.kind_of?(type) || value.nil?
45
48
  begin
46
49
  if type == String then value.to_s
47
50
  elsif type == Float then value.to_f
48
51
  elsif type == Array then value.to_a
49
- elsif type == Time then Time.parse(value.to_s)
50
- elsif type == MongoID then MongoID.mm_typecast(value)
51
- #elsif type == Date then Date.parse(value.to_s)
52
+ elsif type == Time then Time.parse(value.to_s).utc
52
53
  elsif type == Boolean then Boolean.mm_typecast(value)
53
54
  elsif type == Integer
54
55
  # ganked from datamapper
55
56
  value_to_i = value.to_i
56
- if value_to_i == 0 && value != '0'
57
- value_to_s = value.to_s
58
- begin
59
- Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
60
- rescue ArgumentError
61
- nil
62
- end
57
+ if value_to_i == 0
58
+ value.to_s =~ /^(0x|0b)?0+/ ? 0 : nil
63
59
  else
64
60
  value_to_i
65
61
  end
@@ -50,18 +50,8 @@ module MongoMapper #:nodoc:
50
50
  # "created_at": "2006/08/01", "awesome": true,
51
51
  # "permalink": "1-konata-izumi"}
52
52
  def to_json(options = {})
53
- unless options[:only]
54
- o = options[:methods]
55
- if o && o.is_a?(Array)
56
- o << :id
57
- elsif o
58
- o = [o, :id]
59
- else
60
- o = :id
61
- end
62
- options[:methods] = o
63
- end
64
- options.reverse_merge!(:except => :_id)
53
+ apply_to_json_defaults(options)
54
+
65
55
  if include_root_in_json
66
56
  "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
67
57
  else
@@ -85,5 +75,18 @@ module MongoMapper #:nodoc:
85
75
  @json_class_name ||= name.demodulize.underscore.inspect
86
76
  end
87
77
  end
78
+
79
+ private
80
+ def apply_to_json_defaults(options)
81
+ unless options[:only]
82
+ methods = [options.delete(:methods)].flatten.compact
83
+ methods << :id
84
+ options[:methods] = methods.uniq
85
+ end
86
+
87
+ except = [options.delete(:except)].flatten.compact
88
+ except << :_id
89
+ options[:except] = except
90
+ end
88
91
  end
89
92
  end
@@ -0,0 +1,30 @@
1
+ class BasicObject #:nodoc:
2
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|instance_eval|proxy_|^object_id$)/ }
3
+ end unless defined?(BasicObject)
4
+
5
+ class Boolean
6
+ def self.mm_typecast(value)
7
+ ['true', 't', '1'].include?(value.to_s.downcase)
8
+ end
9
+ end
10
+
11
+ class Object
12
+ # The hidden singleton lurks behind everyone
13
+ def metaclass
14
+ class << self; self end
15
+ end
16
+
17
+ def meta_eval(&blk)
18
+ metaclass.instance_eval(&blk)
19
+ end
20
+
21
+ # Adds methods to a metaclass
22
+ def meta_def(name, &blk)
23
+ meta_eval { define_method(name, &blk) }
24
+ end
25
+
26
+ # Defines an instance method within a class
27
+ def class_def(name, &blk)
28
+ class_eval { define_method(name, &blk) }
29
+ end
30
+ end
data/lib/mongomapper.rb CHANGED
@@ -2,43 +2,17 @@ require 'pathname'
2
2
  require 'rubygems'
3
3
 
4
4
  gem 'activesupport'
5
- gem 'mongodb-mongo', '0.10.1'
5
+ gem 'mongodb-mongo', '0.11.1'
6
6
  gem 'jnunemaker-validatable', '1.7.2'
7
7
 
8
8
  require 'activesupport'
9
9
  require 'mongo'
10
10
  require 'validatable'
11
11
 
12
- class BasicObject #:nodoc:
13
- instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
14
- end unless defined?(BasicObject)
15
-
16
- class Boolean
17
- def self.mm_typecast(value)
18
- ['true', 't', '1'].include?(value.to_s.downcase)
19
- end
20
- end
21
-
22
- class MongoID < XGen::Mongo::Driver::ObjectID
23
- def self.mm_typecast(value)
24
- begin
25
- if value.is_a?(XGen::Mongo::Driver::ObjectID)
26
- value
27
- else
28
- XGen::Mongo::Driver::ObjectID::from_string(value.to_s)
29
- end
30
- rescue => exception
31
- if exception.message == 'illegal ObjectID format'
32
- raise MongoMapper::IllegalID
33
- else
34
- raise exception
35
- end
36
- end
37
- end
38
- end
39
-
40
12
  dir = Pathname(__FILE__).dirname.expand_path + 'mongomapper'
41
13
 
14
+ require dir + 'support'
15
+
42
16
  require dir + 'associations'
43
17
  require dir + 'associations/base'
44
18
 
@@ -54,6 +28,7 @@ require dir + 'associations/many_embedded_polymorphic_proxy'
54
28
 
55
29
  require dir + 'callbacks'
56
30
  require dir + 'finder_options'
31
+ require dir + 'dynamic_finder'
57
32
  require dir + 'key'
58
33
  require dir + 'observing'
59
34
  require dir + 'pagination'
@@ -68,16 +43,15 @@ require dir + 'embedded_document'
68
43
  require dir + 'document'
69
44
 
70
45
  module MongoMapper
71
- DocumentNotFound = Class.new(StandardError)
72
- IllegalID = Class.new(StandardError)
46
+ DocumentNotFound = Class.new(StandardError)
73
47
 
74
- DocumentNotValid = Class.new(StandardError) do
48
+ DocumentNotValid = Class.new(StandardError) do
75
49
  def initialize(document)
76
50
  @document = document
77
51
  super("Validation failed: #{@document.errors.full_messages.join(", ")}")
78
52
  end
79
53
  end
80
-
54
+
81
55
  def self.connection
82
56
  @@connection ||= XGen::Mongo::Driver::Mongo.new
83
57
  end
data/mongomapper.gemspec CHANGED
@@ -1,12 +1,15 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
1
4
  # -*- encoding: utf-8 -*-
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = %q{mongomapper}
5
- s.version = "0.3.1.1"
8
+ s.version = "0.3.3"
6
9
 
7
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
11
  s.authors = ["John Nunemaker"]
9
- s.date = %q{2009-08-06}
12
+ s.date = %q{2009-08-16}
10
13
  s.default_executable = %q{mmconsole}
11
14
  s.email = %q{nunemaker@gmail.com}
12
15
  s.executables = ["mmconsole"]
@@ -35,6 +38,7 @@ Gem::Specification.new do |s|
35
38
  "lib/mongomapper/associations/proxy.rb",
36
39
  "lib/mongomapper/callbacks.rb",
37
40
  "lib/mongomapper/document.rb",
41
+ "lib/mongomapper/dynamic_finder.rb",
38
42
  "lib/mongomapper/embedded_document.rb",
39
43
  "lib/mongomapper/finder_options.rb",
40
44
  "lib/mongomapper/key.rb",
@@ -45,6 +49,7 @@ Gem::Specification.new do |s|
45
49
  "lib/mongomapper/save_with_validation.rb",
46
50
  "lib/mongomapper/serialization.rb",
47
51
  "lib/mongomapper/serializers/json_serializer.rb",
52
+ "lib/mongomapper/support.rb",
48
53
  "lib/mongomapper/validations.rb",
49
54
  "mongomapper.gemspec",
50
55
  "test/NOTE_ON_TESTING",
@@ -68,7 +73,6 @@ Gem::Specification.new do |s|
68
73
  "test/unit/test_embedded_document.rb",
69
74
  "test/unit/test_finder_options.rb",
70
75
  "test/unit/test_key.rb",
71
- "test/unit/test_mongo_id.rb",
72
76
  "test/unit/test_mongomapper.rb",
73
77
  "test/unit/test_observing.rb",
74
78
  "test/unit/test_pagination.rb",
@@ -103,7 +107,6 @@ Gem::Specification.new do |s|
103
107
  "test/unit/test_embedded_document.rb",
104
108
  "test/unit/test_finder_options.rb",
105
109
  "test/unit/test_key.rb",
106
- "test/unit/test_mongo_id.rb",
107
110
  "test/unit/test_mongomapper.rb",
108
111
  "test/unit/test_observing.rb",
109
112
  "test/unit/test_pagination.rb",
@@ -118,20 +121,20 @@ Gem::Specification.new do |s|
118
121
 
119
122
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
120
123
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
121
- s.add_runtime_dependency(%q<mongodb-mongo>, ["= 0.10.1"])
124
+ s.add_runtime_dependency(%q<mongodb-mongo>, ["= 0.11.1"])
122
125
  s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.7.2"])
123
126
  s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
124
127
  s.add_development_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
125
128
  else
126
129
  s.add_dependency(%q<activesupport>, [">= 0"])
127
- s.add_dependency(%q<mongodb-mongo>, ["= 0.10.1"])
130
+ s.add_dependency(%q<mongodb-mongo>, ["= 0.11.1"])
128
131
  s.add_dependency(%q<jnunemaker-validatable>, ["= 1.7.2"])
129
132
  s.add_dependency(%q<mocha>, ["= 0.9.4"])
130
133
  s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
131
134
  end
132
135
  else
133
136
  s.add_dependency(%q<activesupport>, [">= 0"])
134
- s.add_dependency(%q<mongodb-mongo>, ["= 0.10.1"])
137
+ s.add_dependency(%q<mongodb-mongo>, ["= 0.11.1"])
135
138
  s.add_dependency(%q<jnunemaker-validatable>, ["= 1.7.2"])
136
139
  s.add_dependency(%q<mocha>, ["= 0.9.4"])
137
140
  s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
@@ -36,4 +36,18 @@ class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
36
36
  from_db.target_id.should be_nil
37
37
  from_db.target.should be_nil
38
38
  end
39
+
40
+ context "association id set but document not found" do
41
+ setup do
42
+ @status = Status.new
43
+ project = Project.new(:name => "mongomapper")
44
+ @status.target = project
45
+ @status.save.should be_true
46
+ project.destroy
47
+ end
48
+
49
+ should "return nil instead of raising error" do
50
+ @status.target.should be_nil
51
+ end
52
+ end
39
53
  end
@@ -32,4 +32,14 @@ class BelongsToProxyTest < Test::Unit::TestCase
32
32
  from_db.project = nil
33
33
  from_db.project.should be_nil
34
34
  end
35
+
36
+ context "association id set but document not found" do
37
+ setup do
38
+ @status = Status.new(:name => 'Foo', :project_id => '1234')
39
+ end
40
+
41
+ should "return nil instead of raising error" do
42
+ @status.project.should be_nil
43
+ end
44
+ end
35
45
  end