mongo_mapper-unstable 2010.3.8 → 2010.06.23

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 (143) hide show
  1. data/README.rdoc +4 -8
  2. data/bin/mmconsole +1 -1
  3. data/examples/keys.rb +37 -0
  4. data/examples/plugins.rb +41 -0
  5. data/examples/querying.rb +35 -0
  6. data/examples/scopes.rb +52 -0
  7. data/lib/mongo_mapper/connection.rb +83 -0
  8. data/lib/mongo_mapper/document.rb +11 -329
  9. data/lib/mongo_mapper/embedded_document.rb +9 -38
  10. data/lib/mongo_mapper/exceptions.rb +30 -0
  11. data/lib/mongo_mapper/extensions/array.rb +19 -0
  12. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  13. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  14. data/lib/mongo_mapper/extensions/date.rb +25 -0
  15. data/lib/mongo_mapper/extensions/float.rb +14 -0
  16. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  17. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  18. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  19. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  20. data/lib/mongo_mapper/extensions/object.rb +27 -0
  21. data/lib/mongo_mapper/extensions/object_id.rb +30 -0
  22. data/lib/mongo_mapper/extensions/set.rb +20 -0
  23. data/lib/mongo_mapper/extensions/string.rb +18 -0
  24. data/lib/mongo_mapper/extensions/time.rb +29 -0
  25. data/lib/mongo_mapper/plugins/accessible.rb +44 -0
  26. data/lib/mongo_mapper/plugins/associations/base.rb +7 -6
  27. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
  28. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
  29. data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
  30. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
  31. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +25 -39
  32. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
  33. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +36 -46
  34. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
  35. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +5 -4
  36. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
  37. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +40 -0
  38. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +7 -7
  39. data/lib/mongo_mapper/plugins/associations/proxy.rb +16 -8
  40. data/lib/mongo_mapper/plugins/associations.rb +14 -22
  41. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  42. data/lib/mongo_mapper/plugins/callbacks.rb +17 -5
  43. data/lib/mongo_mapper/plugins/clone.rb +10 -4
  44. data/lib/mongo_mapper/plugins/descendants.rb +3 -2
  45. data/lib/mongo_mapper/plugins/dirty.rb +1 -0
  46. data/lib/mongo_mapper/plugins/document.rb +41 -0
  47. data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
  48. data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
  49. data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
  50. data/lib/mongo_mapper/plugins/equality.rb +4 -10
  51. data/lib/mongo_mapper/plugins/identity_map.rb +29 -23
  52. data/lib/mongo_mapper/plugins/indexes.rb +12 -0
  53. data/lib/mongo_mapper/plugins/inspect.rb +1 -0
  54. data/lib/mongo_mapper/plugins/keys/key.rb +55 -0
  55. data/lib/mongo_mapper/plugins/keys.rb +85 -110
  56. data/lib/mongo_mapper/plugins/logger.rb +1 -0
  57. data/lib/mongo_mapper/plugins/modifiers.rb +41 -16
  58. data/lib/mongo_mapper/plugins/pagination.rb +5 -15
  59. data/lib/mongo_mapper/plugins/persistence.rb +69 -0
  60. data/lib/mongo_mapper/plugins/protected.rb +9 -1
  61. data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
  62. data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
  63. data/lib/mongo_mapper/plugins/querying.rb +176 -0
  64. data/lib/mongo_mapper/plugins/rails.rb +6 -1
  65. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  66. data/lib/mongo_mapper/plugins/sci.rb +32 -0
  67. data/lib/mongo_mapper/plugins/scopes.rb +21 -0
  68. data/lib/mongo_mapper/plugins/serialization.rb +5 -4
  69. data/lib/mongo_mapper/plugins/timestamps.rb +2 -1
  70. data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
  71. data/lib/mongo_mapper/plugins/validations.rb +9 -5
  72. data/lib/mongo_mapper/plugins.rb +1 -20
  73. data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
  74. data/lib/mongo_mapper/version.rb +4 -0
  75. data/lib/mongo_mapper.rb +71 -128
  76. data/test/{NOTE_ON_TESTING → _NOTE_ON_TESTING} +0 -0
  77. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +5 -5
  78. data/test/functional/associations/test_belongs_to_proxy.rb +13 -21
  79. data/test/functional/associations/test_in_array_proxy.rb +7 -9
  80. data/test/functional/associations/test_many_documents_as_proxy.rb +5 -5
  81. data/test/functional/associations/test_many_documents_proxy.rb +186 -64
  82. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +22 -22
  83. data/test/functional/associations/test_many_embedded_proxy.rb +32 -32
  84. data/test/functional/associations/test_many_polymorphic_proxy.rb +47 -47
  85. data/test/functional/associations/test_one_embedded_proxy.rb +67 -0
  86. data/test/functional/associations/test_one_proxy.rb +70 -49
  87. data/test/functional/test_accessible.rb +168 -0
  88. data/test/functional/test_associations.rb +11 -11
  89. data/test/functional/test_binary.rb +5 -5
  90. data/test/functional/test_caching.rb +76 -0
  91. data/test/functional/test_callbacks.rb +104 -34
  92. data/test/functional/test_dirty.rb +16 -16
  93. data/test/functional/test_document.rb +12 -924
  94. data/test/functional/test_dynamic_querying.rb +75 -0
  95. data/test/functional/test_embedded_document.rb +88 -8
  96. data/test/functional/test_identity_map.rb +41 -43
  97. data/test/functional/{test_indexing.rb → test_indexes.rb} +3 -5
  98. data/test/functional/test_logger.rb +1 -1
  99. data/test/functional/test_modifiers.rb +275 -181
  100. data/test/functional/test_pagination.rb +13 -15
  101. data/test/functional/test_protected.rb +25 -11
  102. data/test/functional/test_querying.rb +873 -0
  103. data/test/functional/test_safe.rb +76 -0
  104. data/test/functional/test_sci.rb +230 -0
  105. data/test/functional/test_scopes.rb +171 -0
  106. data/test/functional/test_string_id_compatibility.rb +11 -11
  107. data/test/functional/test_timestamps.rb +0 -2
  108. data/test/functional/test_userstamps.rb +0 -1
  109. data/test/functional/test_validations.rb +44 -31
  110. data/test/models.rb +18 -17
  111. data/test/{active_model_lint_test.rb → test_active_model_lint.rb} +3 -1
  112. data/test/test_helper.rb +59 -16
  113. data/test/unit/associations/test_base.rb +47 -42
  114. data/test/unit/associations/test_proxy.rb +15 -15
  115. data/test/unit/serializers/test_json_serializer.rb +29 -29
  116. data/test/unit/test_clone.rb +69 -0
  117. data/test/unit/test_descendant_appends.rb +3 -3
  118. data/test/unit/test_document.rb +49 -67
  119. data/test/unit/test_dynamic_finder.rb +53 -51
  120. data/test/unit/test_embedded_document.rb +19 -38
  121. data/test/unit/{test_support.rb → test_extensions.rb} +136 -122
  122. data/test/unit/test_key.rb +185 -0
  123. data/test/unit/test_keys.rb +29 -147
  124. data/test/unit/test_mongo_mapper.rb +3 -48
  125. data/test/unit/test_pagination.rb +1 -150
  126. data/test/unit/test_rails.rb +77 -19
  127. data/test/unit/test_rails_compatibility.rb +12 -12
  128. data/test/unit/test_serialization.rb +5 -5
  129. data/test/unit/test_time_zones.rb +9 -9
  130. data/test/unit/test_validations.rb +46 -46
  131. metadata +157 -155
  132. data/.gitignore +0 -10
  133. data/Rakefile +0 -55
  134. data/VERSION +0 -1
  135. data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
  136. data/lib/mongo_mapper/query.rb +0 -130
  137. data/lib/mongo_mapper/support.rb +0 -215
  138. data/mongo_mapper.gemspec +0 -196
  139. data/performance/read_write.rb +0 -52
  140. data/specs.watchr +0 -51
  141. data/test/support/custom_matchers.rb +0 -55
  142. data/test/support/timing.rb +0 -16
  143. data/test/unit/test_query.rb +0 -340
