mongo_mapper 0.14.0 → 0.15.4

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 (120) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +72 -0
  4. data/examples/keys.rb +1 -1
  5. data/examples/modifiers/set.rb +1 -1
  6. data/examples/querying.rb +1 -1
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +19 -17
  10. data/lib/mongo_mapper/connection.rb +16 -38
  11. data/lib/mongo_mapper/extensions/array.rb +1 -1
  12. data/lib/mongo_mapper/extensions/binary.rb +1 -1
  13. data/lib/mongo_mapper/extensions/date.rb +1 -1
  14. data/lib/mongo_mapper/extensions/float.rb +1 -1
  15. data/lib/mongo_mapper/extensions/hash.rb +1 -1
  16. data/lib/mongo_mapper/extensions/nil_class.rb +2 -2
  17. data/lib/mongo_mapper/extensions/object.rb +1 -1
  18. data/lib/mongo_mapper/extensions/object_id.rb +6 -2
  19. data/lib/mongo_mapper/extensions/set.rb +1 -1
  20. data/lib/mongo_mapper/extensions/string.rb +1 -1
  21. data/lib/mongo_mapper/plugins/accessible.rb +1 -1
  22. data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
  23. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
  24. data/lib/mongo_mapper/plugins/associations/many_association.rb +6 -5
  25. data/lib/mongo_mapper/plugins/associations/{belongs_to_polymorphic_proxy.rb → proxy/belongs_to_polymorphic_proxy.rb} +0 -0
  26. data/lib/mongo_mapper/plugins/associations/{belongs_to_proxy.rb → proxy/belongs_to_proxy.rb} +6 -0
  27. data/lib/mongo_mapper/plugins/associations/proxy/collection.rb +55 -0
  28. data/lib/mongo_mapper/plugins/associations/{embedded_collection.rb → proxy/embedded_collection.rb} +0 -0
  29. data/lib/mongo_mapper/plugins/associations/{in_array_proxy.rb → proxy/in_array_proxy.rb} +36 -6
  30. data/lib/mongo_mapper/plugins/associations/proxy/in_foreign_array_proxy.rb +136 -0
  31. data/lib/mongo_mapper/plugins/associations/{many_documents_as_proxy.rb → proxy/many_documents_as_proxy.rb} +0 -0
  32. data/lib/mongo_mapper/plugins/associations/{many_documents_proxy.rb → proxy/many_documents_proxy.rb} +0 -4
  33. data/lib/mongo_mapper/plugins/associations/{many_embedded_polymorphic_proxy.rb → proxy/many_embedded_polymorphic_proxy.rb} +0 -0
  34. data/lib/mongo_mapper/plugins/associations/{many_embedded_proxy.rb → proxy/many_embedded_proxy.rb} +0 -0
  35. data/lib/mongo_mapper/plugins/associations/{many_polymorphic_proxy.rb → proxy/many_polymorphic_proxy.rb} +0 -0
  36. data/lib/mongo_mapper/plugins/associations/{one_as_proxy.rb → proxy/one_as_proxy.rb} +0 -0
  37. data/lib/mongo_mapper/plugins/associations/{one_embedded_polymorphic_proxy.rb → proxy/one_embedded_polymorphic_proxy.rb} +0 -0
  38. data/lib/mongo_mapper/plugins/associations/{one_embedded_proxy.rb → proxy/one_embedded_proxy.rb} +3 -1
  39. data/lib/mongo_mapper/plugins/associations/{one_proxy.rb → proxy/one_proxy.rb} +0 -0
  40. data/lib/mongo_mapper/plugins/associations/proxy/proxy.rb +164 -0
  41. data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -13
  42. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  43. data/lib/mongo_mapper/plugins/document.rb +1 -1
  44. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
  45. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
  46. data/lib/mongo_mapper/plugins/embedded_document.rb +2 -2
  47. data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
  48. data/lib/mongo_mapper/plugins/indexes.rb +13 -6
  49. data/lib/mongo_mapper/plugins/keys.rb +12 -7
  50. data/lib/mongo_mapper/plugins/keys/key.rb +21 -13
  51. data/lib/mongo_mapper/plugins/modifiers.rb +39 -14
  52. data/lib/mongo_mapper/plugins/persistence.rb +6 -2
  53. data/lib/mongo_mapper/plugins/querying.rb +9 -3
  54. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +6 -6
  55. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  56. data/lib/mongo_mapper/plugins/scopes.rb +19 -3
  57. data/lib/mongo_mapper/plugins/stats.rb +1 -3
  58. data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
  59. data/lib/mongo_mapper/plugins/validations.rb +1 -1
  60. data/lib/mongo_mapper/railtie.rb +1 -0
  61. data/lib/mongo_mapper/utils.rb +2 -2
  62. data/lib/mongo_mapper/version.rb +1 -1
  63. data/spec/examples.txt +1731 -0
  64. data/spec/functional/accessible_spec.rb +7 -1
  65. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
  66. data/spec/functional/associations/belongs_to_proxy_spec.rb +55 -5
  67. data/spec/functional/associations/in_array_proxy_spec.rb +149 -14
  68. data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
  69. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  70. data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
  71. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
  72. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  73. data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
  74. data/spec/functional/associations/one_embedded_proxy_spec.rb +28 -0
  75. data/spec/functional/associations/one_proxy_spec.rb +19 -9
  76. data/spec/functional/associations_spec.rb +3 -3
  77. data/spec/functional/binary_spec.rb +2 -2
  78. data/spec/functional/caching_spec.rb +15 -22
  79. data/spec/functional/callbacks_spec.rb +2 -2
  80. data/spec/functional/counter_cache_spec.rb +10 -10
  81. data/spec/functional/dirty_spec.rb +48 -10
  82. data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
  83. data/spec/functional/document_spec.rb +5 -8
  84. data/spec/functional/dumpable_spec.rb +1 -1
  85. data/spec/functional/embedded_document_spec.rb +5 -5
  86. data/spec/functional/identity_map_spec.rb +8 -8
  87. data/spec/functional/indexes_spec.rb +19 -18
  88. data/spec/functional/keys_spec.rb +64 -33
  89. data/spec/functional/logger_spec.rb +2 -2
  90. data/spec/functional/modifiers_spec.rb +81 -19
  91. data/spec/functional/partial_updates_spec.rb +8 -8
  92. data/spec/functional/protected_spec.rb +1 -1
  93. data/spec/functional/querying_spec.rb +70 -22
  94. data/spec/functional/safe_spec.rb +23 -27
  95. data/spec/functional/sci_spec.rb +7 -7
  96. data/spec/functional/scopes_spec.rb +89 -1
  97. data/spec/functional/static_keys_spec.rb +2 -2
  98. data/spec/functional/stats_spec.rb +28 -12
  99. data/spec/functional/strong_parameters_spec.rb +49 -0
  100. data/spec/functional/validations_spec.rb +8 -16
  101. data/spec/quality_spec.rb +1 -1
  102. data/spec/spec_helper.rb +39 -8
  103. data/spec/support/matchers.rb +1 -1
  104. data/spec/unit/associations/proxy_spec.rb +18 -10
  105. data/spec/unit/clone_spec.rb +1 -1
  106. data/spec/unit/document_spec.rb +3 -3
  107. data/spec/unit/embedded_document_spec.rb +4 -5
  108. data/spec/unit/extensions_spec.rb +12 -7
  109. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  110. data/spec/unit/inspect_spec.rb +1 -1
  111. data/spec/unit/key_spec.rb +23 -18
  112. data/spec/unit/keys_spec.rb +17 -8
  113. data/spec/unit/mongo_mapper_spec.rb +41 -88
  114. data/spec/unit/rails_spec.rb +2 -2
  115. data/spec/unit/validations_spec.rb +18 -18
  116. metadata +70 -38
  117. data/README.rdoc +0 -56
  118. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
  119. data/lib/mongo_mapper/plugins/associations/collection.rb +0 -29
  120. data/lib/mongo_mapper/plugins/associations/proxy.rb +0 -141
