mongoid 4.0.0.alpha2 → 4.0.0.beta1

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/README.md +3 -3
  4. data/lib/config/locales/en.yml +13 -0
  5. data/lib/mongoid.rb +3 -1
  6. data/lib/mongoid/atomic.rb +1 -1
  7. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  8. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  9. data/lib/mongoid/attributes.rb +23 -1
  10. data/lib/mongoid/attributes/processing.rb +1 -1
  11. data/lib/mongoid/composable.rb +3 -2
  12. data/lib/mongoid/contextual/command.rb +0 -26
  13. data/lib/mongoid/contextual/geo_near.rb +1 -1
  14. data/lib/mongoid/contextual/mongo.rb +6 -29
  15. data/lib/mongoid/contextual/text_search.rb +3 -5
  16. data/lib/mongoid/criteria.rb +1 -1
  17. data/lib/mongoid/criteria/modifiable.rb +27 -7
  18. data/lib/mongoid/criteria/permission.rb +70 -0
  19. data/lib/mongoid/document.rb +5 -6
  20. data/lib/mongoid/errors.rb +2 -0
  21. data/lib/mongoid/errors/document_not_destroyed.rb +25 -0
  22. data/lib/mongoid/errors/readonly_document.rb +24 -0
  23. data/lib/mongoid/extensions/boolean.rb +1 -0
  24. data/lib/mongoid/extensions/hash.rb +1 -1
  25. data/lib/mongoid/factory.rb +5 -3
  26. data/lib/mongoid/fields.rb +32 -0
  27. data/lib/mongoid/fields/localized.rb +1 -1
  28. data/lib/mongoid/fields/standard.rb +1 -1
  29. data/lib/mongoid/findable.rb +1 -0
  30. data/lib/mongoid/interceptable.rb +11 -6
  31. data/lib/mongoid/log_subscriber.rb +34 -1
  32. data/lib/mongoid/persistable/deletable.rb +1 -0
  33. data/lib/mongoid/persistable/destroyable.rb +7 -2
  34. data/lib/mongoid/persistable/updatable.rb +27 -26
  35. data/lib/mongoid/query_cache.rb +246 -0
  36. data/lib/mongoid/railties/database.rake +4 -26
  37. data/lib/mongoid/relations.rb +8 -22
  38. data/lib/mongoid/relations/accessors.rb +0 -3
  39. data/lib/mongoid/relations/binding.rb +1 -1
  40. data/lib/mongoid/relations/bindings/embedded/in.rb +1 -1
  41. data/lib/mongoid/relations/eager.rb +5 -6
  42. data/lib/mongoid/relations/eager/base.rb +97 -5
  43. data/lib/mongoid/relations/eager/belongs_to.rb +1 -0
  44. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +16 -9
  45. data/lib/mongoid/relations/eager/has_many.rb +1 -0
  46. data/lib/mongoid/relations/eager/has_one.rb +1 -0
  47. data/lib/mongoid/relations/embedded/batchable.rb +1 -1
  48. data/lib/mongoid/relations/embedded/in.rb +4 -4
  49. data/lib/mongoid/relations/embedded/many.rb +7 -5
  50. data/lib/mongoid/relations/embedded/one.rb +1 -1
  51. data/lib/mongoid/relations/macros.rb +1 -0
  52. data/lib/mongoid/relations/marshalable.rb +3 -3
  53. data/lib/mongoid/relations/proxy.rb +12 -10
  54. data/lib/mongoid/relations/referenced/in.rb +2 -2
  55. data/lib/mongoid/relations/referenced/many.rb +9 -9
  56. data/lib/mongoid/relations/referenced/many_to_many.rb +7 -7
  57. data/lib/mongoid/relations/referenced/one.rb +4 -4
  58. data/lib/mongoid/{state.rb → stateful.rb} +13 -1
  59. data/lib/mongoid/tasks/database.rake +31 -0
  60. data/lib/mongoid/tasks/database.rb +107 -0
  61. data/lib/mongoid/threaded.rb +0 -47
  62. data/lib/mongoid/validatable/uniqueness.rb +4 -16
  63. data/lib/mongoid/version.rb +1 -1
  64. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +0 -3
  65. data/lib/rails/mongoid.rb +0 -124
  66. data/spec/app/models/edit.rb +5 -0
  67. data/spec/app/models/even.rb +7 -0
  68. data/spec/app/models/line_item.rb +1 -1
  69. data/spec/app/models/note.rb +2 -0
  70. data/spec/app/models/odd.rb +7 -0
  71. data/spec/app/models/record.rb +5 -0
  72. data/spec/app/models/wiki_page.rb +1 -1
  73. data/spec/mongoid/attributes_spec.rb +76 -1
  74. data/spec/mongoid/changeable_spec.rb +6 -2
  75. data/spec/mongoid/contextual/mongo_spec.rb +3 -1
  76. data/spec/mongoid/contextual/text_search_spec.rb +3 -1
  77. data/spec/mongoid/criteria/modifiable_spec.rb +192 -0
  78. data/spec/mongoid/criteria_spec.rb +6 -2
  79. data/spec/mongoid/errors/document_not_destroyed_spec.rb +33 -0
  80. data/spec/mongoid/errors/readonly_document_spec.rb +29 -0
  81. data/spec/mongoid/fields/localized_spec.rb +15 -0
  82. data/spec/mongoid/fields_spec.rb +88 -2
  83. data/spec/mongoid/log_subscriber_spec.rb +3 -3
  84. data/spec/mongoid/persistable/deletable_spec.rb +14 -1
  85. data/spec/mongoid/persistable/destroyable_spec.rb +45 -1
  86. data/spec/mongoid/persistable/savable_spec.rb +34 -5
  87. data/spec/mongoid/query_cache_spec.rb +197 -0
  88. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +2 -2
  89. data/spec/mongoid/relations/builders/referenced/many_spec.rb +1 -1
  90. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +11 -37
  91. data/spec/mongoid/relations/eager/has_one_spec.rb +1 -1
  92. data/spec/mongoid/relations/embedded/in_spec.rb +1 -1
  93. data/spec/mongoid/relations/embedded/many_spec.rb +10 -10
  94. data/spec/mongoid/relations/embedded/one_spec.rb +10 -2
  95. data/spec/mongoid/relations/referenced/in_spec.rb +1 -1
  96. data/spec/mongoid/relations/referenced/many_spec.rb +37 -2
  97. data/spec/mongoid/relations/touchable_spec.rb +20 -0
  98. data/spec/mongoid/{state_spec.rb → stateful_spec.rb} +26 -1
  99. data/spec/mongoid/tasks/database_rake_spec.rb +285 -0
  100. data/spec/mongoid/tasks/database_spec.rb +148 -0
  101. data/spec/mongoid/validatable/uniqueness_spec.rb +7 -0
  102. data/spec/rails/mongoid_spec.rb +0 -316
  103. data/spec/spec_helper.rb +1 -0
  104. metadata +30 -8
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ class Criteria
4
+ module Permission
5
+
6
+ [:all,
7
+ :all_in,
8
+ :and,
9
+ :all_of,
10
+ :between,
11
+ :elem_match,
12
+ :exists,
13
+ :gt,
14
+ :gte,
15
+ :in,
16
+ :any_in,
17
+ :lt,
18
+ :lte,
19
+ :max_distance,
20
+ :mod,
21
+ :ne,
22
+ :excludes,
23
+ :near,
24
+ :near_sphere,
25
+ :nin,
26
+ :not_in,
27
+ :nor,
28
+ :negating?,
29
+ :not,
30
+ :or,
31
+ :any_of,
32
+ :with_size,
33
+ :with_type,
34
+ :where,
35
+ :within_box,
36
+ :within_circle,
37
+ :within_polygon,
38
+ :within_spherical_circle
39
+ ].each do |method|
40
+ define_method(method) do |*criteria|
41
+ raise Errors::CriteriaNotPermitted.new(klass, method, criteria) unless should_permit?(criteria)
42
+ super(*criteria)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ # Ensure that the criteria are permitted.
49
+ #
50
+ # @example Ignoring ActionController::Parameters
51
+ # should_permit?({_id: ActionController::Parameters.new("$size" => 1)})
52
+ #
53
+ # @api private
54
+ #
55
+ # @param [ Object ] criteria
56
+ # @return [ Boolean ] if should permit
57
+ def should_permit?(criteria)
58
+ if criteria.respond_to?(:permitted?)
59
+ return criteria.permitted?
60
+ elsif criteria.respond_to?(:each)
61
+ criteria.each do |criterion|
62
+ return false unless should_permit?(criterion)
63
+ end
64
+ end
65
+
66
+ true
67
+ end
68
+ end
69
+ end
70
+ end
@@ -13,7 +13,6 @@ require "mongoid/equality"
13
13
  require "mongoid/criteria"