@@ -1,29 +1,7 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
- module Support
3
- # @api private
4
- module Find
5
- def dynamic_find(finder, args)
6
- attributes = {}
7
-
8
- finder.attributes.each_with_index do |attr, index|
9
- attributes[attr] = args[index]
10
- end
11
-
12
- options = args.extract_options!.merge(attributes)
13
-
14
- if result = send(finder.finder, options)
15
- result
16
- else
17
- if finder.raise?
18
- raise DocumentNotFound, "Couldn't find Document with #{attributes.inspect} in collection named #{collection.name}"
19
- end
20
-
21
- if finder.instantiator
22
- self.send(finder.instantiator, attributes)
23
- end
24
- end
25
- end
26
-
3
+ module Plugins
4
+ module DynamicQuerying
27
5
  class DynamicFinder
28
6
  attr_reader :method, :attributes, :finder, :bang, :instantiator
29
7
 
@@ -61,17 +39,6 @@ module MongoMapper
61
39
  @attributes = names && names.split('_and_')
62
40
  end
63
41
  end
64
-
65
- protected
66
- def method_missing(method, *args, &block)
67
- finder = DynamicFinder.new(method)
68
-
69
- if finder.found?
70
- dynamic_find(finder, args)
71
- else
72
- super
73
- end
74
- end
75
42
  end
