mongo_mapper-unstable 2010.2.9 → 2010.2.10
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/mongo_mapper/document.rb +6 -6
- data/lib/mongo_mapper/plugins/associations/base.rb +26 -24
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -5
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +3 -3
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +2 -2
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +2 -2
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +2 -2
- data/lib/mongo_mapper/plugins/associations/proxy.rb +7 -7
- data/lib/mongo_mapper/plugins/associations.rb +16 -15
- data/lib/mongo_mapper/plugins/identity_map.rb +4 -4
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/pagination.rb +6 -67
- data/lib/mongo_mapper/plugins.rb +15 -14
- data/lib/mongo_mapper/query.rb +130 -0
- data/lib/mongo_mapper/support.rb +9 -11
- data/lib/mongo_mapper.rb +5 -5
- data/mongo_mapper.gemspec +55 -38
- data/test/unit/associations/test_base.rb +4 -4
- data/test/unit/test_pagination.rb +30 -30
- data/test/unit/{test_finder_options.rb → test_query.rb} +71 -66
- data/test/unit/test_support.rb +8 -0
- metadata +6 -5
- data/lib/mongo_mapper/finder_options.rb +0 -127
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2010.02.
|
1
|
+
2010.02.10
|
@@ -71,7 +71,7 @@ module MongoMapper
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def find_each(options={})
|
74
|
-
criteria, options =
|
74
|
+
criteria, options = to_query(options)
|
75
75
|
collection.find(criteria, options).each do |doc|
|
76
76
|
yield load(doc)
|
77
77
|
end
|
@@ -294,7 +294,7 @@ module MongoMapper
|
|
294
294
|
|
295
295
|
# All query methods that load documents pass through find_one or find_many
|
296
296
|
def find_one(options={})
|
297
|
-
criteria, options =
|
297
|
+
criteria, options = to_query(options)
|
298
298
|
if doc = collection.find_one(criteria, options)
|
299
299
|
load(doc)
|
300
300
|
end
|
@@ -302,7 +302,7 @@ module MongoMapper
|
|
302
302
|
|
303
303
|
# All query methods that load documents pass through find_one or find_many
|
304
304
|
def find_many(options)
|
305
|
-
criteria, options =
|
305
|
+
criteria, options = to_query(options)
|
306
306
|
collection.find(criteria, options).to_a.map do |doc|
|
307
307
|
load(doc)
|
308
308
|
end
|
@@ -341,11 +341,11 @@ module MongoMapper
|
|
341
341
|
end
|
342
342
|
|
343
343
|
def to_criteria(options={})
|
344
|
-
|
344
|
+
Query.new(self, options).criteria
|
345
345
|
end
|
346
346
|
|
347
|
-
def
|
348
|
-
|
347
|
+
def to_query(options={})
|
348
|
+
Query.new(self, options).to_a
|
349
349
|
end
|
350
350
|
end
|
351
351
|
|
@@ -2,28 +2,22 @@ module MongoMapper
|
|
2
2
|
module Plugins
|
3
3
|
module Associations
|
4
4
|
class Base
|
5
|
-
attr_reader :type, :name, :options, :
|
5
|
+
attr_reader :type, :name, :options, :query_options
|
6
6
|
|
7
7
|
# Options that should not be considered MongoDB query options/criteria
|
8
8
|
AssociationOptions = [:as, :class, :class_name, :dependent, :extend, :foreign_key, :in, :polymorphic]
|
9
9
|
|
10
10
|
def initialize(type, name, options={}, &extension)
|
11
|
-
@type, @name, @options, @
|
11
|
+
@type, @name, @options, @query_options, @original_options = type, name, {}, {}, options
|
12
12
|
options.symbolize_keys!
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
options.each_pair do |key, value|
|
17
|
-
if AssociationOptions.include?(key)
|
18
|
-
@options[key] = value
|
19
|
-
else
|
20
|
-
@finder_options[key] = value
|
21
|
-
end
|
22
|
-
end
|
13
|
+
options[:extend] = modularized_extensions(extension, options[:extend])
|
14
|
+
separate_options_and_conditions
|
23
15
|
end
|
24
16
|
|
25
17
|
def class_name
|
26
|
-
@class_name
|
18
|
+
return @class_name if defined?(@class_name)
|
19
|
+
|
20
|
+
@class_name =
|
27
21
|
if cn = options[:class_name]
|
28
22
|
cn
|
29
23
|
elsif many?
|
@@ -31,7 +25,6 @@ module MongoMapper
|
|
31
25
|
else
|
32
26
|
name.to_s.camelize
|
33
27
|
end
|
34
|
-
end
|
35
28
|
end
|
36
29
|
|
37
30
|
def klass
|
@@ -39,15 +32,15 @@ module MongoMapper
|
|
39
32
|
end
|
40
33
|
|
41
34
|
def many?
|
42
|
-
@
|
35
|
+
@type == :many
|
43
36
|
end
|
44
37
|
|
45
38
|
def belongs_to?
|
46
|
-
@
|
39
|
+
@type == :belongs_to
|
47
40
|
end
|
48
41
|
|
49
42
|
def one?
|
50
|
-
@
|
43
|
+
@type == :one
|
51
44
|
end
|
52
45
|
|
53
46
|
def polymorphic?
|
@@ -67,7 +60,7 @@ module MongoMapper
|
|
67
60
|
end
|
68
61
|
|
69
62
|
def type_key_name
|
70
|
-
|
63
|
+
many? ? '_type' : "#{as}_type"
|
71
64
|
end
|
72
65
|
|
73
66
|
def as
|
@@ -82,10 +75,13 @@ module MongoMapper
|
|
82
75
|
@ivar ||= "@_#{name}"
|
83
76
|
end
|
84
77
|
|
78
|
+
# hate this, need to revisit
|
85
79
|
def proxy_class
|
86
|
-
@proxy_class
|
80
|
+
return @proxy_class if defined?(@proxy_class)
|
81
|
+
|
82
|
+
@proxy_class =
|
87
83
|
if many?
|
88
|
-
if
|
84
|
+
if klass.embeddable?
|
89
85
|
polymorphic? ? ManyEmbeddedPolymorphicProxy : ManyEmbeddedProxy
|
90
86
|
else
|
91
87
|
if polymorphic?
|
@@ -103,14 +99,20 @@ module MongoMapper
|
|
103
99
|
else
|
104
100
|
polymorphic? ? BelongsToPolymorphicProxy : BelongsToProxy
|
105
101
|
end
|
106
|
-
end
|
107
102
|
end
|
108
103
|
|
109
104
|
private
|
105
|
+
def separate_options_and_conditions
|
106
|
+
@original_options.each_pair do |key, value|
|
107
|
+
if AssociationOptions.include?(key)
|
108
|
+
@options[key] = value
|
109
|
+
else
|
110
|
+
@query_options[key] = value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
110
114
|
|
111
|
-
|
112
|
-
# Procs that extend the behaviour of this association.
|
113
|
-
def modulized_extensions(*extensions)
|
115
|
+
def modularized_extensions(*extensions)
|
114
116
|
extensions.flatten.compact.map do |extension|
|
115
117
|
Proc === extension ? Module.new(&extension) : extension
|
116
118
|
end
|
@@ -10,19 +10,19 @@ module MongoMapper
|
|
10
10
|
id, type = doc.id, doc.class.name
|
11
11
|
end
|
12
12
|
|
13
|
-
owner[
|
14
|
-
owner[
|
13
|
+
owner[association.foreign_key] = id
|
14
|
+
owner[association.type_key_name] = type
|
15
15
|
reset
|
16
16
|
end
|
17
17
|
|
18
18
|
protected
|
19
19
|
def find_target
|
20
|
-
return nil if association_class.nil? || owner[
|
21
|
-
association_class.find_by_id(owner[
|
20
|
+
return nil if association_class.nil? || owner[association.foreign_key].nil?
|
21
|
+
association_class.find_by_id(owner[association.foreign_key])
|
22
22
|
end
|
23
23
|
|
24
24
|
def association_class
|
25
|
-
proxy_owner[
|
25
|
+
proxy_owner[association.type_key_name] ? proxy_owner[association.type_key_name].constantize : nil
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -10,14 +10,14 @@ module MongoMapper
|
|
10
10
|
id = doc.id
|
11
11
|
end
|
12
12
|
|
13
|
-
owner[
|
13
|
+
owner[association.foreign_key] = id
|
14
14
|
reset
|
15
15
|
end
|
16
16
|
|
17
17
|
protected
|
18
18
|
def find_target
|
19
|
-
return nil if owner[
|
20
|
-
klass.find_by_id(owner[
|
19
|
+
return nil if owner[association.foreign_key].nil?
|
20
|
+
klass.find_by_id(owner[association.foreign_key])
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -78,7 +78,7 @@ module MongoMapper
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def nullify
|
81
|
-
criteria =
|
81
|
+
criteria = Query.new(klass, scoped_conditions).criteria
|
82
82
|
all(criteria).each do |doc|
|
83
83
|
doc.update_attributes(self.foreign_key => nil)
|
84
84
|
end
|
@@ -91,7 +91,7 @@ module MongoMapper
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def scoped_options(options)
|
94
|
-
|
94
|
+
association.query_options.merge(options).merge(scoped_conditions)
|
95
95
|
end
|
96
96
|
|
97
97
|
def find_target
|
@@ -4,7 +4,7 @@ module MongoMapper
|
|
4
4
|
class ManyEmbeddedPolymorphicProxy < EmbeddedCollection
|
5
5
|
def replace(values)
|
6
6
|
@_values = values.map do |v|
|
7
|
-
v.respond_to?(:attributes) ? v.attributes.merge(
|
7
|
+
v.respond_to?(:attributes) ? v.attributes.merge(association.type_key_name => v.class.name) : v
|
8
8
|
end
|
9
9
|
reset
|
10
10
|
end
|
@@ -19,7 +19,7 @@ module MongoMapper
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def polymorphic_class(doc)
|
22
|
-
if class_name = doc[
|
22
|
+
if class_name = doc[association.type_key_name]
|
23
23
|
class_name.constantize
|
24
24
|
else
|
25
25
|
klass
|
@@ -46,7 +46,7 @@ module MongoMapper
|
|
46
46
|
|
47
47
|
protected
|
48
48
|
def find_target
|
49
|
-
target_class.first(
|
49
|
+
target_class.first(association.query_options.merge(foreign_key => owner.id))
|
50
50
|
end
|
51
51
|
|
52
52
|
def instantiate_target(instantiator, attrs={})
|
@@ -56,7 +56,7 @@ module MongoMapper
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def target_class
|
59
|
-
@target_class ||= options[:class] || (options[:class_name] ||
|
59
|
+
@target_class ||= options[:class] || (options[:class_name] || association.name.to_s.camelize).constantize
|
60
60
|
end
|
61
61
|
|
62
62
|
def foreign_key
|
@@ -7,19 +7,19 @@ module MongoMapper
|
|
7
7
|
|
8
8
|
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
|
9
9
|
|
10
|
-
attr_reader :owner, :
|
10
|
+
attr_reader :owner, :association, :target
|
11
11
|
|
12
12
|
alias :proxy_owner :owner
|
13
13
|
alias :proxy_target :target
|
14
|
-
alias :
|
14
|
+
alias :proxy_association :association
|
15
15
|
|
16
|
-
delegate :klass, :to => :
|
17
|
-
delegate :options, :to => :
|
16
|
+
delegate :klass, :to => :proxy_association
|
17
|
+
delegate :options, :to => :proxy_association
|
18
18
|
delegate :collection, :to => :klass
|
19
19
|
|
20
|
-
def initialize(owner,
|
21
|
-
@owner, @
|
22
|
-
Array(
|
20
|
+
def initialize(owner, association)
|
21
|
+
@owner, @association, @loaded = owner, association, false
|
22
|
+
Array(association.options[:extend]).each { |ext| proxy_extend(ext) }
|
23
23
|
reset
|
24
24
|
end
|
25
25
|
|
@@ -66,7 +66,7 @@ module MongoMapper
|
|
66
66
|
def associations
|
67
67
|
self.class.associations
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
# @api private?
|
71
71
|
def embedded_associations
|
72
72
|
associations.select do |name, association|
|
@@ -81,24 +81,25 @@ module MongoMapper
|
|
81
81
|
proxy = association.proxy_class.new(self, association)
|
82
82
|
self.instance_variable_set(association.ivar, proxy)
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
proxy
|
86
86
|
end
|
87
87
|
end
|
88
|
+
|
89
|
+
autoload :Base, 'mongo_mapper/plugins/associations/base'
|
90
|
+
autoload :Collection, 'mongo_mapper/plugins/associations/collection'
|
91
|
+
autoload :EmbeddedCollection, 'mongo_mapper/plugins/associations/embedded_collection'
|
92
|
+
autoload :ManyDocumentsProxy, 'mongo_mapper/plugins/associations/many_documents_proxy'
|
93
|
+
autoload :BelongsToProxy, 'mongo_mapper/plugins/associations/belongs_to_proxy'
|
94
|
+
autoload :BelongsToPolymorphicProxy, 'mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy'
|
95
|
+
autoload :ManyPolymorphicProxy, 'mongo_mapper/plugins/associations/many_polymorphic_proxy'
|
96
|
+
autoload :ManyEmbeddedProxy, 'mongo_mapper/plugins/associations/many_embedded_proxy'
|
97
|
+
autoload :ManyEmbeddedPolymorphicProxy, 'mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy'
|
98
|
+
autoload :ManyDocumentsAsProxy, 'mongo_mapper/plugins/associations/many_documents_as_proxy'
|
99
|
+
autoload :OneProxy, 'mongo_mapper/plugins/associations/one_proxy'
|
100
|
+
autoload :InArrayProxy, 'mongo_mapper/plugins/associations/in_array_proxy'
|
88
101
|
end
|
89
102
|
end
|
90
103
|
end
|
91
104
|
|
92
|
-
require 'mongo_mapper/plugins/associations/
|
93
|
-
require 'mongo_mapper/plugins/associations/proxy'
|
94
|
-
require 'mongo_mapper/plugins/associations/collection'
|
95
|
-
require 'mongo_mapper/plugins/associations/embedded_collection'
|
96
|
-
require 'mongo_mapper/plugins/associations/many_documents_proxy'
|
97
|
-
require 'mongo_mapper/plugins/associations/belongs_to_proxy'
|
98
|
-
require 'mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy'
|
99
|
-
require 'mongo_mapper/plugins/associations/many_polymorphic_proxy'
|
100
|
-
require 'mongo_mapper/plugins/associations/many_embedded_proxy'
|
101
|
-
require 'mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy'
|
102
|
-
require 'mongo_mapper/plugins/associations/many_documents_as_proxy'
|
103
|
-
require 'mongo_mapper/plugins/associations/one_proxy'
|
104
|
-
require 'mongo_mapper/plugins/associations/in_array_proxy'
|
105
|
+
require 'mongo_mapper/plugins/associations/proxy'
|
@@ -28,21 +28,21 @@ module MongoMapper
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def find_one(options={})
|
31
|
-
criteria,
|
31
|
+
criteria, query_options = to_query(options)
|
32
32
|
|
33
33
|
if simple_find?(criteria) && identity_map.key?(criteria[:_id])
|
34
34
|
identity_map[criteria[:_id]]
|
35
35
|
else
|
36
36
|
super.tap do |document|
|
37
|
-
remove_documents_from_map(document) if selecting_fields?(
|
37
|
+
remove_documents_from_map(document) if selecting_fields?(query_options)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
def find_many(options)
|
43
|
-
criteria,
|
43
|
+
criteria, query_options = to_query(options)
|
44
44
|
super.tap do |documents|
|
45
|
-
remove_documents_from_map(documents) if selecting_fields?(
|
45
|
+
remove_documents_from_map(documents) if selecting_fields?(query_options)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
module Pagination
|
4
|
+
class Proxy
|
5
|
+
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
|
6
|
+
|
7
|
+
attr_accessor :subject
|
8
|
+
attr_reader :total_entries, :per_page, :current_page
|
9
|
+
alias limit per_page
|
10
|
+
|
11
|
+
def initialize(total_entries, current_page, per_page=nil)
|
12
|
+
@total_entries = total_entries.to_i
|
13
|
+
self.per_page = per_page
|
14
|
+
self.current_page = current_page
|
15
|
+
end
|
16
|
+
|
17
|
+
def total_pages
|
18
|
+
(total_entries / per_page.to_f).ceil
|
19
|
+
end
|
20
|
+
|
21
|
+
def out_of_bounds?
|
22
|
+
current_page > total_pages
|
23
|
+
end
|
24
|
+
|
25
|
+
def previous_page
|
26
|
+
current_page > 1 ? (current_page - 1) : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def next_page
|
30
|
+
current_page < total_pages ? (current_page + 1) : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def skip
|
34
|
+
(current_page - 1) * per_page
|
35
|
+
end
|
36
|
+
alias offset skip # for will paginate support
|
37
|
+
|
38
|
+
def send(method, *args, &block)
|
39
|
+
if respond_to?(method)
|
40
|
+
super
|
41
|
+
else
|
42
|
+
subject.send(method, *args, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def ===(other)
|
47
|
+
other === subject
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing(name, *args, &block)
|
51
|
+
@subject.send(name, *args, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def per_page=(value)
|
56
|
+
value = 25 if value.blank?
|
57
|
+
@per_page = value.to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def current_page=(value)
|
61
|
+
value = value.to_i
|
62
|
+
value = 1 if value < 1
|
63
|
+
@current_page = value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|