14
14
  require "mongoid/factory"
15
15
  require "mongoid/fields"
16
- require "mongoid/state"
17
16
  require "mongoid/timestamps"
18
17
  require "mongoid/composable"
19
18
 
@@ -25,7 +24,7 @@ module Mongoid
25
24
  extend ActiveSupport::Concern
26
25
  include Composable
27
26
 
28
- attr_accessor :criteria_instance_id
27
+ attr_accessor :__selected_fields
29
28
  attr_reader :new_record
30
29
 
31
30
  included do
@@ -301,16 +300,16 @@ module Mongoid
301
300
  # Person.instantiate(:title => "Sir", :age => 30)
302
301
  #
303
302
  # @param [ Hash ] attrs The hash of attributes to instantiate with.
304
- # @param [ Integer ] criteria_instance_id The criteria id that
305
- # instantiated the document.
303
+ # @param [ Integer ] selected_fields The selected fields from the
304
+ # criteria.
306
305
  #
307
306
  # @return [ Document ] A new document.
308
307
  #
309
308
  # @since 1.0.0
310
- def instantiate(attrs = nil, criteria_instance_id = nil)
309
+ def instantiate(attrs = nil, selected_fields = nil)
311
310
  attributes = attrs || {}
312
311
  doc = allocate
313
- doc.criteria_instance_id = criteria_instance_id
312
+ doc.__selected_fields = selected_fields
314
313
  doc.instance_variable_set(:@attributes, attributes)
