mongoid 2.3.3 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,7 +8,55 @@ For instructions on upgrading to newer versions, visit
8
8
  * Ranges can now be passed to #where criteria to create a $gte/$lte query under the
9
9
  covers. `Person.where(dob: start_date...end_date)`
10
10
 
11
- ## 2.3.3 \[ In Development \] \[ Branch: 2.3.0-stable \]
11
+ ## 2.3.4 \[ In Development \] \[ Branch: 2.3.0-stable \]
12
+
13
+ * \#1445 Prevent duplicate documents in the loaded array on the target
14
+ enumerable for relational associations.
15
+
16
+ * \#1442 When using create_ methods for has one relations, the appropriate
17
+ destructive methods now get called when replacing an existing document.
18
+
19
+ * \#1431 Enumerable context should add to the loaded array post yield, so
20
+ that methods like #any? that short circuit based on the value of the block
21
+ dont falsely have extra documents.
22
+
23
+ * \#1418 Documents being loaded from the database for revision purposes
24
+ no longer get placed in the identity map.
25
+
26
+ * \#1399 Allow conversion of strings to integers in foreign keys where the
27
+ id is defined as an int.
28
+
29
+ * \#1397 Don't add default sorting criteria on first if they sort criteria
30
+ already exists.
31
+
32
+ * \#1394 Fix exists? to work when count is greater than 1. (Nick Hoffman)
33
+
34
+ * \#1392 Return 0 on aggregation functions where field is nonexistant.
35
+
36
+ * \#1391 Uniqueness validation now works properly on embedded documents that are
37
+ using primary key definitions.
38
+
39
+ * \#1390 When _type field is lower case class camelize before constantizing.
40
+
41
+ * \#1383 Fix cast on read for serializable fields that are subclassed.
42
+
43
+ * \#1357 Delayed atomic sets from update_attributes on embedded documents
44
+ multiple levels deep now properly persist.
45
+
46
+ * \#1326 Ensure base document on HABTM gets its keys saved after saving a newly
47
+ build child document.
48
+
49
+ * \#1301 Don't overwrite base metadata on embedded in relations if already set.
50
+
51
+ * \#1221 HABTM with inverse nil is allowed again on embedded documents.
52
+
53
+ * \#1208 Don't auto-persist child documents via the setter when setting from
54
+ an embedded_in.
55
+
56
+ * \#791 Root document updates its timestamps when only embedded documents have
57
+ changed.
58
+
59
+ ## 2.3.3
12
60
 
13
61
  ### Resolved Issues
14
62
 
@@ -5,22 +5,21 @@ id:
5
5
  taken:
6
6
  telah digunakan
7
7
  callbacks:
8
- "Calling %{method} on %{klass} resulted in a false return from a callback."
8
+ "Memanggil %{method} dalam %{klass} me-return false return dari salah satu callback."
9
9
  document_not_found:
10
10
  Dokumen tidak ditemukan untuk kelas %{klass} dengan id %{identifiers}.
11
11
  eager_load:
12
- "Eager loading :%{name} is not supported due to it being a many-to-many
13
- or polymorphic belongs_to relation."
12
+ "Eager loading : %{name} is tidak di-support karena merupakan relasi many-to-many
13
+ atau polymorphic belongs_to."
14
14
  invalid_time:
15
- "'%{value}' is not a valid Time."
15
+ "'%{value}' bukan merupakan Time yang valid."
16
16
  invalid_database:
17
17
  Database harus Mongo::DB, bukan %{name}.
18
18
  invalid_type:
19
19
  Field didefinisikan sebagai %{klass}, tetapi menerima %{other} dengan
20
20
  value %{value}.
21
21
  invalid_options:
22
- "Invalid option :%{invalid} provided to relation :%{name}. Valid options
23
- are: %{valid}."
22
+ "Opsi invalid : %{invalid} untuk relasi : %{name}. Opsi yang valid adalah : %{valid}."
24
23
  unsupported_version:
25
24
  MongoDB %{version} tidak di support, silakan upgrade
26
25
  ke %{mongo_version}.
@@ -242,7 +242,7 @@ module Mongoid #:nodoc:
242
242
  #
243
243
  # @return [ Numeric ] A numeric max value.
244
244
  def max(field)
245
- grouped(:max, field.to_s, Javascript.max)
245
+ grouped(:max, field.to_s, Javascript.max, Javascript.max_finalize)
246
246
  end
