forked from mongomapper/mongomapper
/
modifiers.rb
134 lines (111 loc) · 3.77 KB
/
modifiers.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# encoding: UTF-8
module MongoMapper
module Plugins
module Modifiers
extend ActiveSupport::Concern
module ClassMethods
def increment(*args)
modifier_update('$inc', args)
end
def decrement(*args)
criteria, keys, options = criteria_and_keys_from_args(args)
values, to_decrement = keys.values, {}
keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
end
def set(*args)
criteria, updates, options = criteria_and_keys_from_args(args)
updates.each do |key, value|
updates[key] = keys[key.to_s].set(value) if key?(key)
end
modifier_update('$set', [criteria, updates, options])
end
def unset(*args)
if args[0].is_a?(Hash)
criteria, keys = args.shift, args
options = keys.last.is_a?(Hash) ? keys.pop : {}
else
keys, ids = args.partition { |arg| arg.is_a?(Symbol) }
options = ids.last.is_a?(Hash) ? ids.pop : {}
criteria = {:id => ids}
end
criteria = criteria_hash(criteria).to_hash
updates = keys.inject({}) { |hash, key| hash[key] = 1; hash }
modifier_update('$unset', [criteria, updates, options])
end
def push(*args)
modifier_update('$push', args)
end
def push_all(*args)
modifier_update('$pushAll', args)
end
def add_to_set(*args)
modifier_update('$addToSet', args)
end
alias push_uniq add_to_set
def pull(*args)
modifier_update('$pull', args)
end
def pull_all(*args)
modifier_update('$pullAll', args)
end
def pop(*args)
modifier_update('$pop', args)
end
private
def modifier_update(modifier, args)
criteria, updates, options = criteria_and_keys_from_args(args)
if options
collection.update(criteria, {modifier => updates}, options.merge(:multi => true))
else
collection.update(criteria, {modifier => updates}, :multi => true)
end
end
def criteria_and_keys_from_args(args)
if args[0].is_a?(Hash)
criteria = args[0]
updates = args[1]
options = args[2]
else
split_args = args.partition{|a| a.is_a?(BSON::ObjectId)}
criteria = {:id => split_args[0]}
updates = split_args[1].first
options = split_args[1].last
end
[criteria_hash(criteria).to_hash, updates, options]
end
end
def unset(*args)
self.class.unset({:_id => id}, *args)
end
def increment(hash, options=nil)
self.class.increment({:_id => id}, hash, options)
end
def decrement(hash, options=nil)
self.class.decrement({:_id => id}, hash, options)
end
def set(hash, options=nil)
self.class.set({:_id => id}, hash, options)
end
def push(hash, options=nil)
self.class.push({:_id => id}, hash, options)
end
def push_all(hash, options=nil)
self.class.push_all({:_id => id}, hash, options)
end
def pull(hash, options=nil)
self.class.pull({:_id => id}, hash, options)
end
def pull_all(hash, options=nil)
self.class.pull_all({:_id => id}, hash, options)
end
def add_to_set(hash, options=nil)
self.class.push_uniq({:_id => id}, hash, options)
end
alias push_uniq add_to_set
def pop(hash, options=nil)
self.class.pop({:_id => id}, hash, options)
end
end
end
end