315
314
  doc.apply_defaults
316
315
  yield(doc) if block_given?
@@ -2,6 +2,7 @@
2
2
  require "mongoid/errors/mongoid_error"
3
3
  require "mongoid/errors/ambiguous_relationship"
4
4
  require "mongoid/errors/callback"
5
+ require "mongoid/errors/document_not_destroyed"
5
6
  require "mongoid/errors/document_not_found"
6
7
  require "mongoid/errors/eager_load"
7
8
  require "mongoid/errors/invalid_collection"
@@ -32,6 +33,7 @@ require "mongoid/errors/no_sessions_config"
32
33
  require "mongoid/errors/no_session_database"
33
34
  require "mongoid/errors/no_session_hosts"
34
35
  require "mongoid/errors/readonly_attribute"
36
+ require "mongoid/errors/readonly_document"
35
37
  require "mongoid/errors/scope_overwrite"
36
38
  require "mongoid/errors/too_many_nested_attribute_records"
37
39
  require "mongoid/errors/unknown_attribute"
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Errors
4
+
5
+ # Raised when attempting to destroy a document that had destory callbacks
6
+ # return false.
7
+ #
8
+ # @since 4.0.0
9
+ class DocumentNotDestroyed < MongoidError
10
+
11
+ # Instnatiate the exception.
12
+ #
13
+ # @example Create the error.
14
+ # DocumentNotDestroyed.new(Band)
15
+ #
16
+ # @param [ Object ] id The document id.
17
+ # @param [ Class ] klass The document class.
18
+ #
19
+ # @since 4.0.0
20
+ def initialize(id, klass)
21
+ super(compose_message("document_not_destroyed", { id: id.inspect, klass: klass }))
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Errors
4
+
5
+ # Raised when attempting to persist a document that was loaded from the
6
+ # database with partial fields.
7
+ #
8
+ # @since 4.0.0
9
+ class ReadonlyDocument < MongoidError
10
+
11
+ # Instnatiate the exception.
12
+ #
13
+ # @example Create the error.
14
+ # ReadonlyDocument.new(Band)
15
+ #
16
+ # @param [ Class ] klass The document class.
17
+ #
18
+ # @since 4.0.0
19
+ def initialize(klass)
20
+ super(compose_message("readonly_document", { klass: klass }))
21
+ end
22
+ end
23
+ end
24
+ end
@@ -16,6 +16,7 @@ module Mongoid
16
16
  def mongoize(object)