247
247
 
248
248
  # Return the min value for a field.
@@ -259,7 +259,7 @@ module Mongoid #:nodoc:
259
259
  #
260
260
  # @return [ Numeric ] A numeric minimum value.
261
261
  def min(field)
262
- grouped(:min, field.to_s, Javascript.min)
262
+ grouped(:min, field.to_s, Javascript.min, Javascript.min_finalize)
263
263
  end
264
264
 
265
265
  # Perform a pull on the matching documents.
@@ -306,7 +306,7 @@ module Mongoid #:nodoc:
306
306
  #
307
307
  # @return [ Numeric ] A numeric value that is the sum.
308
308
  def sum(field)
309
- grouped(:sum, field.to_s, Javascript.sum)
309
+ grouped(:sum, field.to_s, Javascript.sum, Javascript.sum_finalize)
310
310
  end
311
311
 
312
312
  # Very basic update that will perform a simple atomic $set of the
@@ -359,14 +359,14 @@ module Mongoid #:nodoc:
359
359
  # @param [ String ] reduce The reduce JS function.
360
360
  #
361
361
  # @return [ Numeric ] A numeric result.
362
- def grouped(start, field, reduce)
362
+ def grouped(start, field, reduce, finalize)
363
363
  collection = klass.collection.group(
364
364
  :cond => selector,
365
365
  :initial => { start => "start" },
366
+ :finalize => finalize,
366
367
  :reduce => reduce.gsub("[field]", field)
367
368
  )
368
- value = collection.empty? ? nil : collection.first[start.to_s]
369
- value && value.do_or_do_not(:nan?) ? nil : value
369
+ collection.empty? ? nil : collection.first[start.to_s]
370
370
  end
371
371
 
372
372
  # Get the options hash with the default sorting options provided.
@@ -379,9 +379,9 @@ module Mongoid #:nodoc:
379
379
  # @since 2.3.2
380
380
  def options_with_default_sorting
381
381
  process_options.tap do |opts|
382
- sorting = opts[:sort] ? opts[:sort].dup : []
383
- sorting << [:_id, :asc]
384
- opts[:sort] = sorting
382
+ if opts[:sort].blank?
383
+ opts[:sort] = [[ :_id, :asc ]]
384
+ end
385
385
  end
386
386
  end
387
387
 
@@ -242,7 +242,7 @@ module Mongoid #:nodoc:
242
242
  allocate.tap do |doc|
243
243
  doc.instance_variable_set(:@attributes, attributes)
244
244
  doc.send(:apply_defaults)
245
- IdentityMap.set(doc)
245
+ IdentityMap.set(doc) unless _loading_revision?
246
246
  doc.run_callbacks(:initialize) { doc }
247
247
  end
248
248
  end
@@ -22,7 +22,7 @@ module Mongoid #:nodoc:
22
22
  # BSON::ObjectId.convert(Person, { :_id => "4c52c439931a90ab29000003" })
23
23
  #
24
24
  # @param [ Class ] klass The class to convert the ids for.
25
- # @param [ Object, Array, Hash ] args The object to convert.
25
+ # @param [ Object, Array, Hash ] object The object to convert.
26
26
  #
27
27
  # @raise BSON::InvalidObjectId If using object ids and passed bad
28
28
  # strings.
@@ -30,28 +30,28 @@ module Mongoid #:nodoc:
30
30
  # @return [ BSON::ObjectId, Array, Hash ] The converted object ids.
31
31
  #
32
32
  # @since 2.0.0.rc.7
33
- def convert(klass, args, reject_blank = true)
34
- return args if args.is_a?(BSON::ObjectId) || !klass.using_object_ids?
35
- case args
33
+ def convert(klass, object, reject_blank = true)
34
+ return object if object.is_a?(BSON::ObjectId) || !klass.using_object_ids?
35
+ case object
36
36
  when ::String
37
- return nil if args.blank?
38
- if args.unconvertable_to_bson?
39
- args
37
+ return nil if object.blank?
38
+ if object.unconvertable_to_bson?
39
+ object
40
40
  else
41
- BSON::ObjectId.legal?(args) ? BSON::ObjectId.from_string(args) : args
41
+ BSON::ObjectId.legal?(object) ? BSON::ObjectId.from_string(object) : object
42
42
  end
43
43
  when ::Array
