mm_eager_includer 0.0.1
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/lib/mongo_mapper/eager_include.rb +194 -0
- metadata +47 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'mongo_mapper'
|
2
|
+
|
3
|
+
module MongoMapper
|
4
|
+
class EagerIncluder
|
5
|
+
class << self
|
6
|
+
def enabled?
|
7
|
+
(@enabled == true || @enabled == false) ? @enabled : true
|
8
|
+
end
|
9
|
+
|
10
|
+
def enabled=(bool)
|
11
|
+
@enabled = bool
|
12
|
+
end
|
13
|
+
|
14
|
+
def eager_include(record_or_records, *association_names, &block)
|
15
|
+
association_names.each do |association_name|
|
16
|
+
new(record_or_records, association_name).eager_include(&block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def write_to_cache(object_id, association_name, value)
|
21
|
+
cache[association_name] ||= {}
|
22
|
+
cache[association_name][object_id] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_from_cache(object_id, association_name)
|
26
|
+
cache[association_name][object_id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear_cache!
|
30
|
+
@cache = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def cache
|
36
|
+
@cache ||= {}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(record_or_records, association_name)
|
41
|
+
@records = Array(record_or_records)
|
42
|
+
|
43
|
+
if @records.length == 0
|
44
|
+
return
|
45
|
+
end
|
46
|
+
|
47
|
+
@association_name = association_name.to_sym
|
48
|
+
@association = @records.first.associations[association_name]
|
49
|
+
if !@association
|
50
|
+
raise "Could not find association `#{association_name}` on instance of #{@records.first.class}"
|
51
|
+
end
|
52
|
+
|
53
|
+
@proxy_class = @association.proxy_class
|
54
|
+
end
|
55
|
+
|
56
|
+
def enabled?
|
57
|
+
self.class.enabled?
|
58
|
+
end
|
59
|
+
|
60
|
+
def eager_include(&block)
|
61
|
+
return if !enabled?
|
62
|
+
|
63
|
+
if @records.length == 0
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
if @proxy_class == MongoMapper::Plugins::Associations::ManyDocumentsProxy
|
68
|
+
eager_include_has_many(&block)
|
69
|
+
elsif @proxy_class == MongoMapper::Plugins::Associations::BelongsToProxy
|
70
|
+
eager_include_belongs_to(&block)
|
71
|
+
elsif @proxy_class == MongoMapper::Plugins::Associations::OneProxy
|
72
|
+
eager_include_has_one(&block)
|
73
|
+
elsif @proxy_class == MongoMapper::Plugins::Associations::InArrayProxy
|
74
|
+
eager_include_has_many_in(&block)
|
75
|
+
else
|
76
|
+
raise NotImplementedError, "#{@proxy_class} not supported yet!"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def setup_association(record, association_name, value)
|
83
|
+
association_name = association_name.to_sym
|
84
|
+
|
85
|
+
self.class.write_to_cache(record.object_id, association_name, value)
|
86
|
+
|
87
|
+
code = <<-CODE
|
88
|
+
def #{association_name}
|
89
|
+
MongoMapper::EagerIncluder.read_from_cache(object_id, :#{association_name})
|
90
|
+
end
|
91
|
+
CODE
|
92
|
+
|
93
|
+
record.instance_eval(code, __FILE__, __LINE__)
|
94
|
+
end
|
95
|
+
|
96
|
+
def foreign_keys
|
97
|
+
@association.options[:in]
|
98
|
+
end
|
99
|
+
|
100
|
+
def foreign_key
|
101
|
+
@association_name.to_s.foreign_key
|
102
|
+
end
|
103
|
+
|
104
|
+
def primary_key
|
105
|
+
@association.options[:foreign_key] || @records.first.class.name.foreign_key
|
106
|
+
end
|
107
|
+
|
108
|
+
def eager_include_has_many(&block)
|
109
|
+
ids = @records.map { |el| el.id }.uniq
|
110
|
+
proxy_records = @association.klass.where({
|
111
|
+
primary_key => {
|
112
|
+
'$in' => ids
|
113
|
+
}
|
114
|
+
}).all
|
115
|
+
|
116
|
+
@records.each do |record|
|
117
|
+
matching_proxy_records = proxy_records.select do |proxy_record|
|
118
|
+
record_or_records = proxy_record.send(primary_key)
|
119
|
+
if record_or_records.is_a?(Array)
|
120
|
+
record_or_records.include?(record.id)
|
121
|
+
else
|
122
|
+
record_or_records == record.id
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
setup_association(record, @association_name, matching_proxy_records)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def eager_include_has_one(&block)
|
131
|
+
ids = @records.map { |el| el.id }.uniq
|
132
|
+
proxy_records = @association.klass.where({
|
133
|
+
primary_key => ids
|
134
|
+
})
|
135
|
+
|
136
|
+
if block
|
137
|
+
proxy_records = block.call(proxy_records)
|
138
|
+
end
|
139
|
+
|
140
|
+
proxy_records = proxy_records.all
|
141
|
+
|
142
|
+
@records.each do |record|
|
143
|
+
matching_proxy_record = proxy_records.detect do |proxy_record|
|
144
|
+
proxy_record.send(primary_key) == record.id
|
145
|
+
end
|
146
|
+
|
147
|
+
setup_association(record, @association_name, matching_proxy_record)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def eager_include_belongs_to(&block)
|
152
|
+
ids = @records.map { |el| el.send(foreign_key) }.uniq
|
153
|
+
|
154
|
+
proxy_records = @association.klass.where({
|
155
|
+
:_id => {
|
156
|
+
'$in' => ids
|
157
|
+
}
|
158
|
+
})
|
159
|
+
|
160
|
+
if block
|
161
|
+
proxy_records = block.call(proxy_records)
|
162
|
+
end
|
163
|
+
|
164
|
+
proxy_records = proxy_records.all
|
165
|
+
|
166
|
+
@records.each do |record|
|
167
|
+
matching_proxy_record = proxy_records.detect do |proxy_record|
|
168
|
+
proxy_record.id == record.send(foreign_key)
|
169
|
+
end
|
170
|
+
|
171
|
+
setup_association(record, @association_name, matching_proxy_record)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def eager_include_has_many_in(&block)
|
176
|
+
ids = @records.map { |el| el.send(foreign_keys) }.flatten.uniq
|
177
|
+
proxy_records = @association.klass.where({
|
178
|
+
'_id' => {
|
179
|
+
'$in' => ids
|
180
|
+
}
|
181
|
+
}).all
|
182
|
+
|
183
|
+
@records.each do |record|
|
184
|
+
proxy_record_ids = record.send(foreign_keys)
|
185
|
+
|
186
|
+
matching_proxy_records = proxy_record_ids.map do |proxy_record_id|
|
187
|
+
proxy_records.detect { |proxy_record| proxy_record.id == proxy_record_id }
|
188
|
+
end
|
189
|
+
|
190
|
+
setup_association(record, @association_name, matching_proxy_records)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mm_eager_includer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Scott Taylor
|
9
|
+
- Andrew Pariser
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: Eager include associations with mongo mapper
|
16
|
+
email: scott@railsnewbie.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/mongo_mapper/eager_include.rb
|
22
|
+
homepage: http://github.com/GoLearnUp/eager_include_mm
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 1.8.24
|
44
|
+
signing_key:
|
45
|
+
specification_version: 3
|
46
|
+
summary: Eager include associations with mongo mapper
|
47
|
+
test_files: []
|