lookout-mongo_mapper 0.11.3

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 (176) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +33 -0
  3. data/UPGRADES +26 -0
  4. data/bin/mmconsole +59 -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 +2 -0
  11. data/examples/keys.rb +40 -0
  12. data/examples/modifiers/set.rb +25 -0
  13. data/examples/plugins.rb +38 -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 +94 -0
  19. data/lib/mongo_mapper/connection.rb +96 -0
  20. data/lib/mongo_mapper/document.rb +42 -0
  21. data/lib/mongo_mapper/embedded_document.rb +32 -0
  22. data/lib/mongo_mapper/exceptions.rb +30 -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 +26 -0
  33. data/lib/mongo_mapper/extensions/object_id.rb +32 -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 +28 -0
  37. data/lib/mongo_mapper/locale/en.yml +5 -0
  38. data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
  39. data/lib/mongo_mapper/plugins.rb +22 -0
  40. data/lib/mongo_mapper/plugins/accessible.rb +52 -0
  41. data/lib/mongo_mapper/plugins/active_model.rb +18 -0
  42. data/lib/mongo_mapper/plugins/associations.rb +90 -0
  43. data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
  44. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
  45. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
  46. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  47. data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
  48. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
  49. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
  50. data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
  51. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  52. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
  53. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  54. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  55. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  56. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
  57. data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
  58. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  59. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  60. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
  61. data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
  62. data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
  63. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  64. data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
  65. data/lib/mongo_mapper/plugins/clone.rb +22 -0
  66. data/lib/mongo_mapper/plugins/dirty.rb +60 -0
  67. data/lib/mongo_mapper/plugins/document.rb +41 -0
  68. data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
  69. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  70. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
  71. data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
  72. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  73. data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
  74. data/lib/mongo_mapper/plugins/indexes.rb +13 -0
  75. data/lib/mongo_mapper/plugins/inspect.rb +16 -0
  76. data/lib/mongo_mapper/plugins/keys.rb +313 -0
  77. data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
  78. data/lib/mongo_mapper/plugins/logger.rb +18 -0
  79. data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
  80. data/lib/mongo_mapper/plugins/pagination.rb +16 -0
  81. data/lib/mongo_mapper/plugins/persistence.rb +69 -0
  82. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  83. data/lib/mongo_mapper/plugins/querying.rb +165 -0
  84. data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
  85. data/lib/mongo_mapper/plugins/rails.rb +58 -0
  86. data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  87. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  88. data/lib/mongo_mapper/plugins/sci.rb +36 -0
  89. data/lib/mongo_mapper/plugins/scopes.rb +27 -0
  90. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  91. data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
  92. data/lib/mongo_mapper/plugins/touch.rb +18 -0
  93. data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
  94. data/lib/mongo_mapper/plugins/validations.rb +86 -0
  95. data/lib/mongo_mapper/railtie.rb +48 -0
  96. data/lib/mongo_mapper/railtie/database.rake +65 -0
  97. data/lib/mongo_mapper/translation.rb +10 -0
  98. data/lib/mongo_mapper/version.rb +4 -0
  99. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
  100. data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
  101. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
  102. data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
  103. data/test/_NOTE_ON_TESTING +1 -0
  104. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
  105. data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
  106. data/test/functional/associations/test_in_array_proxy.rb +349 -0
  107. data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
  108. data/test/functional/associations/test_many_documents_proxy.rb +866 -0
  109. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
  110. data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
  111. data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
  112. data/test/functional/associations/test_one_as_proxy.rb +491 -0
  113. data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
  114. data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
  115. data/test/functional/associations/test_one_proxy.rb +383 -0
  116. data/test/functional/test_accessible.rb +198 -0
  117. data/test/functional/test_associations.rb +46 -0
  118. data/test/functional/test_binary.rb +27 -0
  119. data/test/functional/test_caching.rb +77 -0
  120. data/test/functional/test_callbacks.rb +232 -0
  121. data/test/functional/test_dirty.rb +301 -0
  122. data/test/functional/test_document.rb +282 -0
  123. data/test/functional/test_dynamic_querying.rb +75 -0
  124. data/test/functional/test_embedded_document.rb +288 -0
  125. data/test/functional/test_equality.rb +20 -0
  126. data/test/functional/test_identity_map.rb +513 -0
  127. data/test/functional/test_indexes.rb +50 -0
  128. data/test/functional/test_logger.rb +20 -0
  129. data/test/functional/test_modifiers.rb +537 -0
  130. data/test/functional/test_pagination.rb +91 -0
  131. data/test/functional/test_protected.rb +201 -0
  132. data/test/functional/test_querying.rb +935 -0
  133. data/test/functional/test_safe.rb +76 -0
  134. data/test/functional/test_sci.rb +240 -0
  135. data/test/functional/test_scopes.rb +171 -0
  136. data/test/functional/test_timestamps.rb +62 -0
  137. data/test/functional/test_touch.rb +125 -0
  138. data/test/functional/test_userstamps.rb +44 -0
  139. data/test/functional/test_validations.rb +414 -0
  140. data/test/models.rb +261 -0
  141. data/test/support/railtie.rb +4 -0
  142. data/test/support/railtie/autoloaded.rb +2 -0
  143. data/test/support/railtie/not_autoloaded.rb +3 -0
  144. data/test/support/railtie/parent.rb +3 -0
  145. data/test/test_active_model_lint.rb +18 -0
  146. data/test/test_helper.rb +93 -0
  147. data/test/unit/associations/test_base.rb +146 -0
  148. data/test/unit/associations/test_belongs_to_association.rb +29 -0
  149. data/test/unit/associations/test_many_association.rb +63 -0
  150. data/test/unit/associations/test_one_association.rb +47 -0
  151. data/test/unit/associations/test_proxy.rb +100 -0
  152. data/test/unit/serializers/test_json_serializer.rb +216 -0
  153. data/test/unit/serializers/test_xml_serializer.rb +196 -0
  154. data/test/unit/test_clone.rb +69 -0
  155. data/test/unit/test_document.rb +249 -0
  156. data/test/unit/test_dynamic_finder.rb +125 -0
  157. data/test/unit/test_embedded_document.rb +682 -0
  158. data/test/unit/test_equality.rb +38 -0
  159. data/test/unit/test_exceptions.rb +12 -0
  160. data/test/unit/test_extensions.rb +380 -0
  161. data/test/unit/test_identity_map_middleware.rb +34 -0
  162. data/test/unit/test_inspect.rb +47 -0
  163. data/test/unit/test_key.rb +205 -0
  164. data/test/unit/test_keys.rb +65 -0
  165. data/test/unit/test_mongo_mapper.rb +143 -0
  166. data/test/unit/test_pagination.rb +11 -0
  167. data/test/unit/test_plugins.rb +89 -0
  168. data/test/unit/test_rails.rb +183 -0
  169. data/test/unit/test_rails_compatibility.rb +38 -0
  170. data/test/unit/test_rails_reflect_on_association.rb +118 -0
  171. data/test/unit/test_railtie.rb +66 -0
  172. data/test/unit/test_serialization.rb +166 -0
  173. data/test/unit/test_time_zones.rb +44 -0
  174. data/test/unit/test_translation.rb +27 -0
  175. data/test/unit/test_validations.rb +562 -0
  176. metadata +285 -0