44
- args.delete_if { |arg| arg.blank? } if reject_blank
45
- args.replace(args.map { |arg| convert(klass, arg, reject_blank) })
44
+ object.delete_if { |arg| arg.blank? } if reject_blank
45
+ object.replace(object.map { |arg| convert(klass, arg, reject_blank) })
46
46
  when ::Hash
47
- args.tap do |hash|
47
+ object.tap do |hash|
48
48
  hash.each_pair do |key, value|
49
49
  next unless klass.object_id_field?(key)
50
50
  hash[key] = convert(klass, value, reject_blank)
51
51
  end
52
52
  end
53
53
  else
54
- args
54
+ object
55
55
  end
56
56
  end
57
57
  end
@@ -36,7 +36,11 @@ module Mongoid #:nodoc:
36
36
  # @return [ Document ] The instantiated document.
37
37
  def from_db(klass, attributes = {})
38
38
  type = attributes["_type"]
39
- type.blank? ? klass.instantiate(attributes) : type.constantize.instantiate(attributes)
39
+ if type.blank?
40
+ klass.instantiate(attributes)
41
+ else
42
+ type.camelize.constantize.instantiate(attributes)
43
+ end
40
44
  end
41
45
  end
42
46
  end
@@ -30,28 +30,13 @@ module Mongoid #:nodoc:
30
30
  unless method_defined?(:default)
31
31
  alias :default :default_val
32
32
  end
33
+
34
+ class_attribute :cast_on_read
33
35
  end
34
36
 
35
37
  # Set readers for the instance variables.
36
38
  attr_accessor :default_val, :label, :localize, :name, :options
37
39
 
38
- # When reading the field do we need to cast the value? This holds true when
39
- # times are stored or for big decimals which are stored as strings.
40
- #
41
- # @example Typecast on a read?
42
- # field.cast_on_read?
43
- #
44
- # @return [ true, false ] If the field should be cast.
45
- #
46
- # @since 2.1.0
47
- def cast_on_read?
48
- return @cast_on_read if defined?(@cast_on_read)
49
- @cast_on_read =
50
- self.class.public_instance_methods(false).map do |m|
51
- m.to_sym
52
- end.include?(:deserialize)
53
- end
54
-
55
40
  # Get the constraint from the metadata once.
56
41
  #
57
42
  # @example Get the constraint.
@@ -195,6 +180,21 @@ module Mongoid #:nodoc:
195
180
  end
196
181
  end
197
182
  end
183
+
184
+ private
185
+
186
+ # If we define a method called deserialize then we need to cast on
187
+ # read.
188
+ #
189
+ # @example Hook into method added.
190
+ # method_added(:deserialize)
191
+ #
192
+ # @param [ Symbol ] method The method name.
193
+ #
194
+ # @since 2.3.4
195
+ def method_added(method)
196
+ self.cast_on_read = true if method == :deserialize
197
+ end
198
198
  end
199
199
  end
200
200
  end
@@ -33,7 +33,12 @@ module Mongoid #:nodoc:
33
33
  #
34
34
  # @since 2.1.0
35
35
  def serialize(object)
36
- object.blank? ? nil : constraint.convert(object)
36
+ return nil if object.blank?
37
+ if object_id_field?
38
+ constraint.convert(object)
39
+ else
40
+ metadata.klass.fields["_id"].serialize(object)
41
+ end
37
42
  end
38
43
  end
39
44
  end
@@ -6,6 +6,17 @@ module Mongoid #:nodoc:
6
6
  class Time
7
7
  include Serializable
8
8
  include Timekeeping
9
+
10
+ # When reading the field do we need to cast the value? This holds true when
11
+ # times are stored or for big decimals which are stored as strings.
12
+ #
13
+ # @example Typecast on a read?
14
+ # field.cast_on_read?
15
+ #
16
+ # @return [ true ] Date fields cast on read.
17
+ #
18
+ # @since 2.1.0
19
+ def cast_on_read?; true; end
9
20
  end
10
21
  end
11
22
  end
@@ -6,6 +6,17 @@ module Mongoid #:nodoc:
6
6
  class TimeWithZone
7
7
  include Serializable
8
8
  include Timekeeping
9
+
10
+ # When reading the field do we need to cast the value? This holds true when
11
+ # times are stored or for big decimals which are stored as strings.
12
+ #
13
+ # @example Typecast on a read?
14
+ # field.cast_on_read?
15
+ #
16
+ # @return [ true ] Date fields cast on read.
17
+ #
18
+ # @since 2.1.0
19
+ def cast_on_read?; true; end
9
20
  end