76
43
  end
77
44
  end
@@ -0,0 +1,43 @@
1
+ # encoding: UTF-8
2
+ require 'mongo_mapper/plugins/dynamic_querying/dynamic_finder'
3
+
4
+ module MongoMapper
5
+ module Plugins
6
+ module DynamicQuerying
7
+ module ClassMethods
8
+ def dynamic_find(finder, args)
9
+ attributes = {}
10
+
11
+ finder.attributes.each_with_index do |attr, index|
12
+ attributes[attr] = args[index]
13
+ end
14
+
15
+ options = args.extract_options!.merge(attributes)
16
+
17
+ if result = send(finder.finder, options)
18
+ result
19
+ else
20
+ if finder.raise?
21
+ raise DocumentNotFound, "Couldn't find Document with #{attributes.inspect} in collection named #{collection.name}"
22
+ end
23
+
24
+ if finder.instantiator
25
+ self.send(finder.instantiator, attributes)
26
+ end
27
+ end
28
+ end
29
+
30
+ protected
31
+ def method_missing(method, *args, &block)
32
+ finder = DynamicFinder.new(method)
33
+
34
+ if finder.found?
35
+ dynamic_find(finder, args)
36
+ else
37
+ super
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module EmbeddedDocument
5
+ def self.configure(model)
6
+ model.class_eval do
7
+ attr_reader :_root_document, :_parent_document
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def embeddable?
13
+ true
14
+ end
15
+
16
+ def embedded_in(owner_name)
17
+ define_method(owner_name) { _parent_document }
18
+ end
19
+ end
20
+
21
+ module InstanceMethods
22
+ def new?
23
+ _root_document.try(:new?) || @_new
24
+ end
25
+
26
+ def destroyed?
27
+ !!_root_document.try(:destroyed?)
28
+ end
29
+
30
+ def save(options={})
31
+ _root_document.try(:save, options).tap do |result|
32
+ @_new = false if result
33
+ end
34
+ end
35
+
36
+ def save!(options={})
37
+ _root_document.try(:save, options).tap do |result|
38
+ @_new = false if result
39
+ end
40
+ end
41
+
42
+ def _parent_document=(value)
43
+ @_root_document = value._root_document
44
+ @_parent_document = value
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,19 +1,13 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Equality
4
5
  module InstanceMethods
5
- def ==(other)
6
- other.is_a?(self.class) && _id == other._id
7
- end
8
-
9
6
  def eql?(other)
10
- self == other
11
- end
12
-
13
- def equal?(other)
14
- object_id === other.object_id
7
+ other.is_a?(self.class) && _id == other._id
15
8
  end
16
-
9
+ alias :== :eql?
10
+
17
11
  def hash
18
12
  _id.hash
19
13
  end
@@ -1,3 +1,6 @@
1
+ # encoding: UTF-8
2
+ require 'set'
3
+
1
4
  module MongoMapper
2
5
  module Plugins
3
6
  module IdentityMap
@@ -8,7 +11,7 @@ module MongoMapper
8
11
  def self.clear
9
12
  models.each { |m| m.identity_map.clear }
10
13
  end