17
17
  ::Boolean.evolve(object)
18
18
  end
19
+ alias :evolve :mongoize
19
20
  end
20
21
  end
21
22
  end
@@ -40,7 +40,7 @@ module Mongoid
40
40
  each_pair do |key, value|
41
41
  if key =~ /\$/
42
42
  value.each_pair do |_key, _value|
43
- value[_key] = mongoize_for(key, klass, _key, _value)
43
+ value[_key] = (key == "$rename") ? _value.to_s : mongoize_for(key, klass, _key, _value)
44
44
  end
45
45
  (consolidated[key] ||= {}).merge!(value)
46
46
  else
@@ -32,14 +32,16 @@ module Mongoid
32
32
  #
33
33
  # @param [ Class ] klass The class to instantiate from if _type is not present.
34
34
  # @param [ Hash ] attributes The document attributes.
35
+ # @param [ Array ] selected_fields If instantiated from a criteria using
36
+ # #only we give the document a list of the selected fields.
35
37
  #
36
38
  # @return [ Document ] The instantiated document.
37
- def from_db(klass, attributes = nil, criteria_instance_id = nil)
39
+ def from_db(klass, attributes = nil, selected_fields = nil)
38
40
  type = (attributes || {})["_type"]
39
41
  if type.blank?
40
- klass.instantiate(attributes, criteria_instance_id)
42
+ klass.instantiate(attributes, selected_fields)
41
43
  else
42
- type.camelize.constantize.instantiate(attributes, criteria_instance_id)
44
+ type.camelize.constantize.instantiate(attributes, selected_fields)
43
45
  end
44
46
  end
45
47
  end
@@ -10,6 +10,28 @@ module Mongoid
10
10
  module Fields
11
11
  extend ActiveSupport::Concern
12
12
 
13
+ # For fields defined with symbols use the correct class.
14
+ #
15
+ # @since 4.0.0
16
+ TYPE_MAPPINGS = {
17
+ array: Array,
18
+ big_decimal: BigDecimal,
19
+ binary: BSON::Binary,
20
+ boolean: Mongoid::Boolean,
21
+ date: Date,
22
+ date_time: DateTime,
23
+ float: Float,
24
+ hash: Hash,
25
+ integer: Integer,
26
+ object_id: BSON::ObjectId,
27
+ range: Range,
28
+ regexp: Regexp,
29
+ set: Set,
30
+ string: String,
31
+ symbol: Symbol,
32
+ time: Time
33
+ }.with_indifferent_access
34
+
13
35
  included do
14
36
  class_attribute :aliased_fields
15
37
  class_attribute :localized_fields
@@ -533,10 +555,20 @@ module Mongoid
533
555
 
534
556
  def field_for(name, options)
535
557
  opts = options.merge(klass: self)
558
+ type_mapping = TYPE_MAPPINGS[options[:type]]
559
+ opts[:type] = type_mapping || unmapped_type(options)
536
560
  return Fields::Localized.new(name, opts) if options[:localize]
537
561
  return Fields::ForeignKey.new(name, opts) if options[:identity]
538
562
  Fields::Standard.new(name, opts)
539
563
  end
564
+
565
+ def unmapped_type(options)
566
+ if "Boolean" == options[:type].to_s
567
+ Mongoid::Boolean
568
+ else
569
+ options[:type] || Object
570
+ end
571
+ end
540
572
  end
541
573
  end
542
574
  end
@@ -63,7 +63,7 @@ module Mongoid
63
63
  def lookup(object)
64
64
  locale = ::I18n.locale
65
65
  if ::I18n.respond_to?(:fallbacks)