10
21
  end
11
22
  end
@@ -57,7 +57,7 @@ module Mongoid #:nodoc:
57
57
  #
58
58
  # @param [ Array ] args The conditions.
59
59
  def exists?(*args)
60
- find(:all, *args).limit(1).count == 1
60
+ find(:all, *args).count > 0
61
61
  end
62
62
 
63
63
  # Find a +Document+ in several different ways.
@@ -18,6 +18,14 @@ max:
18
18
  }
19
19
  }"
20
20
 
21
+ max_finalize:
22
+ "function(obj) {
23
+ if (obj.max == 'start' || isNaN(obj.max)) {
24
+ obj.max = 0;
25
+ }
26
+ return obj;
27
+ }"
28
+
21
29
  min:
22
30
  "function(obj, prev) {
23
31
  if (obj.[field] && prev.min == 'start') {
@@ -28,6 +36,14 @@ min:
28
36
  }
29
37
  }"
30
38
 
39
+ min_finalize:
40
+ "function(obj) {
41
+ if (obj.min == 'start' || isNaN(obj.min)) {
42
+ obj.min = 0;
43
+ }
44
+ return obj;
45
+ }"
46
+
31
47
  sum:
32
48
  "function(obj, prev) {
33
49
  if (prev.sum == 'start') {
@@ -37,3 +53,11 @@ sum:
37
53
  prev.sum += obj.[field];
38
54
  }
39
55
  }"
56
+
57
+ sum_finalize:
58
+ "function(obj) {
59
+ if (obj.sum == 'start' || isNaN(obj.sum)) {
60
+ obj.sum = 0;
61
+ }
62
+ return obj;
63
+ }"
@@ -42,6 +42,15 @@ module Mongoid #:nodoc:
42
42
  def persist
43
43
  prepare do
44
44
  unless updates.empty?
45
+ # @todo Durran: This is a temporary fix for #791 until we rewrite
46
+ # the dirty tracking to properly flag a document as changed if
47
+ # only embedded documents have changed.
48
+ if document.respond_to?(:updated_at)
49
+ if document.timestamping? && !document.updated_at_changed?
50
+ document.updated_at = Time.now
51
+ end
52
+ end
53
+
45
54
  collection.update(selector, updates, options)
46
55
  conflicts.each_pair do |key, value|
47
56
  collection.update(selector, { key => value }, options)
@@ -24,7 +24,7 @@ module Mongoid # :nodoc:
24
24
  #
25
25
  # @since 2.0.0.rc.1
26
26
  def bind
27
- base.metadata = metadata.inverse_metadata(target)
27
+ base.metadata = metadata.inverse_metadata(target) unless base.metadata
28
28
  base.parentize(target)
29
29
  unless _binding?
30
30
  _binding do
@@ -32,6 +32,23 @@ module Mongoid # :nodoc:
32
32
  module Builders
33
33
  extend ActiveSupport::Concern
34
34
 
35
+ private
36
+
37
+ # Parse out the attributes and the options from the args passed to a
38
+ # build_ or create_ methods.
39
+ #
40
+ # @example Parse the args.
41
+ # doc.parse_args(:name => "Joe")
42
+ #
43
+ # @param [ Array ] args The arguments.
44
+ #
45
+ # @return [ Array<Hash> ] The attributes and options.
46
+ #
47
+ # @since 2.3.4
48
+ def parse_args(*args)
49
+ [ args.first || {}, args.size > 1 ? args[1] : {} ]
50
+ end
51
+
35
52
  module ClassMethods #:nodoc:
36
53
 
37
54
  # Defines a builder method for an embeds_one relation. This is
@@ -48,8 +65,7 @@ module Mongoid # :nodoc:
48
65
  def builder(name, metadata)
49
66
  tap do
50
67
  define_method("build_#{name}") do |*args|
51
- attributes = args.first || {}
52
- options = args.size > 1 ? args[1] : {}
68
+ attributes, options = parse_args(*args)
53
69
  document = Factory.build(metadata.klass, attributes, options)
54
70
  _building do
55
71
  send("#{name}=", document)
@@ -70,10 +86,12 @@ module Mongoid # :nodoc:
70
86
  # @return [ Class ] The class being set up.
71
87
  #
72
88
  # @since 2.0.0.rc.1
