mongo_mapper-unstable 2010.3.8 → 2010.06.23

Sign up to get free protection for your applications and to get access to all the features.
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