66
- object[::I18n.fallbacks[locale].map(&:to_s).find{ |loc| object[loc] }]
66
+ object[::I18n.fallbacks[locale].map(&:to_s).find{ |loc| object.has_key?(loc) }]
67
67
  else
68
68
  object[locale.to_s]
69
69
  end
@@ -50,7 +50,7 @@ module Mongoid
50
50
  #
51
51
  # @since 2.1.8
52
52
  def eval_default(doc)
53
- if fields = Threaded.selection(doc.criteria_instance_id)
53
+ if fields = doc.__selected_fields
54
54
  evaluated_default(doc) if included?(fields)
55
55
  else
56
56
  evaluated_default(doc)
@@ -21,6 +21,7 @@ module Mongoid
21
21
  :extras,
22
22
  :find_and_modify,
23
23
  :find_or_create_by,
24
+ :find_or_create_by!,
24
25
  :find_or_initialize_by,
25
26
  :first_or_create,
26
27
  :first_or_create!,
@@ -125,7 +125,13 @@ module Mongoid
125
125
  # @since 2.3.0
126
126
  def run_callbacks(kind, *args, &block)
127
127
  cascadable_children(kind).each do |child|
128
- unless child.run_callbacks(child_callback_type(kind, child), *args)
128
+ # This is returning false for some destroy tests on 4.1.0.beta1,
129
+ # causing them to fail since 4.1.0 expects a block to be passed if the
130
+ # callbacks for the type are empty. If no block is passed then the nil
131
+ # return value gets interpreted as false and halts the chain.
132
+ #
133
+ # @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/callbacks.rb#L79
134
+ if child.run_callbacks(child_callback_type(kind, child), *args) == false
129
135
  return false
130
136
  end
131
137
  end
@@ -170,7 +176,7 @@ module Mongoid
170
176
  relation = send(name)
171
177
  Array.wrap(relation).each do |child|
172
178
  next if children.include?(child)
173
- children.add(child) if cascadable_child?(kind, child)
179
+ children.add(child) if cascadable_child?(kind, child, metadata)
174
180
  child.send(:cascadable_children, kind, children)
175
181
  end
176
182
  end
@@ -189,10 +195,9 @@ module Mongoid
189
195
  # @return [ true, false ] If the child should fire the callback.
190
196
  #
191
197
  # @since 2.3.0
192
- def cascadable_child?(kind, child)
193
- if kind == :initialize || kind == :find
194
- return false
195
- end
198
+ def cascadable_child?(kind, child, metadata)
199
+ return false if kind == :initialize || kind == :find
200
+ return false if kind == :validate && metadata.validate?
196
201
  child.callback_executable?(kind) ? child.in_callback_state?(kind) : false
197
202
  end
198
203
 
@@ -1,6 +1,13 @@
1
+ # encoding: utf-8
1
2
  module Mongoid
2
-
3
+ # A Log subscriber to the moped queries
4
+ #
5
+ # @since 4.0.0
3
6
  class LogSubscriber < ActiveSupport::LogSubscriber
7
+
8
+ # Log the query operation on moped
9
+ #
10
+ # @since 4.0.0
4
11
  def query(event)
5
12
  return unless logger.debug?
6
13
 
@@ -9,10 +16,35 @@ module Mongoid
9
16
  debug(payload[:prefix], payload[:ops], runtime)
10
17
  end
11
18
 
19
+ def query_cache(event)
20
+ return unless logger.debug?
21
+
22
+ database, collection, selector = event.payload[:key]
23
+ operation = "%-12s database=%s collection=%s selector=%s" % ["QUERY CACHE", database, collection, selector.inspect]
24
+ logger.debug operation
25
+ end
26
+ # Log the provided operations.
27
+ #
28
+ # @example Delegates the operation to moped so it can log it.
29
+ # subscriber.debug("MOPED", {}, 30)
30
+ #
31
+ # @param [ String ] prefix The prefix for all operations in the log.
32
+ # @param [ Array ] ops The operations.
33
+ # @param [ String ] runtime The runtime in formatted ms.
34
+ #
35
+ # @since 4.0.0
12
36
  def debug(prefix, operations, runtime)
