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.
- data/README.rdoc +4 -8
- data/bin/mmconsole +1 -1
- data/examples/keys.rb +37 -0
- data/examples/plugins.rb +41 -0
- data/examples/querying.rb +35 -0
- data/examples/scopes.rb +52 -0
- data/lib/mongo_mapper/connection.rb +83 -0
- data/lib/mongo_mapper/document.rb +11 -329
- data/lib/mongo_mapper/embedded_document.rb +9 -38
- data/lib/mongo_mapper/exceptions.rb +30 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +27 -0
- data/lib/mongo_mapper/extensions/object_id.rb +30 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +29 -0
- data/lib/mongo_mapper/plugins/accessible.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +7 -6
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
- data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +25 -39
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +36 -46
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +5 -4
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +40 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +7 -7
- data/lib/mongo_mapper/plugins/associations/proxy.rb +16 -8
- data/lib/mongo_mapper/plugins/associations.rb +14 -22
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +17 -5
- data/lib/mongo_mapper/plugins/clone.rb +10 -4
- data/lib/mongo_mapper/plugins/descendants.rb +3 -2
- data/lib/mongo_mapper/plugins/dirty.rb +1 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
- data/lib/mongo_mapper/plugins/equality.rb +4 -10
- data/lib/mongo_mapper/plugins/identity_map.rb +29 -23
- data/lib/mongo_mapper/plugins/indexes.rb +12 -0
- data/lib/mongo_mapper/plugins/inspect.rb +1 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +55 -0
- data/lib/mongo_mapper/plugins/keys.rb +85 -110
- data/lib/mongo_mapper/plugins/logger.rb +1 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +41 -16
- data/lib/mongo_mapper/plugins/pagination.rb +5 -15
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +9 -1
- data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
- data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
- data/lib/mongo_mapper/plugins/querying.rb +176 -0
- data/lib/mongo_mapper/plugins/rails.rb +6 -1
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +32 -0
- data/lib/mongo_mapper/plugins/scopes.rb +21 -0
- data/lib/mongo_mapper/plugins/serialization.rb +5 -4
- data/lib/mongo_mapper/plugins/timestamps.rb +2 -1
- data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
- data/lib/mongo_mapper/plugins/validations.rb +9 -5
- data/lib/mongo_mapper/plugins.rb +1 -20
- data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/mongo_mapper.rb +71 -128
- data/test/{NOTE_ON_TESTING → _NOTE_ON_TESTING} +0 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +5 -5
- data/test/functional/associations/test_belongs_to_proxy.rb +13 -21
- data/test/functional/associations/test_in_array_proxy.rb +7 -9
- data/test/functional/associations/test_many_documents_as_proxy.rb +5 -5
- data/test/functional/associations/test_many_documents_proxy.rb +186 -64
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +22 -22
- data/test/functional/associations/test_many_embedded_proxy.rb +32 -32
- data/test/functional/associations/test_many_polymorphic_proxy.rb +47 -47
- data/test/functional/associations/test_one_embedded_proxy.rb +67 -0
- data/test/functional/associations/test_one_proxy.rb +70 -49
- data/test/functional/test_accessible.rb +168 -0
- data/test/functional/test_associations.rb +11 -11
- data/test/functional/test_binary.rb +5 -5
- data/test/functional/test_caching.rb +76 -0
- data/test/functional/test_callbacks.rb +104 -34
- data/test/functional/test_dirty.rb +16 -16
- data/test/functional/test_document.rb +12 -924
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +88 -8
- data/test/functional/test_identity_map.rb +41 -43
- data/test/functional/{test_indexing.rb → test_indexes.rb} +3 -5
- data/test/functional/test_logger.rb +1 -1
- data/test/functional/test_modifiers.rb +275 -181
- data/test/functional/test_pagination.rb +13 -15
- data/test/functional/test_protected.rb +25 -11
- data/test/functional/test_querying.rb +873 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +230 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_string_id_compatibility.rb +11 -11
- data/test/functional/test_timestamps.rb +0 -2
- data/test/functional/test_userstamps.rb +0 -1
- data/test/functional/test_validations.rb +44 -31
- data/test/models.rb +18 -17
- data/test/{active_model_lint_test.rb → test_active_model_lint.rb} +3 -1
- data/test/test_helper.rb +59 -16
- data/test/unit/associations/test_base.rb +47 -42
- data/test/unit/associations/test_proxy.rb +15 -15
- data/test/unit/serializers/test_json_serializer.rb +29 -29
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_descendant_appends.rb +3 -3
- data/test/unit/test_document.rb +49 -67
- data/test/unit/test_dynamic_finder.rb +53 -51
- data/test/unit/test_embedded_document.rb +19 -38
- data/test/unit/{test_support.rb → test_extensions.rb} +136 -122
- data/test/unit/test_key.rb +185 -0
- data/test/unit/test_keys.rb +29 -147
- data/test/unit/test_mongo_mapper.rb +3 -48
- data/test/unit/test_pagination.rb +1 -150
- data/test/unit/test_rails.rb +77 -19
- data/test/unit/test_rails_compatibility.rb +12 -12
- data/test/unit/test_serialization.rb +5 -5
- data/test/unit/test_time_zones.rb +9 -9
- data/test/unit/test_validations.rb +46 -46
- metadata +157 -155
- data/.gitignore +0 -10
- data/Rakefile +0 -55
- data/VERSION +0 -1
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
- data/lib/mongo_mapper/query.rb +0 -130
- data/lib/mongo_mapper/support.rb +0 -215
- data/mongo_mapper.gemspec +0 -196
- data/performance/read_write.rb +0 -52
- data/specs.watchr +0 -51
- data/test/support/custom_matchers.rb +0 -55
- data/test/support/timing.rb +0 -16
- data/test/unit/test_query.rb +0 -340
@@ -1,29 +1,7 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
|
-
module
|
3
|
-
|
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
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
43
|
-
|
44
|
-
|
45
|
-
|
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,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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
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
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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
|
-
|
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
|
-
@
|
160
|
-
|
162
|
+
@_new = false
|
163
|
+
load_from_database(attrs)
|
161
164
|
else
|
162
|
-
@
|
165
|
+
@_new = true
|
163
166
|
assign(attrs)
|
164
167
|
end
|
165
168
|
end
|
166
169
|
|
167
|
-
def
|
168
|
-
|
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 |
|
175
|
-
|
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[
|
181
|
+
self[key] = value
|
184
182
|
end
|
185
183
|
end
|
186
184
|
end
|
187
185
|
|
188
186
|
def attributes
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
197
|
-
|
198
|
-
|
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 =
|
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
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
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
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
281
|
-
|
278
|
+
def ensure_key_exists(name)
|
279
|
+
self.class.key(name) unless respond_to?("#{name}=")
|
282
280
|
end
|
283
281
|
|
284
|
-
def
|
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
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
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
|
-
|
294
|
+
raise KeyNotFound, "Could not find key: #{key_name.inspect}"
|
324
295
|
end
|
325
296
|
end
|
326
297
|
|
327
|
-
|
328
|
-
|
298
|
+
def read_key_before_typecast(name)
|
299
|
+
instance_variable_get(:"@#{name}_before_typecast")
|
300
|
+
end
|
329
301
|
|
330
|
-
|
331
|
-
|
332
|
-
|
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
|