73
- def creator(name)
89
+ def creator(name, metadata)
74
90
  tap do
75
91
  define_method("create_#{name}") do |*args|
76
- send("build_#{name}", *args).tap { |doc| doc.save }
92
+ attributes, options = parse_args(*args)
93
+ document = Factory.build(metadata.klass, attributes, options)
94
+ send("#{name}=", document).tap { |doc| doc.save }
77
95
  end
78
96
  end
79
97
  end
@@ -22,7 +22,6 @@ module Mongoid # :nodoc:
22
22
  init(base, target, metadata) do
23
23
  characterize_one(target)
24
24
  bind_one
25
- base.save if persistable?
26
25
  end
27
26
  end
28
27
 
@@ -103,7 +103,7 @@ module Mongoid # :nodoc:
103
103
  def embeds_one(name, options = {}, &block)
104
104
  characterize(name, Embedded::One, options, &block).tap do |meta|
105
105
  relate(name, meta)
106
- builder(name, meta).creator(name)
106
+ builder(name, meta).creator(name, meta)
107
107
  validates_relation(meta)
108
108
  end
109
109
  end
@@ -219,7 +219,7 @@ module Mongoid # :nodoc:
219
219
  characterize(name, Referenced::One, options, &block).tap do |meta|
220
220
  relate(name, meta)
221
221
  reference(meta)
222
- builder(name, meta).creator(name).autosave(meta)
222
+ builder(name, meta).creator(name, meta).autosave(meta)
223
223
  validates_relation(meta)
224
224
  end
225
225
  end
@@ -75,6 +75,7 @@ module Mongoid # :nodoc:
75
75
  Factory.build(type || klass, attributes, options).tap do |doc|
76
76
  base.send(metadata.foreign_key).push(doc.id)
77
77
  append(doc)
78
+ doc.synced[metadata.inverse_foreign_key] = false
78
79
  yield(doc) if block_given?
79
80
  end
80
81
  end
@@ -151,8 +151,8 @@ module Mongoid #:nodoc:
151
151
  end
152
152
  else
153
153
  unloaded.each do |doc|
154
- loaded.push(added.delete_one(doc) || doc)
155
154
  yield(doc)
155
+ loaded.push(added.delete_one(doc) || loaded.delete_one(doc) || doc)
156
156
  end
157
157
  end
158
158
  added.each do |doc|
@@ -67,7 +67,7 @@ module Mongoid #:nodoc:
67
67
  new? &&
68
68
  embedded_many? &&
69
69
  _parent.persisted? &&
70
- !_parent.delayed_atomic_sets[atomic_path]
70
+ !_parent.delayed_atomic_sets[metadata.name.to_s]
71
71
  end
72
72
 
73
73
  # Determine if the document can be set.
@@ -56,7 +56,7 @@ module Mongoid #:nodoc:
56
56
  create_stack.push(true)
57
57
  end
58
58
 
59
- # Begins a creating block.
59
+ # Begins a loading block.
60
60
  #
61
61
  # @example Begin the load.
62
62
  # Threaded.begin_load
@@ -68,6 +68,18 @@ module Mongoid #:nodoc:
68
68
  load_stack.push(true)
69
69
  end
70
70
 
71
+ # Begins a loading revision block.
72
+ #
73
+ # @example Begin the revision load.
74
+ # Threaded.begin_load_revision
75
+ #
76
+ # @return [ true ] Always true.
77
+ #
78
+ # @since 2.3.4
79
+ def begin_load_revision
80
+ load_revision_stack.push(true)
81
+ end
82
+
71
83
  # Begin validating a document on the current thread.
72
84
  #
73
85
  # @example Begin validation.
@@ -128,18 +140,30 @@ module Mongoid #:nodoc:
128
140
  !create_stack.empty?
129
141
  end
130
142
 
131
- # Is the current thread in creating mode?
143
+ # Is the current thread in loading mode?
132
144
  #
133
- # @example Is the thread in creating mode?
134
- # Threaded.creating?
145
+ # @example Is the thread in loading mode?
146
+ # Threaded.loading?
135
147
  #
136
- # @return [ true, false ] If the thread is in creating mode?
148
+ # @return [ true, false ] If the thread is in loading mode?
137
149
  #
138
150
  # @since 2.3.2
139
151
  def loading?
140
152
  !load_stack.empty?
141
153
  end
142
154
 
