ign-mongo_mapper 0.8.6.1
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.
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +7 -0
- data/bin/mmconsole +60 -0
- data/examples/attr_accessible.rb +22 -0
- data/examples/attr_protected.rb +22 -0
- data/examples/cache_key.rb +24 -0
- data/examples/custom_types.rb +24 -0
- data/examples/identity_map.rb +33 -0
- data/examples/identity_map/automatic.rb +8 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +41 -0
- data/examples/querying.rb +35 -0
- data/examples/safe.rb +43 -0
- data/examples/scopes.rb +52 -0
- data/examples/validating/embedded_docs.rb +29 -0
- data/lib/mongo_mapper.rb +83 -0
- data/lib/mongo_mapper/connection.rb +83 -0
- data/lib/mongo_mapper/document.rb +41 -0
- data/lib/mongo_mapper/embedded_document.rb +31 -0
- data/lib/mongo_mapper/exceptions.rb +27 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +27 -0
- data/lib/mongo_mapper/extensions/object_id.rb +30 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +29 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +15 -0
- data/lib/mongo_mapper/plugins/accessible.rb +44 -0
- data/lib/mongo_mapper/plugins/associations.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +124 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +29 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +40 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +151 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +109 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +41 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +243 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/descendants.rb +17 -0
- data/lib/mongo_mapper/plugins/dirty.rb +124 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +48 -0
- data/lib/mongo_mapper/plugins/equality.rb +17 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +12 -0
- data/lib/mongo_mapper/plugins/inspect.rb +15 -0
- data/lib/mongo_mapper/plugins/keys.rb +311 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +65 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +112 -0
- data/lib/mongo_mapper/plugins/pagination.rb +14 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +53 -0
- data/lib/mongo_mapper/plugins/querying.rb +176 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
- data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +32 -0
- data/lib/mongo_mapper/plugins/scopes.rb +21 -0
- data/lib/mongo_mapper/plugins/serialization.rb +76 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +15 -0
- data/lib/mongo_mapper/plugins/validations.rb +50 -0
- data/lib/mongo_mapper/support/descendant_appends.rb +45 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/rails/init.rb +15 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +117 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
- data/test/functional/associations/test_many_documents_proxy.rb +615 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +206 -0
- data/test/functional/test_accessible.rb +168 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +76 -0
- data/test/functional/test_callbacks.rb +151 -0
- data/test/functional/test_dirty.rb +163 -0
- data/test/functional/test_document.rb +272 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +210 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +42 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +416 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +175 -0
- data/test/functional/test_querying.rb +873 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +230 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_string_id_compatibility.rb +67 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_userstamps.rb +27 -0
- data/test/functional/test_validations.rb +342 -0
- data/test/models.rb +233 -0
- data/test/test_active_model_lint.rb +13 -0
- data/test/test_helper.rb +102 -0
- data/test/unit/associations/test_base.rb +212 -0
- data/test/unit/associations/test_proxy.rb +105 -0
- data/test/unit/serializers/test_json_serializer.rb +217 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +208 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +639 -0
- data/test/unit/test_extensions.rb +376 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +22 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +89 -0
- data/test/unit/test_mongo_mapper.rb +110 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/test_rails.rb +181 -0
- data/test/unit/test_rails_compatibility.rb +52 -0
- data/test/unit/test_serialization.rb +51 -0
- data/test/unit/test_time_zones.rb +39 -0
- data/test/unit/test_validations.rb +564 -0
- metadata +385 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Inspect
|
5
|
+
module InstanceMethods
|
6
|
+
def inspect
|
7
|
+
attributes_as_nice_string = key_names.sort.collect do |name|
|
8
|
+
"#{name}: #{self[name].inspect}"
|
9
|
+
end.join(", ")
|
10
|
+
"#<#{self.class} #{attributes_as_nice_string}>"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,311 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'mongo_mapper/plugins/keys/key'
|
3
|
+
|
4
|
+
module MongoMapper
|
5
|
+
module Plugins
|
6
|
+
module Keys
|
7
|
+
def self.configure(model)
|
8
|
+
model.key :_id, ObjectId
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def inherited(descendant)
|
13
|
+
descendant.instance_variable_set(:@keys, keys.dup)
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def keys
|
18
|
+
@keys ||= HashWithIndifferentAccess.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def key(*args)
|
22
|
+
Key.new(*args).tap do |key|
|
23
|
+
keys[key.name] = key
|
24
|
+
create_accessors_for(key)
|
25
|
+
create_key_in_descendants(*args)
|
26
|
+
create_indexes_for(key)
|
27
|
+
create_validations_for(key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def key?(key)
|
32
|
+
keys.keys.include?(key.to_s)
|
33
|
+
end
|
34
|
+
|
35
|
+
def using_object_id?
|
36
|
+
object_id_key?(:_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def object_id_keys
|
40
|
+
keys.keys.select { |key| keys[key].type == ObjectId }.map(&:to_sym)
|
41
|
+
end
|
42
|
+
|
43
|
+
def object_id_key?(name)
|
44
|
+
object_id_keys.include?(name.to_sym)
|
45
|
+
end
|
46
|
+
|
47
|
+
# API Private
|
48
|
+
def can_default_id?
|
49
|
+
keys['_id'].can_default_id?
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_mongo(instance)
|
53
|
+
return nil if instance.nil?
|
54
|
+
instance.to_mongo
|
55
|
+
end
|
56
|
+
|
57
|
+
def from_mongo(value)
|
58
|
+
return nil if value.nil?
|
59
|
+
value.is_a?(self) ? value : load(value)
|
60
|
+
end
|
61
|
+
|
62
|
+
# load is overridden in identity map to ensure same objects are loaded
|
63
|
+
def load(attrs)
|
64
|
+
return nil if attrs.nil?
|
65
|
+
begin
|
66
|
+
attrs['_type'].present? ? attrs['_type'].constantize : self
|
67
|
+
rescue NameError
|
68
|
+
self
|
69
|
+
end.allocate.initialize_from_database(attrs)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def key_accessors_module_defined?
|
74
|
+
if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
|
75
|
+
const_defined?('MongoMapperKeys')
|
76
|
+
else
|
77
|
+
const_defined?('MongoMapperKeys', false)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def accessors_module
|
82
|
+
if key_accessors_module_defined?
|
83
|
+
const_get 'MongoMapperKeys'
|
84
|
+
else
|
85
|
+
const_set 'MongoMapperKeys', Module.new
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_accessors_for(key)
|
90
|
+
accessors_module.module_eval <<-end_eval
|
91
|
+
def #{key.name}
|
92
|
+
read_key(:#{key.name})
|
93
|
+
end
|
94
|
+
|
95
|
+
def #{key.name}_before_typecast
|
96
|
+
read_key_before_typecast(:#{key.name})
|
97
|
+
end
|
98
|
+
|
99
|
+
def #{key.name}=(value)
|
100
|
+
write_key(:#{key.name}, value)
|
101
|
+
end
|
102
|
+
|
103
|
+
def #{key.name}?
|
104
|
+
read_key(:#{key.name}).present?
|
105
|
+
end
|
106
|
+
end_eval
|
107
|
+
|
108
|
+
include accessors_module
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_key_in_descendants(*args)
|
112
|
+
descendants.each { |descendant| descendant.key(*args) }
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_indexes_for(key)
|
116
|
+
ensure_index key.name if key.options[:index] && !key.embeddable?
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_validations_for(key)
|
120
|
+
attribute = key.name.to_sym
|
121
|
+
|
122
|
+
if key.options[:required]
|
123
|
+
validates_presence_of(attribute)
|
124
|
+
end
|
125
|
+
|
126
|
+
if key.options[:unique]
|
127
|
+
validates_uniqueness_of(attribute)
|
128
|
+
end
|
129
|
+
|
130
|
+
if key.options[:numeric]
|
131
|
+
number_options = key.type == Integer ? {:only_integer => true} : {}
|
132
|
+
validates_numericality_of(attribute, number_options)
|
133
|
+
end
|
134
|
+
|
135
|
+
if key.options[:format]
|
136
|
+
validates_format_of(attribute, :with => key.options[:format])
|
137
|
+
end
|
138
|
+
|
139
|
+
if key.options[:in]
|
140
|
+
validates_inclusion_of(attribute, :within => key.options[:in])
|
141
|
+
end
|
142
|
+
|
143
|
+
if key.options[:not_in]
|
144
|
+
validates_exclusion_of(attribute, :within => key.options[:not_in])
|
145
|
+
end
|
146
|
+
|
147
|
+
if key.options[:length]
|
148
|
+
length_options = case key.options[:length]
|
149
|
+
when Integer
|
150
|
+
{:minimum => 0, :maximum => key.options[:length]}
|
151
|
+
when Range
|
152
|
+
{:within => key.options[:length]}
|
153
|
+
when Hash
|
154
|
+
key.options[:length]
|
155
|
+
end
|
156
|
+
validates_length_of(attribute, length_options)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module InstanceMethods
|
162
|
+
def initialize(attrs={})
|
163
|
+
default_id_value(attrs)
|
164
|
+
@_new = true
|
165
|
+
assign(attrs)
|
166
|
+
end
|
167
|
+
|
168
|
+
def initialize_from_database(attrs={})
|
169
|
+
@_new = false
|
170
|
+
load_from_database(attrs)
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
def persisted?
|
175
|
+
!new? && !destroyed?
|
176
|
+
end
|
177
|
+
|
178
|
+
def attributes=(attrs)
|
179
|
+
return if attrs.blank?
|
180
|
+
|
181
|
+
attrs.each_pair do |key, value|
|
182
|
+
if respond_to?(:"#{key}=")
|
183
|
+
self.send(:"#{key}=", value)
|
184
|
+
else
|
185
|
+
self[key] = value
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def attributes
|
191
|
+
HashWithIndifferentAccess.new.tap do |attrs|
|
192
|
+
keys.each_pair do |name, key|
|
193
|
+
value = key.set(self[key.name])
|
194
|
+
attrs[name] = value
|
195
|
+
end
|
196
|
+
|
197
|
+
embedded_associations.each do |association|
|
198
|
+
if documents = instance_variable_get(association.ivar)
|
199
|
+
if association.one?
|
200
|
+
attrs[association.name] = documents.to_mongo
|
201
|
+
else
|
202
|
+
attrs[association.name] = documents.map { |document| document.to_mongo }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
alias :to_mongo :attributes
|
209
|
+
|
210
|
+
def assign(attrs={})
|
211
|
+
self.attributes = attrs
|
212
|
+
end
|
213
|
+
|
214
|
+
def update_attributes(attrs={})
|
215
|
+
assign(attrs)
|
216
|
+
save
|
217
|
+
end
|
218
|
+
|
219
|
+
def update_attributes!(attrs={})
|
220
|
+
assign(attrs)
|
221
|
+
save!
|
222
|
+
end
|
223
|
+
|
224
|
+
def id
|
225
|
+
_id
|
226
|
+
end
|
227
|
+
|
228
|
+
def id=(value)
|
229
|
+
if self.class.using_object_id?
|
230
|
+
value = ObjectId.to_mongo(value)
|
231
|
+
end
|
232
|
+
|
233
|
+
self[:_id] = value
|
234
|
+
end
|
235
|
+
|
236
|
+
def [](name)
|
237
|
+
read_key(name)
|
238
|
+
end
|
239
|
+
|
240
|
+
def []=(name, value)
|
241
|
+
ensure_key_exists(name)
|
242
|
+
write_key(name, value)
|
243
|
+
end
|
244
|
+
|
245
|
+
def keys
|
246
|
+
self.class.keys
|
247
|
+
end
|
248
|
+
|
249
|
+
def key_names
|
250
|
+
keys.keys
|
251
|
+
end
|
252
|
+
|
253
|
+
def non_embedded_keys
|
254
|
+
keys.values.select { |key| !key.embeddable? }
|
255
|
+
end
|
256
|
+
|
257
|
+
def embedded_keys
|
258
|
+
keys.values.select { |key| key.embeddable? }
|
259
|
+
end
|
260
|
+
|
261
|
+
def default_id_value(attrs={})
|
262
|
+
id_provided = !attrs.nil? && attrs.keys.map { |k| k.to_s }.detect { |k| k == 'id' || k == '_id' }
|
263
|
+
if !id_provided && self.class.can_default_id?
|
264
|
+
write_key :_id, BSON::ObjectId.new
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
private
|
269
|
+
def load_from_database(attrs)
|
270
|
+
return if attrs.blank?
|
271
|
+
attrs.each do |key, value|
|
272
|
+
if respond_to?(:"#{key}=") && !self.class.key?(key)
|
273
|
+
self.send(:"#{key}=", value)
|
274
|
+
else
|
275
|
+
self[key] = value
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def ensure_key_exists(name)
|
281
|
+
self.class.key(name) unless respond_to?("#{name}=")
|
282
|
+
end
|
283
|
+
|
284
|
+
def set_parent_document(key, value)
|
285
|
+
if key.embeddable? && value.is_a?(key.type)
|
286
|
+
value._parent_document = self
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def read_key(key_name)
|
291
|
+
if key = keys[key_name]
|
292
|
+
value = key.get(instance_variable_get(:"@#{key_name}"))
|
293
|
+
set_parent_document(key, value)
|
294
|
+
instance_variable_set(:"@#{key_name}", value)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def read_key_before_typecast(name)
|
299
|
+
instance_variable_get(:"@#{name}_before_typecast")
|
300
|
+
end
|
301
|
+
|
302
|
+
def write_key(name, value)
|
303
|
+
key = keys[name.to_s]
|
304
|
+
set_parent_document(key, value)
|
305
|
+
instance_variable_set :"@#{name}_before_typecast", value
|
306
|
+
instance_variable_set :"@#{name}", key.set(value)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Keys
|
5
|
+
class Key
|
6
|
+
attr_accessor :name, :type, :options, :default_value
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
options = args.extract_options!
|
10
|
+
@name, @type = args.shift.to_s, args.shift
|
11
|
+
self.options = (options || {}).symbolize_keys
|
12
|
+
self.default_value = self.options[:default]
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
@name == other.name && @type == other.type
|
17
|
+
end
|
18
|
+
|
19
|
+
def embeddable?
|
20
|
+
return false unless type.respond_to?(:embeddable?)
|
21
|
+
type.embeddable?
|
22
|
+
end
|
23
|
+
|
24
|
+
def can_default_id?
|
25
|
+
type && [ObjectId, BSON::ObjectId, String].include?(type)
|
26
|
+
end
|
27
|
+
|
28
|
+
def number?
|
29
|
+
[Integer, Float].include?(type)
|
30
|
+
end
|
31
|
+
|
32
|
+
def get(value)
|
33
|
+
if value.nil? && !default_value.nil?
|
34
|
+
if default_value.respond_to?(:call)
|
35
|
+
return default_value.call
|
36
|
+
else
|
37
|
+
# Using Marshal is easiest way to get a copy of mutable objects
|
38
|
+
# without getting an error on immutable objects
|
39
|
+
return Marshal.load(Marshal.dump(default_value))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if options[:typecast].present?
|
44
|
+
type.from_mongo(value).map! { |v| typecast_class.from_mongo(v) }
|
45
|
+
else
|
46
|
+
type.from_mongo(value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def set(value)
|
51
|
+
type.to_mongo(value).tap do |values|
|
52
|
+
if options[:typecast].present?
|
53
|
+
values.map! { |v| typecast_class.to_mongo(v) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def typecast_class
|
60
|
+
@typecast_class ||= options[:typecast].constantize
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Modifiers
|
5
|
+
module ClassMethods
|
6
|
+
def increment(*args)
|
7
|
+
modifier_update('$inc', args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def decrement(*args)
|
11
|
+
criteria, keys = criteria_and_keys_from_args(args)
|
12
|
+
values, to_decrement = keys.values, {}
|
13
|
+
keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
|
14
|
+
collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(*args)
|
18
|
+
criteria, updates = criteria_and_keys_from_args(args)
|
19
|
+
updates.each do |key, value|
|
20
|
+
updates[key] = keys[key].set(value) if key?(key)
|
21
|
+
end
|
22
|
+
collection.update(criteria, {'$set' => updates}, :multi => true)
|
23
|
+
end
|
24
|
+
|
25
|
+
def unset(*args)
|
26
|
+
if args[0].is_a?(Hash)
|
27
|
+
criteria, keys = args.shift, args
|
28
|
+
else
|
29
|
+
keys, ids = args.partition { |arg| arg.is_a?(Symbol) }
|
30
|
+
criteria = {:id => ids}
|
31
|
+
end
|
32
|
+
|
33
|
+
criteria = criteria_hash(criteria).to_hash
|
34
|
+
modifiers = keys.inject({}) { |hash, key| hash[key] = 1; hash }
|
35
|
+
collection.update(criteria, {'$unset' => modifiers}, :multi => true)
|
36
|
+
end
|
37
|
+
|
38
|
+
def push(*args)
|
39
|
+
modifier_update('$push', args)
|
40
|
+
end
|
41
|
+
|
42
|
+
def push_all(*args)
|
43
|
+
modifier_update('$pushAll', args)
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_to_set(*args)
|
47
|
+
modifier_update('$addToSet', args)
|
48
|
+
end
|
49
|
+
alias push_uniq add_to_set
|
50
|
+
|
51
|
+
def pull(*args)
|
52
|
+
modifier_update('$pull', args)
|
53
|
+
end
|
54
|
+
|
55
|
+
def pull_all(*args)
|
56
|
+
modifier_update('$pullAll', args)
|
57
|
+
end
|
58
|
+
|
59
|
+
def pop(*args)
|
60
|
+
modifier_update('$pop', args)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def modifier_update(modifier, args)
|
65
|
+
criteria, updates = criteria_and_keys_from_args(args)
|
66
|
+
collection.update(criteria, {modifier => updates}, :multi => true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def criteria_and_keys_from_args(args)
|
70
|
+
keys = args.pop
|
71
|
+
criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
|
72
|
+
[criteria_hash(criteria).to_hash, keys]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module InstanceMethods
|
77
|
+
def unset(*keys)
|
78
|
+
self.class.unset(id, *keys)
|
79
|
+
end
|
80
|
+
|
81
|
+
def increment(hash)
|
82
|
+
self.class.increment(id, hash)
|
83
|
+
end
|
84
|
+
|
85
|
+
def decrement(hash)
|
86
|
+
self.class.decrement(id, hash)
|
87
|
+
end
|
88
|
+
|
89
|
+
def set(hash)
|
90
|
+
self.class.set(id, hash)
|
91
|
+
end
|
92
|
+
|
93
|
+
def push(hash)
|
94
|
+
self.class.push(id, hash)
|
95
|
+
end
|
96
|
+
|
97
|
+
def pull(hash)
|
98
|
+
self.class.pull(id, hash)
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_to_set(hash)
|
102
|
+
self.class.push_uniq(id, hash)
|
103
|
+
end
|
104
|
+
alias push_uniq add_to_set
|
105
|
+
|
106
|
+
def pop(hash)
|
107
|
+
self.class.pop(id, hash)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|