@@ -5,22 +5,14 @@ module MongoMapper
5
5
  class SingleAssociation < Base
6
6
  def setup(model)
7
7
  @model = model
8
- model.associations_module.module_eval <<-end_eval
8
+
9
+ model.associations_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
9
10
  def #{name}
10
- proxy = get_proxy(associations[#{name.inspect}])
11
- proxy.nil? ? nil : proxy
11
+ get_proxy(associations[#{name.inspect}]).read
12
12
  end
13
13
 
14
14
  def #{name}=(value)
15
- association = associations[#{name.inspect}]
16
- proxy = get_proxy(association)
17
-
18
- if proxy.nil? || proxy.target != value
19
- proxy = build_proxy(association)
20
- end
21
-
22
- proxy.replace(value)
23
- value
15
+ get_proxy(associations[#{name.inspect}]).write(value)
24
16
  end
25
17
 
26
18
  def #{name}?
@@ -43,4 +35,4 @@ module MongoMapper
43
35
  end
44
36
  end
45
37
  end
46
- end
38
+ end
@@ -3,58 +3,50 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Dirty
5
5
  extend ActiveSupport::Concern
6
-
7
6
  include ::ActiveModel::Dirty
8
7
 
9
- def initialize(*)
10
- # never register initial id assignment as a change
11
- # Chaining super into tap breaks implicit block passing in Ruby 1.8
12
- doc = super
13
- doc.tap { changed_attributes.delete('_id') }
14
- end
15
-
16
- def save(*)
17
- clear_changes { super }
18
- end
19
-
20
- def reload(*)
21
- doc = super
22
- doc.tap { clear_changes }
23
- end
24
-
25
- def clear_changes
26
- previous = changes
27
- (block_given? ? yield : true).tap do |result|
28
- unless result == false #failed validation; nil is OK.
29
- @previously_changed = previous
30
- changed_attributes.clear
8
+ module ClassMethods
9
+ def create_accessors_for(key)
10
+ super.tap do
11
+ define_attribute_methods([key.name])
31
12
  end
32
13
  end
33
14
  end
34
15
 
35
- protected
16
+ def save_to_collection(*)
17
+ super.tap do
18
+ changes_applied
19
+ end
20
+ end
36
21
 
37
- # We don't call super here to avoid invoking #attributes, which builds a whole new hash per call.
38
- def attribute_method?(attr_name)
39
- keys.key?(attr_name) || !embedded_associations.detect {|a| a.name == attr_name }.nil?
22
+ def reload!
23
+ super.tap do
24
+ clear_changes_information
25
+ end
40
26
  end
41
27
 
42
28
  private
43
29
 
44
- def write_key(key, value)
45
- key = unalias_key(key)
46
- if !keys.key?(key)
30
+ def write_key(key_name, value)
31
+ key_name = unalias_key(key_name)
32
+
33
+ if !keys.key?(key_name)
47
34
  super
48
35
  else
49
- attribute_will_change!(key) unless attribute_changed?(key)
50
- super.tap do
51
- changed_attributes.delete(key) unless attribute_value_changed?(key)
36
+ # find the MongoMapper::Plugins::Keys::Key
37
+ _, key = keys.detect { |n, v| n == key_name }
38
+
39
+ # typecast to the new value
40
+ old_value = read_key(key_name)
41
+ new_value = key.set(value)
42
+
43
+ # only mark changed if really changed value (after typecasting)
44
+ unless old_value == new_value
45
+ attribute_will_change!(key_name)
52
46
  end
53
- end
54
- end
55
47
 
56
- def attribute_value_changed?(key_name)
57
- changed_attributes[key_name] != read_key(key_name)
48
+ super
49
+ end
58
50
  end
59
51
  end
60
52
  end
@@ -19,7 +19,7 @@ module MongoMapper
19
19
  end
20
20
 
21
21
  def reload
22
- if doc = collection.find_one(:_id => id)
22
+ if doc = collection.find({:_id => id},{limit: -1}).first
23
23
  self.class.associations.each_value do |association|
24
24
  get_proxy(association).reset
25
25
  end
@@ -42,4 +42,4 @@ module MongoMapper
42
42
  end
43
43
  end
44
44
  end
45
- end
45
+ end
@@ -44,6 +44,7 @@ module MongoMapper
44
44
  definition.each do |prefix, suffixes|
45
45
  suffixes.each do |suffix|
46
46
  callback = "%s_%s" % [prefix, suffix]
47
+
47
48
  class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
48
49
  class << self
49
50
  alias_method :__original_#{callback}, :#{callback}
@@ -41,12 +41,12 @@ module MongoMapper
41
41
 
42
42
  def persist(options={})
43
43
  @_new = false
44
- clear_changes if respond_to?(:clear_changes)
44
+ changes_applied if respond_to?(:changes_applied)
45
45
  save_to_collection(options)
46
46
  end
47
47
 
48
48
  def _root_document
49
- @_root_document ||= _parent_document.try(:_root_document)
49
+ _parent_document.try(:_root_document)
50
50
  end
51
51
  end
52
52
  end
@@ -133,10 +133,12 @@ module PluckyMethods
133
133
  end
134
134
 
135
135
  def find_each(opts={})
136
+ return super if !block_given?
137
+
136
138
  query = clone.amend(opts)
137
139
  super(opts) do |doc|
138
140
  doc.remove_from_identity_map if doc && query.fields?
139
- yield doc if block_given?
141
+ yield doc
140
142
  end
141
143
  end
142
144
  end
@@ -6,19 +6,20 @@ module MongoMapper
6
6
 
7
7
  module ClassMethods
8
8
  def ensure_index(spec, options = {})
9
- collection.ensure_index dealias_options(spec), options
9
+ #TODO: should we emulate the mongo 1.x behaviour of caching attempts to create indexes?
10
+ collection.indexes.create_one dealias_options(spec), options
10
11
  end
11
12
 
12
13
  def create_index(spec, options = {})
13
- collection.create_index dealias_options(spec), options
14
+ collection.indexes.create_one dealias_options(spec), options
14
15
  end
15
16
 
16
17
  def drop_index(name)
17
- collection.drop_index name
18
+ collection.indexes.drop_one name
18
19
  end
19
20
 
20
21
  def drop_indexes
21
- collection.drop_indexes
22
+ collection.indexes.drop_all
22
23
  end
23
24
 
24
25
  private
@@ -26,11 +27,17 @@ module MongoMapper
26
27
  def dealias_options(options)
27
28
  case options
28
29
  when Symbol, String
29
- abbr(options)
30
+ {abbr(options) => 1}
30
31
  when Hash
31
32
  dealias_keys(options)
32
33
  when Array
33
- options.map {|o| dealias_options(o) }
34
+ if options.first.is_a?(Hash)
35
+ options.map {|o| dealias_options(o) }
36
+ elsif options.first.is_a?(Array) # [[:foo, 1], [:bar, 1]]
37
+ options.inject({}) {|acc, tuple| acc.merge(dealias_options(tuple))}
38
+ else
39
+ dealias_keys(Hash[*options])
40
+ end
34
41
  else
35
42
  options
36
43
  end
@@ -144,9 +144,8 @@ module MongoMapper
144
144
  end
145
145
 
146
146
  def create_accessors_for(key)
147
- accessors = ""
148
147
  if key.read_accessor?
149
- accessors << <<-end_eval
148
+ accessors_module.module_eval(<<-end_eval, __FILE__, __LINE__+1)
150
149
  def #{key.name}
151
150
  read_key(:#{key.name})
152
151
  end
@@ -158,7 +157,7 @@ module MongoMapper
158
157
  end
159
158
 
160
159
  if key.write_accessor?
161
- accessors << <<-end_eval
160
+ accessors_module.module_eval(<<-end_eval, __FILE__, __LINE__+1)
162
161
  def #{key.name}=(value)
163
162
  write_key(:#{key.name}, value)
164
163
  end
@@ -166,7 +165,7 @@ module MongoMapper
166
165
  end
167
166
 
168
167
  if key.predicate_accessor?
169
- accessors << <<-end_eval
168
+ accessors_module.module_eval(<<-end_eval, __FILE__, __LINE__+1)
170
169
  def #{key.name}?
171
170
  read_key(:#{key.name}).present?
172
171
  end
@@ -179,7 +178,6 @@ module MongoMapper
179
178
  end
180
179
  end
181
180
 
182
- accessors_module.module_eval accessors
183
181
  include accessors_module
184
182
  end
185
183
 
@@ -295,8 +293,16 @@ module MongoMapper
295
293
  end
296
294
  end
297
295
 
296
+ # NOTE: We can't use alias_method here as we need the #attributes=
297
+ # superclass method to get called (for example:
298
+ # MongoMapper::Plugins::Accessible filters non-permitted parameters
299
+ # through `attributes=`
300
+ def assign_attributes(new_attributes)
301
+ self.attributes = new_attributes
302
+ end
303
+
298
304
  def to_mongo(include_abbreviatons = true)
299
- BSON::OrderedHash.new.tap do |attrs|
305
+ Hash.new.tap do |attrs|
300
306
  self.class.unaliased_keys.each do |name, key|
301
307
  value = self.read_key(key.name)
302
308
  if key.type == ObjectId || !value.nil?
@@ -449,7 +455,6 @@ module MongoMapper
449
455
  else
450
456
  @_dynamic_attributes[key.name.to_sym] = as_typecast
451
457
  end
452
- @attributes = nil
453
458
  value
454
459
  end
455
460
 
@@ -3,10 +3,11 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Keys
5
5
  class Key
6
- attr_accessor :name, :type, :options, :default, :ivar, :abbr, :accessors
7
-
6
+ RESERVED_KEYS = %w( id class object_id attributes )
8
7
  ID_STR = '_id'
9
8
 
9
+ attr_accessor :name, :type, :options, :default, :ivar, :abbr, :accessors
10
+
10
11
  def initialize(*args)
11
12
  options_from_args = args.extract_options!
12
13
  @name, @type = args.shift.to_s, args.shift
@@ -60,32 +61,40 @@ module MongoMapper
60
61
  # Special Case: Generate default _id on access
61
62
  value = default_value if @is_id and !value
62
63
 
64
+ value = type ? type.from_mongo(value) : value
65
+
63
66
  if @typecast
64
- klass = typecast_class # Don't make this lookup on every call
65
- type.from_mongo(value).map { |v| klass.from_mongo(v) }
66
- else
67
- type.from_mongo(value)
67
+ klass = typecast_class # Don't make this lookup on every call
68
+ # typecast assumes array-ish object.
69
+ value = value.map { |v| klass.from_mongo(v) }
70
+ # recast it in the original type
71
+ value = type.from_mongo(value)
68
72
  end
73
+
74
+ value
69
75
  end
70
76
 
71
77
  def set(value)
72
78
  # Avoid tap here so we don't have to create a block binding.
73
- values = type.to_mongo(value)
79
+ value = type ? type.to_mongo(value) : value.to_mongo
80
+
74
81
  if @typecast
75
- values.map { |v| typecast_class.to_mongo(v) }
82
+ klass = typecast_class # Don't make this lookup on every call
83
+ value.map { |v| klass.to_mongo(v) }
76
84
  else
77
- values
85
+ value
78
86
  end
79
87
  end
80
88
 
81
89
  def default_value
82
90
  return unless default?
91
+
83
92
  if default.instance_of? Proc
84
- type.to_mongo default.call
93
+ default.call
85
94
  else
86
95
  # Using Marshal is easiest way to get a copy of mutable objects
87
96
  # without getting an error on immutable objects
88
- type.to_mongo Marshal.load(Marshal.dump(default))
97
+ Marshal.load(Marshal.dump(default))
89
98
  end
90
99
  end
91
100
 
@@ -93,7 +102,6 @@ module MongoMapper
93
102
  !!@name.match(/\A[a-z_][a-z0-9_]*\z/i)
94
103
  end
95
104
 
96
- RESERVED_KEYS = %w( id class object_id )
97
105
  def reserved_name?
98
106
  RESERVED_KEYS.include?(@name)
99
107
  end
@@ -124,7 +132,7 @@ module MongoMapper
124
132
 
125
133
  def validate_key_name!
126
134
  if reserved_name?
127
- raise MongoMapper::InvalidKey.new("`#{@name}` is a reserved key name (did you mean to use _id?)")
135
+ raise MongoMapper::InvalidKey.new("`#{@name}` is a reserved key name")
128
136
  elsif !valid_ruby_name?
129
137
  raise MongoMapper::InvalidKey.new("`#{@name}` is not a valid key name. Keys must match [a-z][a-z0-9_]*")
130
138
  end
@@ -13,7 +13,7 @@ module MongoMapper
13
13
  criteria, keys, options = criteria_and_keys_from_args(args)
14
14
  values, to_decrement = keys.values, {}
15
15
  keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
16
- collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
16
+ collection.update_many(criteria, {'$inc' => to_decrement}, options || {})
17
17
  end
18
18
 
19
19
  def set(*args)
@@ -44,7 +44,16 @@ module MongoMapper
44
44
  end
45
45
 
46
46
  def push_all(*args)
47
- modifier_update('$pushAll', args)
47
+ Kernel.warn "push_all no longer supported. use $push with $each"
48
+
49
+ hash = args.pop
50
+ ids = args
51
+
52
+ push_values = hash.inject({}) do |hsh, (key, values)|
53
+ { key => { '$each' => values } }
54
+ end
55
+
56
+ modifier_update('$addToSet', [ids, push_values].flatten)
48
57
  end
49
58
 
50
59
  def add_to_set(*args)
@@ -64,16 +73,18 @@ module MongoMapper
64
73
  modifier_update('$pop', args)
65
74
  end
66
75
 
67
- def find_and_modify(args)
68
- args[:query] = dealias_keys(args[:query]) if args.key? :query
69
- args[:update] = dealias_keys(args[:update]) if args.key? :update
70
- collection.find_and_modify(args)
76
+ def find_one_and_update(args)
77
+ args = args.dup
78
+ args[:query] = dealias_keys(args.delete :query) if args.key? :query
79
+ args[:update] = dealias_keys(args.delete :update) if args.key? :update
80
+ collection.find_one_and_update(args[:query], args[:update], args)
71
81
  end
82
+ alias_method :find_and_modify, :find_one_and_update
72
83
 
73
84
  def upsert(selector, updates, args = {})
74
85
  criteria = dealias_keys(selector)
75
86
  updates = dealias_keys(updates)
76
- collection.update(criteria, updates, args)
87
+ collection.update_one(criteria, updates, args.merge(upsert: true))
77
88
  end
78
89
 
79
90
  private
@@ -81,9 +92,9 @@ module MongoMapper
81
92
  def modifier_update(modifier, args)
82
93
  criteria, updates, options = criteria_and_keys_from_args(args)
83
94
  if options
84
- collection.update(criteria, {modifier => updates}, options.merge(:multi => true))
95
+ collection.update_many(criteria, {modifier => updates}, options)
85
96
  else
86
- collection.update(criteria, {modifier => updates}, :multi => true)
97
+ collection.update_many(criteria, {modifier => updates})
87
98
  end
88
99
  end
89
100
 
@@ -114,12 +125,12 @@ module MongoMapper
114
125
  self.class.unset({:_id => id}, *args)
115
126
  end
116
127
 
117
- def increment(hash, options=nil)
118
- self.class.increment({:_id => id}, hash, options)
128
+ def increment(args, options=nil)
129
+ self.class.increment({:_id => id}, _args_for_counter(args), options)
119
130
  end
120
131
 
121
- def decrement(hash, options=nil)
122
- self.class.decrement({:_id => id}, hash, options)
132
+ def decrement(args, options=nil)
133
+ self.class.decrement({:_id => id}, _args_for_counter(args), options)
123
134
  end
124
135
 
125
136
  def set(hash, options=nil)
@@ -131,7 +142,13 @@ module MongoMapper
131
142
  end
132
143
 
133
144
  def push_all(hash, options=nil)
134
- self.class.push_all({:_id => id}, hash, options)
145
+ Kernel.warn "push_all no longer supported. use $push with $each"
146
+
147
+ push_values = hash.inject({}) do |hsh, (key, values)|
148
+ { key => { '$each' => values } }
149
+ end
150
+
151
+ self.class.push({:_id => id}, push_values, options)
135
152
  end
136
153
 
137
154
  def pull(hash, options=nil)
@@ -150,6 +167,14 @@ module MongoMapper
150
167
  def pop(hash, options=nil)
151
168
  self.class.pop({:_id => id}, hash, options)
152
169
  end
170
+
171
+ private
172
+
173
+ def _args_for_counter(args)
174
+ args.kind_of?(String) || args.kind_of?(Symbol) ?
175
+ { args => 1 } :
176
+ args
177
+ end
153
178
  end
154
179
  end
155
180
  end