155
+ # Is the current thread in revision load mode?
156
+ #
157
+ # @example Is the thread in revision load mode?
158
+ # Threaded.loading_revision?
159
+ #
160
+ # @return [ true, false ] If the thread is in revision load mode?
161
+ #
162
+ # @since 2.3.4
163
+ def loading_revision?
164
+ !load_revision_stack.empty?
165
+ end
166
+
143
167
  # Get the assign stack for the current thread. Is simply an array of calls
144
168
  # to Mongoid's assigning method.
145
169
  #
@@ -205,6 +229,19 @@ module Mongoid #:nodoc:
205
229
  Thread.current[:"[mongoid]:load-stack"] ||= []
206
230
  end
207
231
 
232
+ # Get the revision load stack for the current thread. Is simply an array
233
+ # of calls to Mongoid's loading_revision method.
234
+ #
235
+ # @example Get the revision load stack.
236
+ # Threaded.load_revision_stack
237
+ #
238
+ # @return [ Array ] The array of load revision calls.
239
+ #
240
+ # @since 2.3.4
241
+ def load_revision_stack
242
+ Thread.current[:"[mongoid]:load-revision-stack"] ||= []
243
+ end
244
+
208
245
  # Clear out all the safety options set using the safely proxy.
209
246
  #
210
247
  # @example Clear out the options.
@@ -288,6 +325,18 @@ module Mongoid #:nodoc:
288
325
  load_stack.pop
289
326
  end
290
327
 
328
+ # Exit the revision loading block.
329
+ #
330
+ # @example Exit the revision loading block.
331
+ # Threaded.exit_load_revision
332
+ #
333
+ # @return [ true ] The last element in the stack.
334
+ #
335
+ # @since 2.3.4
336
+ def exit_load_revision
337
+ load_revision_stack.pop
338
+ end
339
+
291
340
  # Exit validating a document on the current thread.
292
341
  #
293
342
  # @example Exit validation.
@@ -139,6 +139,23 @@ module Mongoid #:nodoc:
139
139
  Threaded.loading?
140
140
  end
141
141
 
142
+ # Execute a block in loading revision mode.
143
+ #
144
+ # @example Execute in loading revision mode.
145
+ # _loading_revision do
146
+ # load_revision
147
+ # end
148
+ #
149
+ # @return [ Object ] The return value of the block.
150
+ #
151
+ # @since 2.3.4
152
+ def _loading_revision
153
+ Threaded.begin_load_revision
154
+ yield
155
+ ensure
156
+ Threaded.exit_load_revision
157
+ end
158
+
142
159
  module ClassMethods #:nodoc:
143
160
 
144
161
  # Execute a block in creating mode.
@@ -157,6 +174,18 @@ module Mongoid #:nodoc:
157
174
  ensure
158
175
  Threaded.exit_create
159
176
  end
177
+
178
+ # Is the current thread in loading revision mode?
179
+ #
180
+ # @example Is the current thread in loading revision mode?
181
+ # proxy._loading_revision?
182
+ #
183
+ # @return [ true, false ] If the thread is loading a revision.
184
+ #
185
+ # @since 2.3.4
186
+ def _loading_revision?
187
+ Threaded.loading_revision?
188
+ end
160
189
  end
161
190
  end
162
191
  end
@@ -19,7 +19,7 @@ module Mongoid #:nodoc:
19
19
  # @example Set the updated at time.
20
20
  # person.set_updated_at
21
21
  def set_updated_at
22
- self.updated_at = Time.now.utc unless self.updated_at_changed?
22
+ self.updated_at = Time.now.utc unless updated_at_changed?
23
23
  end
24
24
  end
25
25
  end
@@ -45,11 +45,17 @@ module Mongoid #:nodoc:
45
45
  return if skip_validation?(document)
46
46
  relation = document._parent.send(document.metadata.name)
47
47
  criteria = relation.where(criterion(document, attribute, value))
48
+ criteria = scope(criteria, document, attribute)
49
+ if document.primary_key == Array.wrap(attribute)
50
+ document.errors.add(attribute, :taken) if criteria.count > 1
51
+ else
52
+ document.errors.add(attribute, :taken) if criteria.exists?
53
+ end
48
54
  else
49
55
  criteria = klass.where(criterion(document, attribute, value))
56
+ criteria = scope(criteria, document, attribute)
57
+ document.errors.add(attribute, :taken) if criteria.exists?
50
58
  end