13
37
  Moped::Loggable.log_operations(prefix, operations, runtime)
14
38
  end
15
39
 
40
+ # Get the logger.
41
+ #
42
+ # @example Get the logger.
43
+ # subscriber.logger
44
+ #
45
+ # @return [ Logger ] The logger.
46
+ #
47
+ # @since 4.0.0
16
48
  def logger
17
49
  Moped.logger
18
50
  end
@@ -20,3 +52,4 @@ module Mongoid
20
52
  end
21
53
 
22
54
  Mongoid::LogSubscriber.attach_to :moped
55
+ Mongoid::LogSubscriber.attach_to :mongoid
@@ -19,6 +19,7 @@ module Mongoid
19
19
  #
20
20
  # @since 1.0.0
21
21
  def delete(options = {})
22
+ raise Errors::ReadonlyDocument.new(self.class) if readonly?
22
23
  prepare_delete do
23
24
  if embedded?
24
25
  delete_as_embedded(options)
@@ -18,13 +18,18 @@ module Mongoid
18
18
  # @return [ true, false ] True if successful, false if not.
19
19
  #
20
20
  # @since 1.0.0
21
- def destroy(options = {})
21
+ def destroy(options = nil)
22
+ raise Errors::ReadonlyDocument.new(self.class) if readonly?
22
23
  self.flagged_for_destroy = true
23
- result = run_callbacks(:destroy) { delete(options) }
24
+ result = run_callbacks(:destroy) { delete(options || {}) }
24
25
  self.flagged_for_destroy = false
25
26
  result
26
27
  end
27
28
 
29
+ def destroy!(options = {})
30
+ destroy || raise(Errors::DocumentNotDestroyed.new(id, self.class))
31
+ end
32
+
28
33
  module ClassMethods
29
34
 
30
35
  # Delete all documents given the supplied conditions. If no conditions
@@ -8,32 +8,6 @@ module Mongoid
8
8
  # @since 4.0.0
9
9
  module Updatable
10
10
 
11
- # Update the document in the database.
12
- #
13
- # @example Update an existing document.
14
- # document.update
15
- #
16
- # @param [ Hash ] options Options to pass to update.
17
- #
18
- # @option options [ true, false ] :validate Whether or not to validate.
19
- #
20
- # @return [ true, false ] True if succeeded, false if not.
21
- #
22
- # @since 1.0.0
23
- def update_document(options = {})
24
- prepare_update(options) do
25
- updates, conflicts = init_atomic_updates
26
- unless updates.empty?
27
- coll = _root.collection
28
- selector = atomic_selector
29
- coll.find(selector).update(positionally(selector, updates))
30
- conflicts.each_pair do |key, value|
31
- coll.find(selector).update(positionally(selector, { key => value }))
32
- end
33
- end
34
- end
35
- end
36
-
37
11
  # Update a single attribute and persist the entire document.
38
12
  # This skips validation but fires the callbacks.
39
13
  #
@@ -146,6 +120,33 @@ module Mongoid
146
120
  end
147
121
  post_process_persist(result, options) and result
148
122
  end
123
+
124
+ # Update the document in the database.
125
+ #
126
+ # @example Update an existing document.
127
+ # document.update
128
+ #
129
+ # @param [ Hash ] options Options to pass to update.
130
+ #
131
+ # @option options [ true, false ] :validate Whether or not to validate.
132
+ #
133
+ # @return [ true, false ] True if succeeded, false if not.
134
+ #
135
+ # @since 1.0.0
136
+ def update_document(options = {})
137
+ raise Errors::ReadonlyDocument.new(self.class) if readonly?
138
+ prepare_update(options) do
139
+ updates, conflicts = init_atomic_updates
140
+ unless updates.empty?
141
+ coll = _root.collection
142
+ selector = atomic_selector
143
+ coll.find(selector).update(positionally(selector, updates))
144
+ conflicts.each_pair do |key, value|
145
+ coll.find(selector).update(positionally(selector, { key => value }))
146
+ end
147
+ end
148
+ end
149
+ end
149
150
  end
150
151
  end
151
152
  end