mongo_mapper 0.14.0 → 0.15.4
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.
- checksums.yaml +5 -5
- data/LICENSE +1 -1
- data/README.md +72 -0
- data/examples/keys.rb +1 -1
- data/examples/modifiers/set.rb +1 -1
- data/examples/querying.rb +1 -1
- data/examples/safe.rb +2 -2
- data/examples/scopes.rb +1 -1
- data/lib/mongo_mapper.rb +19 -17
- data/lib/mongo_mapper/connection.rb +16 -38
- data/lib/mongo_mapper/extensions/array.rb +1 -1
- data/lib/mongo_mapper/extensions/binary.rb +1 -1
- data/lib/mongo_mapper/extensions/date.rb +1 -1
- data/lib/mongo_mapper/extensions/float.rb +1 -1
- data/lib/mongo_mapper/extensions/hash.rb +1 -1
- data/lib/mongo_mapper/extensions/nil_class.rb +2 -2
- data/lib/mongo_mapper/extensions/object.rb +1 -1
- data/lib/mongo_mapper/extensions/object_id.rb +6 -2
- data/lib/mongo_mapper/extensions/set.rb +1 -1
- data/lib/mongo_mapper/extensions/string.rb +1 -1
- data/lib/mongo_mapper/plugins/accessible.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/base.rb +10 -2
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/many_association.rb +6 -5
- data/lib/mongo_mapper/plugins/associations/{belongs_to_polymorphic_proxy.rb → proxy/belongs_to_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{belongs_to_proxy.rb → proxy/belongs_to_proxy.rb} +6 -0
- data/lib/mongo_mapper/plugins/associations/proxy/collection.rb +55 -0
- data/lib/mongo_mapper/plugins/associations/{embedded_collection.rb → proxy/embedded_collection.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{in_array_proxy.rb → proxy/in_array_proxy.rb} +36 -6
- data/lib/mongo_mapper/plugins/associations/proxy/in_foreign_array_proxy.rb +136 -0
- data/lib/mongo_mapper/plugins/associations/{many_documents_as_proxy.rb → proxy/many_documents_as_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{many_documents_proxy.rb → proxy/many_documents_proxy.rb} +0 -4
- data/lib/mongo_mapper/plugins/associations/{many_embedded_polymorphic_proxy.rb → proxy/many_embedded_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{many_embedded_proxy.rb → proxy/many_embedded_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{many_polymorphic_proxy.rb → proxy/many_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{one_as_proxy.rb → proxy/one_as_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{one_embedded_polymorphic_proxy.rb → proxy/one_embedded_polymorphic_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/{one_embedded_proxy.rb → proxy/one_embedded_proxy.rb} +3 -1
- data/lib/mongo_mapper/plugins/associations/{one_proxy.rb → proxy/one_proxy.rb} +0 -0
- data/lib/mongo_mapper/plugins/associations/proxy/proxy.rb +164 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -13
- data/lib/mongo_mapper/plugins/dirty.rb +29 -37
- data/lib/mongo_mapper/plugins/document.rb +1 -1
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +1 -1
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +2 -2
- data/lib/mongo_mapper/plugins/identity_map.rb +3 -1
- data/lib/mongo_mapper/plugins/indexes.rb +13 -6
- data/lib/mongo_mapper/plugins/keys.rb +12 -7
- data/lib/mongo_mapper/plugins/keys/key.rb +21 -13
- data/lib/mongo_mapper/plugins/modifiers.rb +39 -14
- data/lib/mongo_mapper/plugins/persistence.rb +6 -2
- data/lib/mongo_mapper/plugins/querying.rb +9 -3
- data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +6 -6
- data/lib/mongo_mapper/plugins/safe.rb +10 -4
- data/lib/mongo_mapper/plugins/scopes.rb +19 -3
- data/lib/mongo_mapper/plugins/stats.rb +1 -3
- data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
- data/lib/mongo_mapper/plugins/validations.rb +1 -1
- data/lib/mongo_mapper/railtie.rb +1 -0
- data/lib/mongo_mapper/utils.rb +2 -2
- data/lib/mongo_mapper/version.rb +1 -1
- data/spec/examples.txt +1731 -0
- data/spec/functional/accessible_spec.rb +7 -1
- data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +2 -2
- data/spec/functional/associations/belongs_to_proxy_spec.rb +55 -5
- data/spec/functional/associations/in_array_proxy_spec.rb +149 -14
- data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
- data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
- data/spec/functional/associations/many_documents_proxy_spec.rb +22 -22
- data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +2 -2
- data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
- data/spec/functional/associations/one_as_proxy_spec.rb +8 -8
- data/spec/functional/associations/one_embedded_proxy_spec.rb +28 -0
- data/spec/functional/associations/one_proxy_spec.rb +19 -9
- data/spec/functional/associations_spec.rb +3 -3
- data/spec/functional/binary_spec.rb +2 -2
- data/spec/functional/caching_spec.rb +15 -22
- data/spec/functional/callbacks_spec.rb +2 -2
- data/spec/functional/counter_cache_spec.rb +10 -10
- data/spec/functional/dirty_spec.rb +48 -10
- data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
- data/spec/functional/document_spec.rb +5 -8
- data/spec/functional/dumpable_spec.rb +1 -1
- data/spec/functional/embedded_document_spec.rb +5 -5
- data/spec/functional/identity_map_spec.rb +8 -8
- data/spec/functional/indexes_spec.rb +19 -18
- data/spec/functional/keys_spec.rb +64 -33
- data/spec/functional/logger_spec.rb +2 -2
- data/spec/functional/modifiers_spec.rb +81 -19
- data/spec/functional/partial_updates_spec.rb +8 -8
- data/spec/functional/protected_spec.rb +1 -1
- data/spec/functional/querying_spec.rb +70 -22
- data/spec/functional/safe_spec.rb +23 -27
- data/spec/functional/sci_spec.rb +7 -7
- data/spec/functional/scopes_spec.rb +89 -1
- data/spec/functional/static_keys_spec.rb +2 -2
- data/spec/functional/stats_spec.rb +28 -12
- data/spec/functional/strong_parameters_spec.rb +49 -0
- data/spec/functional/validations_spec.rb +8 -16
- data/spec/quality_spec.rb +1 -1
- data/spec/spec_helper.rb +39 -8
- data/spec/support/matchers.rb +1 -1
- data/spec/unit/associations/proxy_spec.rb +18 -10
- data/spec/unit/clone_spec.rb +1 -1
- data/spec/unit/document_spec.rb +3 -3
- data/spec/unit/embedded_document_spec.rb +4 -5
- data/spec/unit/extensions_spec.rb +12 -7
- data/spec/unit/identity_map_middleware_spec.rb +65 -96
- data/spec/unit/inspect_spec.rb +1 -1
- data/spec/unit/key_spec.rb +23 -18
- data/spec/unit/keys_spec.rb +17 -8
- data/spec/unit/mongo_mapper_spec.rb +41 -88
- data/spec/unit/rails_spec.rb +2 -2
- data/spec/unit/validations_spec.rb +18 -18
- metadata +70 -38
- data/README.rdoc +0 -56
- data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
- data/lib/mongo_mapper/plugins/associations/collection.rb +0 -29
- data/lib/mongo_mapper/plugins/associations/proxy.rb +0 -141
@@ -17,6 +17,8 @@ module MongoMapper
|
|
17
17
|
ManyPolymorphicProxy
|
18
18
|
elsif as?
|
19
19
|
ManyDocumentsAsProxy
|
20
|
+
elsif in_foreign_array?
|
21
|
+
InForeignArrayProxy
|
20
22
|
elsif in_array?
|
21
23
|
InArrayProxy
|
22
24
|
else
|
@@ -26,14 +28,13 @@ module MongoMapper
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def setup(model)
|
29
|
-
model.associations_module.module_eval
|
31
|
+
model.associations_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
|
30
32
|
def #{name}
|
31
|
-
get_proxy(associations[#{name.inspect}])
|
33
|
+
get_proxy(associations[#{name.inspect}]).read
|
32
34
|
end
|
33
35
|
|
34
36
|
def #{name}=(value)
|
35
|
-
get_proxy(associations[#{name.inspect}]).
|
36
|
-
value
|
37
|
+
get_proxy(associations[#{name.inspect}]).write(value)
|
37
38
|
end
|
38
39
|
end_eval
|
39
40
|
|
@@ -60,4 +61,4 @@ module MongoMapper
|
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
63
|
-
end
|
64
|
+
end
|
File without changes
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Associations
|
5
|
+
class Collection < Proxy
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def to_a
|
9
|
+
load_target
|
10
|
+
|
11
|
+
target.is_a?(Array) ?
|
12
|
+
target :
|
13
|
+
Array(target)
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :to_ary, :to_a
|
17
|
+
|
18
|
+
def each(&block)
|
19
|
+
to_a.each(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def [](val)
|
23
|
+
objs = to_a
|
24
|
+
objs ? objs[val] : nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def empty?
|
28
|
+
to_a.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def size
|
32
|
+
to_a.size
|
33
|
+
end
|
34
|
+
|
35
|
+
def length
|
36
|
+
to_a.length
|
37
|
+
end
|
38
|
+
|
39
|
+
def reset
|
40
|
+
super
|
41
|
+
target = []
|
42
|
+
end
|
43
|
+
|
44
|
+
def read
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def write(value)
|
49
|
+
replace(value)
|
50
|
+
read
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/mongo_mapper/plugins/associations/{embedded_collection.rb → proxy/embedded_collection.rb}
RENAMED
File without changes
|
@@ -6,11 +6,11 @@ module MongoMapper
|
|
6
6
|
include DynamicQuerying::ClassMethods
|
7
7
|
|
8
8
|
def find(*args)
|
9
|
-
query.find(*scoped_ids(args))
|
9
|
+
order_results(query.find(*scoped_ids(args)))
|
10
10
|
end
|
11
11
|
|
12
12
|
def find!(*args)
|
13
|
-
query.find!(*scoped_ids(args))
|
13
|
+
order_results(query.find!(*scoped_ids(args)))
|
14
14
|
end
|
15
15
|
|
16
16
|
def paginate(options)
|
@@ -20,17 +20,29 @@ module MongoMapper
|
|
20
20
|
|
21
21
|
def all(options={})
|
22
22
|
return [] if ids.blank?
|
23
|
-
query(options).all
|
23
|
+
order_results(query(options).all)
|
24
24
|
end
|
25
25
|
|
26
26
|
def first(options={})
|
27
27
|
return nil if ids.blank?
|
28
|
-
|
28
|
+
|
29
|
+
if ordered?
|
30
|
+
ids = find_ordered_ids(options)
|
31
|
+
find!(ids.first) if ids.any?
|
32
|
+
else
|
33
|
+
query(options).first
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
37
|
def last(options={})
|
32
38
|
return nil if ids.blank?
|
33
|
-
|
39
|
+
|
40
|
+
if ordered?
|
41
|
+
ids = find_ordered_ids(options)
|
42
|
+
find!(ids.last) if ids.any?
|
43
|
+
else
|
44
|
+
query(options).last
|
45
|
+
end
|
34
46
|
end
|
35
47
|
|
36
48
|
def count(options={})
|
@@ -120,6 +132,13 @@ module MongoMapper
|
|
120
132
|
valid.empty? ? nil : valid
|
121
133
|
end
|
122
134
|
|
135
|
+
def find_ordered_ids(options={})
|
136
|
+
return ids if options.empty?
|
137
|
+
|
138
|
+
matched_ids = klass.collection.distinct(:_id, query(options).criteria.to_hash)
|
139
|
+
matched_ids.sort_by! { |matched_id| ids.index(matched_id) }
|
140
|
+
end
|
141
|
+
|
123
142
|
def find_target
|
124
143
|
return [] if ids.blank?
|
125
144
|
all
|
@@ -128,7 +147,18 @@ module MongoMapper
|
|
128
147
|
def ids
|
129
148
|
proxy_owner[options[:in]]
|
130
149
|
end
|
150
|
+
|
151
|
+
def order_results(objects)
|
152
|
+
return objects if !ordered?
|
153
|
+
return objects unless objects.respond_to?(:to_a) && objects.respond_to?(:sort_by)
|
154
|
+
objects.sort_by { |obj| ids.index(obj.id) }
|
155
|
+
end
|
156
|
+
|
157
|
+
def ordered?
|
158
|
+
association.ordered?
|
159
|
+
end
|
160
|
+
|
131
161
|
end
|
132
162
|
end
|
133
163
|
end
|
134
|
-
end
|
164
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Associations
|
5
|
+
class InForeignArrayProxy < Collection
|
6
|
+
include DynamicQuerying::ClassMethods
|
7
|
+
|
8
|
+
def find(*args)
|
9
|
+
query.find(*scoped_ids(args))
|
10
|
+
end
|
11
|
+
|
12
|
+
def find!(*args)
|
13
|
+
query.find!(*scoped_ids(args))
|
14
|
+
end
|
15
|
+
|
16
|
+
def paginate(options)
|
17
|
+
query.paginate(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def all(options={})
|
21
|
+
query(options).all
|
22
|
+
end
|
23
|
+
|
24
|
+
def first(options={})
|
25
|
+
query(options).first
|
26
|
+
end
|
27
|
+
|
28
|
+
def last(options={})
|
29
|
+
query(options).last
|
30
|
+
end
|
31
|
+
|
32
|
+
def count(options={})
|
33
|
+
query(options).count
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy_all(options={})
|
37
|
+
all(options).each do |doc|
|
38
|
+
doc.destroy
|
39
|
+
end
|
40
|
+
reset
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_all(options={})
|
44
|
+
docs = query(options).fields(:_id).all
|
45
|
+
klass.delete(docs.map { |d| d.id })
|
46
|
+
reset
|
47
|
+
end
|
48
|
+
|
49
|
+
def nullify
|
50
|
+
replace([])
|
51
|
+
reset
|
52
|
+
end
|
53
|
+
|
54
|
+
def create(attrs={})
|
55
|
+
doc = klass.create(attrs)
|
56
|
+
if doc.persisted?
|
57
|
+
inverse_association(doc) << proxy_owner
|
58
|
+
doc.save
|
59
|
+
reset
|
60
|
+
end
|
61
|
+
doc
|
62
|
+
end
|
63
|
+
|
64
|
+
def create!(attrs={})
|
65
|
+
doc = klass.create!(attrs)
|
66
|
+
|
67
|
+
if doc.persisted?
|
68
|
+
inverse_association(doc) << proxy_owner
|
69
|
+
doc.save
|
70
|
+
reset
|
71
|
+
end
|
72
|
+
doc
|
73
|
+
end
|
74
|
+
|
75
|
+
def <<(*docs)
|
76
|
+
flatten_deeper(docs).each do |doc|
|
77
|
+
inverse_association(doc) << proxy_owner
|
78
|
+
doc.save
|
79
|
+
end
|
80
|
+
reset
|
81
|
+
end
|
82
|
+
alias_method :push, :<<
|
83
|
+
alias_method :concat, :<<
|
84
|
+
|
85
|
+
def replace(docs)
|
86
|
+
doc_ids = docs.map do |doc|
|
87
|
+
doc.save unless doc.persisted?
|
88
|
+
inverse_association(doc) << proxy_owner
|
89
|
+
doc.save
|
90
|
+
doc.id
|
91
|
+
end
|
92
|
+
|
93
|
+
replace_selector = { options[:from] => proxy_owner.id }
|
94
|
+
unless doc_ids.empty?
|
95
|
+
replace_selector[:_id] = {"$not" => {"$in" => doc_ids}}
|
96
|
+
end
|
97
|
+
|
98
|
+
klass.collection.update_many(replace_selector, {
|
99
|
+
"$pull" => { options[:from] => proxy_owner.id }
|
100
|
+
})
|
101
|
+
|
102
|
+
reset
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def query(options={})
|
108
|
+
klass.query({}.
|
109
|
+
merge(association.query_options).
|
110
|
+
merge(options).
|
111
|
+
merge(criteria))
|
112
|
+
end
|
113
|
+
|
114
|
+
def criteria
|
115
|
+
{options[:from] => proxy_owner.id}
|
116
|
+
end
|
117
|
+
|
118
|
+
def scoped_ids(args)
|
119
|
+
valid = args.flatten.map do |id|
|
120
|
+
id = ObjectId.to_mongo(id) if klass.using_object_id?
|
121
|
+
id
|
122
|
+
end
|
123
|
+
valid.empty? ? nil : valid
|
124
|
+
end
|
125
|
+
|
126
|
+
def find_target
|
127
|
+
all
|
128
|
+
end
|
129
|
+
|
130
|
+
def inverse_association(doc)
|
131
|
+
doc.send(options[:as].to_s.pluralize)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
File without changes
|
File without changes
|
data/lib/mongo_mapper/plugins/associations/{many_embedded_proxy.rb → proxy/many_embedded_proxy.rb}
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/mongo_mapper/plugins/associations/{one_embedded_proxy.rb → proxy/one_embedded_proxy.rb}
RENAMED
@@ -11,7 +11,9 @@ module MongoMapper
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def replace(doc)
|
14
|
-
if doc.
|
14
|
+
if doc.instance_of?(klass)
|
15
|
+
@target = doc
|
16
|
+
elsif doc.respond_to?(:attributes)
|
15
17
|
@target = klass.load(doc.attributes, true)
|
16
18
|
else
|
17
19
|
@target = klass.load(doc, true)
|
File without changes
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module MongoMapper
|
5
|
+
module Plugins
|
6
|
+
module Associations
|
7
|
+
class Proxy
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def define_proxy_method(method)
|
12
|
+
define_method(method) do |*args, &block|
|
13
|
+
proxy_method(method, *args, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :proxy_owner, :association, :target
|
19
|
+
|
20
|
+
alias_method :proxy_respond_to?, :respond_to?
|
21
|
+
alias_method :proxy_extend, :extend
|
22
|
+
alias_method :proxy_association, :association
|
23
|
+
|
24
|
+
def_delegators :proxy_association, :klass, :options
|
25
|
+
def_delegator :klass, :collection
|
26
|
+
|
27
|
+
def initialize(owner, association)
|
28
|
+
@proxy_owner, @association, @loaded = owner, association, false
|
29
|
+
Array(association.options[:extend]).each { |ext| proxy_extend(ext) }
|
30
|
+
reset
|
31
|
+
end
|
32
|
+
|
33
|
+
[
|
34
|
+
:is_a?,
|
35
|
+
:to_mongo,
|
36
|
+
:==,
|
37
|
+
:!=,
|
38
|
+
:nil?,
|
39
|
+
:blank?,
|
40
|
+
:present?,
|
41
|
+
# Active support in rails 3 beta 4 can override to_json after this is loaded,
|
42
|
+
# at least when run in mongomapper tests. The implementation was changed in master
|
43
|
+
# some time after this, so not sure whether this is still a problem.
|
44
|
+
#
|
45
|
+
# In rails 2, this isn't a problem however it also solves an issue where
|
46
|
+
# to_json isn't forwarded because it supports to_json itself
|
47
|
+
:to_json,
|
48
|
+
# see comments to to_json
|
49
|
+
:as_json,
|
50
|
+
].each do |m|
|
51
|
+
define_proxy_method(m)
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
load_target
|
56
|
+
"#<#{self.class.inspect}:#{object_id} #{@target.inspect}>"
|
57
|
+
end
|
58
|
+
|
59
|
+
def loaded?
|
60
|
+
@loaded
|
61
|
+
end
|
62
|
+
|
63
|
+
def loaded
|
64
|
+
@loaded = true
|
65
|
+
end
|
66
|
+
|
67
|
+
def reload
|
68
|
+
reset
|
69
|
+
load_target
|
70
|
+
self unless target.nil?
|
71
|
+
end
|
72
|
+
|
73
|
+
# :nocov:
|
74
|
+
def replace(v)
|
75
|
+
raise NotImplementedError
|
76
|
+
end
|
77
|
+
# :nocov:
|
78
|
+
|
79
|
+
def reset
|
80
|
+
@loaded = false
|
81
|
+
@target = nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def respond_to?(*args)
|
85
|
+
super || (load_target && target.respond_to?(*args))
|
86
|
+
end
|
87
|
+
|
88
|
+
def read
|
89
|
+
load_target
|
90
|
+
@target
|
91
|
+
end
|
92
|
+
|
93
|
+
def write(value)
|
94
|
+
replace(value)
|
95
|
+
read
|
96
|
+
end
|
97
|
+
|
98
|
+
def proxy_method(method, *args, &block)
|
99
|
+
load_target
|
100
|
+
target.public_send(method, *args, &block)
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def load_target
|
106
|
+
if !loaded? || stale_target?
|
107
|
+
if @target.is_a?(Array) && @target.any?
|
108
|
+
@target = find_target + @target.find_all { |record| !record.persisted? }
|
109
|
+
else
|
110
|
+
@target = find_target
|
111
|
+
end
|
112
|
+
loaded
|
113
|
+
end
|
114
|
+
@target
|
115
|
+
rescue MongoMapper::DocumentNotFound
|
116
|
+
reset
|
117
|
+
end
|
118
|
+
|
119
|
+
# :nocov:
|
120
|
+
def find_target
|
121
|
+
raise NotImplementedError
|
122
|
+
end
|
123
|
+
# :nocov:
|
124
|
+
|
125
|
+
def flatten_deeper(array)
|
126
|
+
array.collect do |element|
|
127
|
+
(element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
|
128
|
+
end.flatten
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def stale_target?
|
134
|
+
false
|
135
|
+
end
|
136
|
+
|
137
|
+
def define_proxy_method(method)
|
138
|
+
metaclass = class << self; self; end
|
139
|
+
metaclass.class_eval do
|
140
|
+
define_proxy_method(method)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def define_and_call_proxy_method(method, *args, &block)
|
145
|
+
define_proxy_method(method)
|
146
|
+
public_send(method, *args, &block)
|
147
|
+
end
|
148
|
+
|
149
|
+
def method_missing(method, *args, &block)
|
150
|
+
# load the target just in case it isn't loaded
|
151
|
+
load_target
|
152
|
+
|
153
|
+
# only define the method if the target has the method
|
154
|
+
# NOTE: include private methods!
|
155
|
+
if target.respond_to?(method, true)
|
156
|
+
define_and_call_proxy_method(method, *args, &block)
|
157
|
+
else
|
158
|
+
super
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|