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.
Files changed (147) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +33 -0
  3. data/UPGRADES +7 -0
  4. data/bin/mmconsole +60 -0
  5. data/examples/attr_accessible.rb +22 -0
  6. data/examples/attr_protected.rb +22 -0
  7. data/examples/cache_key.rb +24 -0
  8. data/examples/custom_types.rb +24 -0
  9. data/examples/identity_map.rb +33 -0
  10. data/examples/identity_map/automatic.rb +8 -0
  11. data/examples/keys.rb +40 -0
  12. data/examples/modifiers/set.rb +25 -0
  13. data/examples/plugins.rb +41 -0
  14. data/examples/querying.rb +35 -0
  15. data/examples/safe.rb +43 -0
  16. data/examples/scopes.rb +52 -0
  17. data/examples/validating/embedded_docs.rb +29 -0
  18. data/lib/mongo_mapper.rb +83 -0
  19. data/lib/mongo_mapper/connection.rb +83 -0
  20. data/lib/mongo_mapper/document.rb +41 -0
  21. data/lib/mongo_mapper/embedded_document.rb +31 -0
  22. data/lib/mongo_mapper/exceptions.rb +27 -0
  23. data/lib/mongo_mapper/extensions/array.rb +19 -0
  24. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  25. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  26. data/lib/mongo_mapper/extensions/date.rb +25 -0
  27. data/lib/mongo_mapper/extensions/float.rb +14 -0
  28. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  29. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  30. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  31. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  32. data/lib/mongo_mapper/extensions/object.rb +27 -0
  33. data/lib/mongo_mapper/extensions/object_id.rb +30 -0
  34. data/lib/mongo_mapper/extensions/set.rb +20 -0
  35. data/lib/mongo_mapper/extensions/string.rb +18 -0
  36. data/lib/mongo_mapper/extensions/time.rb +29 -0
  37. data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
  38. data/lib/mongo_mapper/plugins.rb +15 -0
  39. data/lib/mongo_mapper/plugins/accessible.rb +44 -0
  40. data/lib/mongo_mapper/plugins/associations.rb +134 -0
  41. data/lib/mongo_mapper/plugins/associations/base.rb +124 -0
  42. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +29 -0
  43. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +24 -0
  44. data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
  45. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +40 -0
  46. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +151 -0
  47. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  48. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +109 -0
  49. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  50. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  51. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  52. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +41 -0
  53. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  54. data/lib/mongo_mapper/plugins/associations/proxy.rb +139 -0
  55. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  56. data/lib/mongo_mapper/plugins/callbacks.rb +243 -0
  57. data/lib/mongo_mapper/plugins/clone.rb +22 -0
  58. data/lib/mongo_mapper/plugins/descendants.rb +17 -0
  59. data/lib/mongo_mapper/plugins/dirty.rb +124 -0
  60. data/lib/mongo_mapper/plugins/document.rb +41 -0
  61. data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
  62. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  63. data/lib/mongo_mapper/plugins/embedded_document.rb +48 -0
  64. data/lib/mongo_mapper/plugins/equality.rb +17 -0
  65. data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
  66. data/lib/mongo_mapper/plugins/indexes.rb +12 -0
  67. data/lib/mongo_mapper/plugins/inspect.rb +15 -0
  68. data/lib/mongo_mapper/plugins/keys.rb +311 -0
  69. data/lib/mongo_mapper/plugins/keys/key.rb +65 -0
  70. data/lib/mongo_mapper/plugins/logger.rb +18 -0
  71. data/lib/mongo_mapper/plugins/modifiers.rb +112 -0
  72. data/lib/mongo_mapper/plugins/pagination.rb +14 -0
  73. data/lib/mongo_mapper/plugins/persistence.rb +69 -0
  74. data/lib/mongo_mapper/plugins/protected.rb +53 -0
  75. data/lib/mongo_mapper/plugins/querying.rb +176 -0
  76. data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
  77. data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
  78. data/lib/mongo_mapper/plugins/rails.rb +58 -0
  79. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  80. data/lib/mongo_mapper/plugins/sci.rb +32 -0
  81. data/lib/mongo_mapper/plugins/scopes.rb +21 -0
  82. data/lib/mongo_mapper/plugins/serialization.rb +76 -0
  83. data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
  84. data/lib/mongo_mapper/plugins/userstamps.rb +15 -0
  85. data/lib/mongo_mapper/plugins/validations.rb +50 -0
  86. data/lib/mongo_mapper/support/descendant_appends.rb +45 -0
  87. data/lib/mongo_mapper/version.rb +4 -0
  88. data/rails/init.rb +15 -0
  89. data/test/_NOTE_ON_TESTING +1 -0
  90. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
  91. data/test/functional/associations/test_belongs_to_proxy.rb +117 -0
  92. data/test/functional/associations/test_in_array_proxy.rb +349 -0
  93. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  94. data/test/functional/associations/test_many_documents_proxy.rb +615 -0
  95. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  96. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  97. data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
  98. data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
  99. data/test/functional/associations/test_one_proxy.rb +206 -0
  100. data/test/functional/test_accessible.rb +168 -0
  101. data/test/functional/test_associations.rb +46 -0
  102. data/test/functional/test_binary.rb +27 -0
  103. data/test/functional/test_caching.rb +76 -0
  104. data/test/functional/test_callbacks.rb +151 -0
  105. data/test/functional/test_dirty.rb +163 -0
  106. data/test/functional/test_document.rb +272 -0
  107. data/test/functional/test_dynamic_querying.rb +75 -0
  108. data/test/functional/test_embedded_document.rb +210 -0
  109. data/test/functional/test_identity_map.rb +513 -0
  110. data/test/functional/test_indexes.rb +42 -0
  111. data/test/functional/test_logger.rb +20 -0
  112. data/test/functional/test_modifiers.rb +416 -0
  113. data/test/functional/test_pagination.rb +91 -0
  114. data/test/functional/test_protected.rb +175 -0
  115. data/test/functional/test_querying.rb +873 -0
  116. data/test/functional/test_safe.rb +76 -0
  117. data/test/functional/test_sci.rb +230 -0
  118. data/test/functional/test_scopes.rb +171 -0
  119. data/test/functional/test_string_id_compatibility.rb +67 -0
  120. data/test/functional/test_timestamps.rb +62 -0
  121. data/test/functional/test_userstamps.rb +27 -0
  122. data/test/functional/test_validations.rb +342 -0
  123. data/test/models.rb +233 -0
  124. data/test/test_active_model_lint.rb +13 -0
  125. data/test/test_helper.rb +102 -0
  126. data/test/unit/associations/test_base.rb +212 -0
  127. data/test/unit/associations/test_proxy.rb +105 -0
  128. data/test/unit/serializers/test_json_serializer.rb +217 -0
  129. data/test/unit/test_clone.rb +69 -0
  130. data/test/unit/test_descendant_appends.rb +71 -0
  131. data/test/unit/test_document.rb +208 -0
  132. data/test/unit/test_dynamic_finder.rb +125 -0
  133. data/test/unit/test_embedded_document.rb +639 -0
  134. data/test/unit/test_extensions.rb +376 -0
  135. data/test/unit/test_identity_map_middleware.rb +34 -0
  136. data/test/unit/test_inspect.rb +22 -0
  137. data/test/unit/test_key.rb +205 -0
  138. data/test/unit/test_keys.rb +89 -0
  139. data/test/unit/test_mongo_mapper.rb +110 -0
  140. data/test/unit/test_pagination.rb +11 -0
  141. data/test/unit/test_plugins.rb +50 -0
  142. data/test/unit/test_rails.rb +181 -0
  143. data/test/unit/test_rails_compatibility.rb +52 -0
  144. data/test/unit/test_serialization.rb +51 -0
  145. data/test/unit/test_time_zones.rb +39 -0
  146. data/test/unit/test_validations.rb +564 -0
  147. metadata +385 -0
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Indexes
5
+ module ClassMethods
6
+ def ensure_index(spec, options={})
7
+ collection.create_index(spec, options)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -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,18 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Logger
5
+ module ClassMethods
6
+ def logger
7
+ MongoMapper.logger
8
+ end
9
+ end
10
+
11
+ module InstanceMethods
12
+ def logger
13
+ self.class.logger
14
+ end
15
+ end
16
+ end
17
+ end
18
+ 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