11
-
14
+
12
15
  def self.configure(model)
13
16
  IdentityMap.models << model
14
17
  end
@@ -27,28 +30,41 @@ module MongoMapper
27
30
  @identity_map = v
28
31
  end
29
32
 
30
- def find_one(options={})
31
- criteria, query_options = to_query(options)
33
+ module IdentityMapQueryMethods
34
+ def all(opts={})
35
+ query = clone.update(opts)
36
+ super.tap do |docs|
37
+ model.remove_documents_from_map(docs) if query.fields?
38
+ end
39
+ end
32
40
 
33
- if simple_find?(criteria) && identity_map.key?(criteria[:_id])
34
- identity_map[criteria[:_id]]
35
- else
36
- super.tap do |document|
37
- remove_documents_from_map(document) if selecting_fields?(query_options)
41
+ def find_one(opts={})
42
+ query = clone.update(opts)
43
+
44
+ if query.simple? && model.identity_map[query[:_id]]
45
+ model.identity_map[query[:_id]]
46
+ else
47
+ super.tap do |doc|
48
+ model.remove_documents_from_map(doc) if query.fields?
49
+ end
38
50
  end
39
51
  end
40
52
  end
41
53
 
42
- def find_many(options)
43
- criteria, query_options = to_query(options)
44
- super.tap do |documents|
45
- remove_documents_from_map(documents) if selecting_fields?(query_options)
54
+ def query(opts={})
55
+ super.extend(IdentityMapQueryMethods)
56
+ end
57
+
58
+ def remove_documents_from_map(*documents)
59
+ documents.flatten.compact.each do |document|
60
+ identity_map.delete(document['_id'])
46
61
  end
47
62
  end
48
63
 
49
64
  def load(attrs)
65
+ return nil if attrs.nil?
50
66
  document = identity_map[attrs['_id']]
51
-
67
+
52
68
  if document.nil? || identity_map_off?
53
69
  document = super
54
70
  identity_map[document._id] = document if identity_map_on?
@@ -85,16 +101,6 @@ module MongoMapper
85
101
  end
86
102
 
87
103
  private
88
- def remove_documents_from_map(*documents)
89
- documents.flatten.compact.each do |document|
90
- identity_map.delete(document._id)
91
- end
92
- end
93
-
94
- def simple_find?(criteria)
95
- criteria.keys == [:_id] || criteria.keys.to_set == [:_id, :_type].to_set
96
- end
97
-
98
104
  def selecting_fields?(options)
99
105
  !options[:fields].nil?
100
106
  end
@@ -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
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Inspect
@@ -0,0 +1,55 @@
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
+ [Integer, Float].include?(type)
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
+ return default_value
34
+ end
35
+ end
36
+
37
+ type.from_mongo(value)
38
+ end
39
+
40
+ def set(value)
41
+ type.to_mongo(value).tap do |values|
42
+ if options[:typecast].present?
43
+ values.map! { |v| typecast_class.to_mongo(v) }
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+ def typecast_class
50
+ @typecast_class ||= options[:typecast].constantize
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,3 +1,6 @@
1
+ # encoding: UTF-8
2
+ require 'mongo_mapper/plugins/keys/key'
3
+
1
4
  module MongoMapper
2
5
  module Plugins
3
6
  module Keys
@@ -16,24 +19,29 @@ module MongoMapper
16
19
  end
17
20
 
18
21
  def key(*args)
19
- key = Key.new(*args)
20
- keys[key.name] = key
21
-
22
- create_accessors_for(key)
23
- create_key_in_descendants(*args)
24
- create_indexes_for(key)
25
- create_validations_for(key)
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
26
30
 
27
- key
31
+ def key?(key)
32
+ keys.keys.include?(key.to_s)
28
33
  end
29
34
 
30
35
  def using_object_id?
31
36
  object_id_key?(:_id)
32
37
  end
33
38
 
39
+ def object_id_keys
40
+ keys.keys.select { |key| keys[key].type == ObjectId }.map(&:to_sym)
41
+ end
42
+
34
43
  def object_id_key?(name)
35
- key = keys[name.to_s]
36
- key && key.type == ObjectId
44
+ object_id_keys.include?(name.to_sym)
37
45
  end
38
46
 