@@ -0,0 +1,61 @@
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 number?
25
+ type == Integer || type == Float
26
+ end
27
+
28
+ def get(value)
29
+ if value.nil? && !default_value.nil?
30
+ if default_value.respond_to?(:call)
31
+ return default_value.call
32
+ else
33
+ # Using Marshal is easiest way to get a copy of mutable objects
34
+ # without getting an error on immutable objects
35
+ return Marshal.load(Marshal.dump(default_value))
36
+ end
37
+ end
38
+
39
+ if options[:typecast].present?
40
+ type.from_mongo(value).map! { |v| typecast_class.from_mongo(v) }
41
+ else
42
+ type.from_mongo(value)
43
+ end
44
+ end
45
+
46
+ def set(value)
47
+ type.to_mongo(value).tap do |values|
48
+ if options[:typecast].present?
49
+ values.map! { |v| typecast_class.to_mongo(v) }
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+ def typecast_class
56
+ @typecast_class ||= options[:typecast].constantize
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Logger
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def logger
9
+ MongoMapper.logger
10
+ end
11
+ end
12
+
13
+ def logger
14
+ self.class.logger
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,134 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Modifiers
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def increment(*args)
9
+ modifier_update('$inc', args)
10
+ end
11
+
12
+ def decrement(*args)
13
+ criteria, keys, options = criteria_and_keys_from_args(args)
14
+ values, to_decrement = keys.values, {}
15
+ keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
16
+ collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
17
+ end
18
+
19
+ def set(*args)
20
+ criteria, updates, options = criteria_and_keys_from_args(args)
21
+ updates.each do |key, value|
22
+ updates[key] = keys[key.to_s].set(value) if key?(key)
23
+ end
24
+ modifier_update('$set', [criteria, updates, options])
25
+ end
26
+
27
+ def unset(*args)
28
+ if args[0].is_a?(Hash)
29
+ criteria, keys = args.shift, args
30
+ options = keys.last.is_a?(Hash) ? keys.pop : {}
31
+ else
32
+ keys, ids = args.partition { |arg| arg.is_a?(Symbol) }
33
+ options = ids.last.is_a?(Hash) ? ids.pop : {}
34
+ criteria = {:id => ids}
35
+ end
36
+
37
+ criteria = criteria_hash(criteria).to_hash
38
+ updates = keys.inject({}) { |hash, key| hash[key] = 1; hash }
39
+ modifier_update('$unset', [criteria, updates, options])
40
+ end
41
+
42
+ def push(*args)
43
+ modifier_update('$push', args)
44
+ end
45
+
46
+ def push_all(*args)
47
+ modifier_update('$pushAll', args)
48
+ end
49
+
50
+ def add_to_set(*args)
51
+ modifier_update('$addToSet', args)
52
+ end
53
+ alias push_uniq add_to_set
54
+
55
+ def pull(*args)
56
+ modifier_update('$pull', args)
57
+ end
58
+
59
+ def pull_all(*args)
60
+ modifier_update('$pullAll', args)
61
+ end
62
+
63
+ def pop(*args)
64
+ modifier_update('$pop', args)
65
+ end
66
+
67
+ private
68
+ def modifier_update(modifier, args)
69
+ criteria, updates, options = criteria_and_keys_from_args(args)
70
+ if options
71
+ collection.update(criteria, {modifier => updates}, options.merge(:multi => true))
72
+ else
73
+ collection.update(criteria, {modifier => updates}, :multi => true)
74
+ end
75
+ end
76
+
77
+ def criteria_and_keys_from_args(args)
78
+ if args[0].is_a?(Hash)
79
+ criteria = args[0]
80
+ updates = args[1]
81
+ options = args[2]
82
+ else
83
+ split_args = args.partition{|a| a.is_a?(BSON::ObjectId)}
84
+ criteria = {:id => split_args[0]}
85
+ updates = split_args[1].first
86
+ options = split_args[1].last
87
+ end
88
+ [criteria_hash(criteria).to_hash, updates, options]
89
+ end
90
+ end
91
+
92
+ def unset(*args)
93
+ self.class.unset(id, *args)
94
+ end
95
+
96
+ def increment(hash, options=nil)
97
+ self.class.increment(id, hash, options)
98
+ end
99
+
100
+ def decrement(hash, options=nil)
101
+ self.class.decrement(id, hash, options)
102
+ end
103
+
104
+ def set(hash, options=nil)
105
+ self.class.set(id, hash, options)
106
+ end
107
+
108
+ def push(hash, options=nil)
109
+ self.class.push(id, hash, options)
110
+ end
111
+
112
+ def push_all(hash, options=nil)
113
+ self.class.push_all(id, hash, options)
114
+ end
115
+
116
+ def pull(hash, options=nil)
117
+ self.class.pull(id, hash, options)
118
+ end
119
+
120
+ def pull_all(hash, options=nil)
121
+ self.class.pull_all(id, hash, options)
122
+ end
123
+
124
+ def add_to_set(hash, options=nil)
125
+ self.class.push_uniq(id, hash, options)
126
+ end
127
+ alias push_uniq add_to_set
128
+
129
+ def pop(hash, options=nil)
130
+ self.class.pop(id, hash, options)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Pagination
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def per_page; 25 end
9
+
10
+ def paginate(opts={})
11
+ query.paginate({:per_page => per_page}.merge(opts))
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Persistence
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def connection(mongo_connection=nil)
9
+ assert_supported
10
+ if mongo_connection.nil?
11
+ @connection ||= MongoMapper.connection
12
+ else
13
+ @connection = mongo_connection
14
+ end
15
+ @connection
16
+ end
17
+
18
+ def set_database_name(name)
19
+ assert_supported
20
+ @database_name = name
21
+ end
22
+
23
+ def database_name
24
+ assert_supported
25
+ @database_name
26
+ end
27
+
28
+ def database
29
+ assert_supported
30
+ if database_name.nil?
31
+ MongoMapper.database
32
+ else
33
+ connection.db(database_name)
34
+ end
35
+ end
36
+
37
+ def set_collection_name(name)
38
+ assert_supported
39
+ @collection_name = name
40
+ end
41
+
42
+ def collection_name
43
+ assert_supported
44
+ @collection_name ||= self.to_s.tableize.gsub(/\//, '.')
45
+ end
46
+
47
+ def collection
48
+ assert_supported
49
+ database.collection(collection_name)
50
+ end
51
+
52
+ private
53
+ def assert_supported
54
+ if embeddable?
55
+ raise NotSupported.new('This is not supported for embeddable documents at this time.')
56
+ end
57
+ end
58
+ end
59
+
60
+ def collection
61
+ _root_document.class.collection
62
+ end
63
+
64
+ def database
65
+ _root_document.class.database
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: UTF-8
2
+ require 'set'
3
+
4
+ module MongoMapper
5
+ module Plugins
6
+ module Protected
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ class_attribute :protected_attributes
11
+ end
12
+
13
+ module ClassMethods
14
+ def attr_protected(*attrs)
15
+ raise AccessibleOrProtected.new(name) if try(:accessible_attributes?)
16
+ self.protected_attributes = Set.new(attrs) + (protected_attributes || [])
17
+ end
18
+
19
+ def key(*args)
20
+ key = super
21
+ attr_protected key.name.to_sym if key.options[:protected]
22
+ key
23
+ end
24
+ end
25
+
26
+ def attributes=(attrs={})
27
+ super(filter_protected_attrs(attrs))
28
+ end
29
+
30
+ def update_attributes(attrs={})
31
+ super(filter_protected_attrs(attrs))
32
+ end
33
+
34
+ def update_attributes!(attrs={})
35
+ super(filter_protected_attrs(attrs))
36
+ end
37
+
38
+ protected
39
+ def filter_protected_attrs(attrs)
40
+ return attrs if protected_attributes.blank? || attrs.blank?
41
+ attrs.dup.delete_if { |key, val| protected_attributes.include?(key.to_sym) }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,165 @@
1
+ # encoding: UTF-8
2
+ require 'mongo_mapper/plugins/querying/decorator'
3
+
4
+ module MongoMapper
5
+ module Plugins
6
+ module Querying
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ extend Forwardable
11
+
12
+ def_delegators :query, *Querying::Methods
13
+
14
+ def find_by_id(id)
15
+ find_one(:_id => id)
16
+ end
17
+
18
+ def first_or_create(args)
19
+ first(args) || create(args.reject { |key, value| !key?(key) })
20
+ end
21
+
22
+ def first_or_new(args)
23
+ first(args) || new(args.reject { |key, value| !key?(key) })
24
+ end
25
+
26
+ def create(*docs)
27
+ initialize_each(*docs) { |doc| doc.save }
28
+ end
29
+
30
+ def create!(*docs)
31
+ initialize_each(*docs) { |doc| doc.save! }
32
+ end
33
+
34
+ def update(*args)
35
+ if args.length == 1
36
+ update_multiple(args[0])
37
+ else
38
+ id, attributes = args
39
+ update_single(id, attributes)
40
+ end
41
+ end
42
+
43
+ def delete(*ids)
44
+ query(:_id => ids.flatten).remove
45
+ end
46
+
47
+ def delete_all(options={})
48
+ query(options).remove
49
+ end
50
+
51
+ def destroy(*ids)
52
+ find_some!(ids.flatten).each { |doc| doc.destroy }
53
+ end
54
+
55
+ def destroy_all(options={})
56
+ find_each(options) { |document| document.destroy }
57
+ end
58
+
59
+ # @api private for now
60
+ def query(options={})
61
+ query = Plucky::Query.new(collection, :transformer => transformer)
62
+ query.extend(Decorator)
63
+ query.object_ids(object_id_keys)
64
+ query.amend(options)
65
+ query.model(self)
66
+ query
67
+ end
68
+
69
+ # @api private for now
70
+ def criteria_hash(criteria={})
71
+ Plucky::CriteriaHash.new(criteria, :object_ids => object_id_keys)
72
+ end
73
+
74
+ private
75
+ def transformer
76
+ @transformer ||= lambda { |doc| load(doc) }
77
+ end
78
+
79
+ def find_some(ids, options={})
80
+ query = query(options).amend(:_id => ids.flatten.compact.uniq)
81
+ query.all
82
+ end
83
+
84
+ def find_some!(ids, options={})
85
+ ids = ids.flatten.compact.uniq
86
+ docs = find_some(ids, options)
87
+
88
+ if ids.size != docs.size
89
+ raise DocumentNotFound, "Couldn't find all of the ids (#{ids.to_sentence}). Found #{docs.size}, but was expecting #{ids.size}"
90
+ end
91
+
92
+ docs
93
+ end
94
+
95
+ def initialize_each(*docs)
96
+ instances = []
97
+ docs = [{}] if docs.blank?
98
+ docs.flatten.each do |attrs|
99
+ doc = new(attrs)
100
+ yield(doc)
101
+ instances << doc
102
+ end
103
+ instances.size == 1 ? instances[0] : instances
104
+ end
105
+
106
+ def update_single(id, attrs)
107
+ if id.blank? || attrs.blank? || !attrs.is_a?(Hash)
108
+ raise ArgumentError, "Updating a single document requires an id and a hash of attributes"
109
+ end
110
+
111
+ find(id).tap do |doc|
112
+ doc.update_attributes(attrs)
113
+ end
114
+ end
115
+
116
+ def update_multiple(docs)
117
+ unless docs.is_a?(Hash)
118
+ raise ArgumentError, "Updating multiple documents takes 1 argument and it must be hash"
119
+ end
120
+
121
+ instances = []
122
+ docs.each_pair { |id, attrs| instances << update(id, attrs) }
123
+ instances
124
+ end
125
+ end
126
+
127
+ def save(options={})
128
+ options.assert_valid_keys(:validate, :safe)
129
+ create_or_update(options)
130
+ end
131
+
132
+ def save!(options={})
133
+ options.assert_valid_keys(:safe)
134
+ save(options) || raise(DocumentNotValid.new(self))
135
+ end
136
+
137
+ def destroy
138
+ delete
139
+ end
140
+
141
+ def delete
142
+ self.class.delete(id).tap { @_destroyed = true } if persisted?
143
+ end
144
+
145
+ private
146
+ def create_or_update(options={})
147
+ result = persisted? ? update(options) : create(options)
148
+ result != false
149
+ end
150
+
151
+ def create(options={})
152
+ save_to_collection(options)
153
+ end
154
+
155
+ def update(options={})
156
+ save_to_collection(options)
157
+ end
158
+
159
+ def save_to_collection(options={})
160
+ @_new = false
161
+ collection.save(to_mongo, :safe => options[:safe])
162
+ end
163
+ end
164
+ end
165
+ end