51
- criteria = scope(criteria, document, attribute)
52
- document.errors.add(attribute, :taken) if criteria.exists?
53
59
  end
54
60
 
55
61
  protected
@@ -80,7 +86,8 @@ module Mongoid #:nodoc:
80
86
  # @since 2.3.0
81
87
  def criterion(document, attribute, value)
82
88
  { attribute => filter(value) }.tap do |selector|
83
- if document.persisted? || document.embedded?
89
+ if document.persisted? ||
90
+ (document.embedded? && (document.primary_key != Array.wrap(attribute)))
84
91
  selector.merge!(:_id => { "$ne" => document.id })
85
92
  end
86
93
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
- VERSION = "2.3.3"
3
+ VERSION = "2.3.4"
4
4
  end
@@ -117,9 +117,11 @@ module Mongoid #:nodoc:
117
117
  #
118
118
  # @since 2.0.0
119
119
  def previous_revision
120
- self.class.
121
- where(:_id => id).
122
- any_of({ :version => version }, { :version => nil }).first
120
+ _loading_revision do
121
+ self.class.
122
+ where(:_id => id).
123
+ any_of({ :version => version }, { :version => nil }).first
124
+ end
123
125
  end
124
126
 
125
127
  # Is the document able to be revised? This is true if the document has
@@ -16,13 +16,15 @@ module Rails #:nodoc:
16
16
  # @since 2.1.0
17
17
  def create_indexes(pattern)
18
18
  Dir.glob(pattern).each do |file|
19
+ logger = Logger.new($stdout)
19
20
  begin
20
21
  model = determine_model(file)
21
22
  if model
22
23
  model.create_indexes
23
- Logger.new($stdout).info("Generated indexes for #{model}")
24
+ logger.info("Generated indexes for #{model}")
24
25
  end
25
26
  rescue => e
27
+ logger.error("ERROR: #{e.message}")
26
28
  end
27
29
  end
28
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.3
4
+ version: 2.3.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-31 00:00:00.000000000Z
12
+ date: 2011-11-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
16
- requirement: &70239778174840 !ruby/object:Gem::Requirement
16
+ requirement: &70174220762600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70239778174840
24
+ version_requirements: *70174220762600
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: tzinfo
27
- requirement: &70239778174200 !ruby/object:Gem::Requirement
27
+ requirement: &70174220760140 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.3.22
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70239778174200
35
+ version_requirements: *70174220760140
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: mongo
38
- requirement: &70239778173520 !ruby/object:Gem::Requirement
38
+ requirement: &70174220759060 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '1.3'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70239778173520
46
+ version_requirements: *70174220759060
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rdoc
49
- requirement: &70239778172400 !ruby/object:Gem::Requirement
49
+ requirement: &70174220792380 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 3.5.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70239778172400
57
+ version_requirements: *70174220792380
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: bson_ext
60
- requirement: &70239778171440 !ruby/object:Gem::Requirement
60
+ requirement: &70174220788760 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '1.3'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70239778171440
68
+ version_requirements: *70174220788760
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: mocha
71
- requirement: &70239778170600 !ruby/object:Gem::Requirement
71
+ requirement: &70174220786360 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.9.12
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70239778170600
79
+ version_requirements: *70174220786360
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rspec
82
- requirement: &70239778169700 !ruby/object:Gem::Requirement
82
+ requirement: &70174220785700 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '2.6'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70239778169700
90
+ version_requirements: *70174220785700
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: watchr
93
- requirement: &70239778168680 !ruby/object:Gem::Requirement
93
+ requirement: &70174220855580 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0.6'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70239778168680
101
+ version_requirements: *70174220855580
102
102
  description: Mongoid is an ODM (Object Document Mapper) Framework for MongoDB, written
103
103
  in Ruby.
104
104
  email:
@@ -393,7 +393,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
393
393
  version: '0'
394
394
  segments:
395
395
  - 0
396
- hash: 1966370546899582904
396
+ hash: 4304237674641660259
397
397
  required_rubygems_version: !ruby/object:Gem::Requirement
398
398
  none: false
399
399
  requirements:
@@ -402,7 +402,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
402
402
  version: 1.3.6
403
403
  requirements: []
404
404
  rubyforge_project: mongoid
405
- rubygems_version: 1.8.6
405
+ rubygems_version: 1.8.10
406
406
  signing_key:
407
407
  specification_version: 3
408
408
  summary: Elegant Persistance in Ruby for MongoDB.