39
47
  def to_mongo(instance)
@@ -48,6 +56,7 @@ module MongoMapper
48
56
 
49
57
  # load is overridden in identity map to ensure same objects are loaded
50
58
  def load(attrs)
59
+ return nil if attrs.nil?
51
60
  begin
52
61
  klass = attrs['_type'].present? ? attrs['_type'].constantize : self
53
62
  klass.new(attrs, true)
@@ -57,14 +66,16 @@ module MongoMapper
57
66
  end
58
67
 
59
68
  private
60
- def accessors_module
61
- module_defined = if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
62
- const_defined?('MongoMapperKeys')
63
- else
64
- const_defined?('MongoMapperKeys', false)
65
- end
69
+ def key_accessors_module_defined?
70
+ if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
71
+ const_defined?('MongoMapperKeys')
72
+ else
73
+ const_defined?('MongoMapperKeys', false)
74
+ end
75
+ end
66
76
 
67
- if module_defined
77
+ def accessors_module
78
+ if key_accessors_module_defined?
68
79
  const_get 'MongoMapperKeys'
69
80
  else
70
81
  const_set 'MongoMapperKeys', Module.new
@@ -94,7 +105,6 @@ module MongoMapper
94
105
  end
95
106
 
96
107
  def create_key_in_descendants(*args)
97
- return if descendants.blank?
98
108
  descendants.each { |descendant| descendant.key(*args) }
99
109
  end
100
110
 
@@ -146,60 +156,50 @@ module MongoMapper
146
156
 
147
157
  module InstanceMethods
148
158
  def initialize(attrs={}, from_database=false)
149
- unless attrs.nil?
150
- provided_keys = attrs.keys.map { |k| k.to_s }
151
- unless provided_keys.include?('_id') || provided_keys.include?('id')
152
- write_key :_id, Mongo::ObjectID.new
153
- end
154
- end
155
-
156
- assign_type_if_present
159
+ default_id_value(attrs)
157
160
 
158
161
  if from_database
159
- @new = false
160
- self.attributes = attrs
162
+ @_new = false
163
+ load_from_database(attrs)
161
164
  else
162
- @new = true
165
+ @_new = true
163
166
  assign(attrs)
164
167
  end
165
168
  end
166
169
 
167
- def new?
168
- @new
170
+ def persisted?
171
+ !new? && !destroyed?
169
172
  end
170
173
 
171
174
  def attributes=(attrs)
172
175
  return if attrs.blank?
173
176
 
174
- attrs.each_pair do |name, value|
175
- writer_method = "#{name}="
176
-
177
- if respond_to?(writer_method)
178
- if writer_method == '_root_document='
179
- puts "_root_document= #{value.inspect}"
180
- end
181
- self.send(writer_method, value)
177
+ attrs.each_pair do |key, value|
178
+ if respond_to?(:"#{key}=")
179
+ self.send(:"#{key}=", value)
182
180
  else
183
- self[name.to_s] = value
181
+ self[key] = value
184
182
  end
185
183
  end
186
184
  end
187
185
 
188
186
  def attributes
189
- attrs = HashWithIndifferentAccess.new
190
-
191
- keys.each_pair do |name, key|
192
- value = key.set(self[key.name])
193
- attrs[name] = value
194
- end
187
+ HashWithIndifferentAccess.new.tap do |attrs|
188
+ keys.each_pair do |name, key|
189
+ value = key.set(self[key.name])
190
+ attrs[name] = value
191
+ end
195
192
 
196
- embedded_associations.each do |association|
197
- if documents = instance_variable_get(association.ivar)
198
- attrs[association.name] = documents.map { |document| document.to_mongo }
193
+ embedded_associations.each do |association|
194
+ if documents = instance_variable_get(association.ivar)
195
+ if association.one?
196
+ attrs[association.name] = documents.to_mongo
197
+ else
198
+ attrs[association.name] = documents.map { |document| document.to_mongo }
199
+ end
200
+ end
199
201
  end
200
202
  end
201
-
202
- attrs
203
203
  end
204
204
  alias :to_mongo :attributes
205
205
 
@@ -223,7 +223,7 @@ module MongoMapper
223
223
 
224
224
  def id=(value)
225
225
  if self.class.using_object_id?
226
- value = MongoMapper.normalize_object_id(value)
226
+ value = ObjectId.to_mongo(value)
227
227
  end
228
228
 
229
229
  self[:_id] = value
@@ -238,98 +238,73 @@ module MongoMapper
238
238
  write_key(name, value)
239
239
  end
240
240
 
241
- # @api public
242
241
  def keys
243
242
  self.class.keys
244
243
  end
245
244
 
246
- # @api private?
247
245
  def key_names
248
246
  keys.keys
249
247
  end
250
248
 
251
- # @api private?
252
249
  def non_embedded_keys
253
250
  keys.values.select { |key| !key.embeddable? }
254
251
  end
255
252
 
256
- # @api private?
257
253
  def embedded_keys
258
254
  keys.values.select { |key| key.embeddable? }
259
255
  end
260
256
 
261
257
  private
262
- def assign_type_if_present
263
- self._type = self.class.name if respond_to?(:_type=)
264
- end
265
-
266
- def ensure_key_exists(name)
267
- self.class.key(name) unless respond_to?("#{name}=")
258
+ def load_from_database(attrs)
259
+ return if attrs.blank?
260
+ attrs.each do |key, value|
261
+ if respond_to?(:"#{key}=") && !self.class.key?(key)
262
+ self.send(:"#{key}=", value)
263
+ else
264
+ self[key] = value
265
+ end
266
+ end
268
267
  end
269
268
 
270
- def read_key(name)
271
- if key = keys[name]
272
- var_name = "@#{name}"
273
- value = key.get(instance_variable_get(var_name))
274
- instance_variable_set(var_name, value)
275
- else
276
- raise KeyNotFound, "Could not find key: #{name.inspect}"
269
+ def default_id_value(attrs)
270
+ unless attrs.nil?
271
+ provided_keys = attrs.keys.map { |k| k.to_s }
272
+ unless provided_keys.include?('_id') || provided_keys.include?('id')
273
+ write_key :_id, BSON::ObjectID.new
274
+ end
277
275
  end
278
276
  end
279
277
 
280
- def read_key_before_typecast(name)
281
- instance_variable_get("@#{name}_before_typecast")
278
+ def ensure_key_exists(name)
279
+ self.class.key(name) unless respond_to?("#{name}=")
282
280
  end
283
281
 
284
- def write_key(name, value)
285
- key = keys[name]
286
-
282
+ def set_parent_document(key, value)
287
283
  if key.embeddable? && value.is_a?(key.type)
288
284
  value._parent_document = self
289
285
  end
290
-
291
- instance_variable_set "@#{name}_before_typecast", value
292
- instance_variable_set "@#{name}", key.set(value)
293
286
  end
294
- end
295
-
296
- class Key
297
- attr_accessor :name, :type, :options, :default_value
298
-
299
- def initialize(*args)
300
- options = args.extract_options!
301
- @name, @type = args.shift.to_s, args.shift
302
- self.options = (options || {}).symbolize_keys
303
- self.default_value = self.options.delete(:default)
304
- end
305
287
 
306
- def ==(other)
307
- @name == other.name && @type == other.type
308
- end
309
-
310
- def embeddable?
311
- type.respond_to?(:embeddable?) && type.embeddable? ? true : false
312
- end
313
-
314
- def number?
315
- [Integer, Float].include?(type)
316
- end
317
-
318
- def get(value)
319
- if value.nil? && !default_value.nil?
320
- if default_value.respond_to?(:call)
321
- return default_value.call
288
+ def read_key(key_name)
289
+ if key = keys[key_name]
290
+ value = key.get(instance_variable_get(:"@#{key_name}"))
291
+ set_parent_document(key, value)
292
+ instance_variable_set(:"@#{key_name}", value)
322
293
  else
323
- return default_value
294
+ raise KeyNotFound, "Could not find key: #{key_name.inspect}"
324
295
  end
325
296
  end
326
297
 
327
- type.from_mongo(value)
328
- end
298
+ def read_key_before_typecast(name)
299
+ instance_variable_get(:"@#{name}_before_typecast")
300
+ end
329
301
 
330
- def set(value)
331
- type.to_mongo(value)
332
- end
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
333
308
  end
334
309
  end
335
310
  end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Logger