mongoid-eager-loading 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/lib/mongoid-eager-loading/mongoid/criterion/eager_loading.rb +30 -20
- data/lib/mongoid-eager-loading/version.rb +1 -1
- data/spec/mongoid-eager-loading/mongoid/criteria_spec.rb +7 -0
- data/spec/mongoid-eager-loading/mongoid/criterion/eager_loading_spec.rb +91 -47
- metadata +4 -4
data/Gemfile.lock
CHANGED
@@ -10,7 +10,7 @@ module Mongoid
|
|
10
10
|
# <tt>criteria.includes(:user, :post)</tt>
|
11
11
|
#
|
12
12
|
# Returns: <tt>self</tt>
|
13
|
-
attr_accessor :eager_loadings, :
|
13
|
+
attr_accessor :eager_loadings, :id_documents_map, :id_associations_map
|
14
14
|
|
15
15
|
def includes(*options)
|
16
16
|
@eager_loadings = options
|
@@ -18,12 +18,13 @@ module Mongoid
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def preload(documents)
|
21
|
+
return if documents.blank?
|
21
22
|
document_class = documents.first.class
|
22
23
|
@eager_loadings.each do |eager_loading|
|
23
24
|
setup_associations(documents, association_reflection(document_class, eager_loading))
|
24
25
|
end
|
25
26
|
end
|
26
|
-
|
27
|
+
|
27
28
|
private
|
28
29
|
def ignore_includes
|
29
30
|
@eager_loadings = nil
|
@@ -48,19 +49,21 @@ module Mongoid
|
|
48
49
|
def setup_associations_with_ids(documents, reflection, one=true)
|
49
50
|
ids = []
|
50
51
|
documents.each do |document|
|
51
|
-
|
52
|
+
add_id_document(document.id, document)
|
52
53
|
ids << document.id if document.id
|
53
54
|
end
|
54
55
|
|
55
56
|
association_class = reflection.name.singularize.camelize.constantize
|
56
57
|
ignore_includes
|
57
|
-
eager_associations = association_class.where(reflection.foreign_key.to_sym.in => ids).to_a
|
58
|
+
eager_associations = association_class.where(reflection.foreign_key.to_sym.in => ids.uniq).to_a
|
58
59
|
eager_associations.each do |eager_association|
|
59
60
|
add_id_association(eager_association.send(reflection.foreign_key), eager_association)
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
-
|
63
|
+
id_documents_map.each do |id, documents|
|
64
|
+
documents.each do |document|
|
65
|
+
document.instance_variable_set("@#{reflection.name}", one ? id_associations_map[id].first : id_associations_map[id])
|
66
|
+
end
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -70,11 +73,11 @@ module Mongoid
|
|
70
73
|
documents.each do |document|
|
71
74
|
foreign_key_value = document.send(foreign_key_name)
|
72
75
|
if one
|
73
|
-
|
76
|
+
add_id_document(foreign_key_value, document)
|
74
77
|
ids << foreign_key_value if foreign_key_value
|
75
78
|
elsif foreign_key_value
|
76
79
|
foreign_key_value.each do |fkv|
|
77
|
-
|
80
|
+
add_id_document(fkv, document)
|
78
81
|
ids << fkv if fkv
|
79
82
|
end
|
80
83
|
end
|
@@ -82,31 +85,38 @@ module Mongoid
|
|
82
85
|
|
83
86
|
association_class = reflection.name.singularize.camelize.constantize
|
84
87
|
ignore_includes
|
85
|
-
eager_associations = association_class.find(ids).to_a
|
88
|
+
eager_associations = association_class.find(ids.uniq).to_a
|
86
89
|
eager_associations.each do |eager_association|
|
87
90
|
add_id_association(eager_association.id, eager_association)
|
88
91
|
end
|
89
92
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
93
|
+
id_documents_map.each do |id, documents|
|
94
|
+
documents.each do |document|
|
95
|
+
foreign_key_value = document.send(foreign_key_name)
|
96
|
+
associations = \
|
97
|
+
if one
|
98
|
+
id_associations_map[foreign_key_value].first
|
99
|
+
else
|
100
|
+
foreign_key_value.collect { |fkv| id_associations_map[fkv] }.flatten.uniq
|
101
|
+
end
|
102
|
+
document.instance_variable_set("@#{reflection.name}", associations)
|
103
|
+
end
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
102
|
-
def
|
103
|
-
@
|
107
|
+
def id_documents_map
|
108
|
+
@id_documents_map ||= {}
|
104
109
|
end
|
105
110
|
|
106
111
|
def id_associations_map
|
107
112
|
@id_associations_map ||= {}
|
108
113
|
end
|
109
114
|
|
115
|
+
def add_id_document(id, document)
|
116
|
+
id_documents_map[id] ||= []
|
117
|
+
id_documents_map[id] << document
|
118
|
+
end
|
119
|
+
|
110
120
|
def add_id_association(id, association)
|
111
121
|
id_associations_map[id] ||= []
|
112
122
|
id_associations_map[id] << association
|
@@ -23,5 +23,12 @@ describe Mongoid::Criteria do
|
|
23
23
|
criteria.collect(&:title).should == ["Sir", "Madam"]
|
24
24
|
criteria.collect(&:game).should == [@person1.game, @person2.game]
|
25
25
|
end
|
26
|
+
|
27
|
+
it "empty parent objects with include" do
|
28
|
+
Game.destroy_all
|
29
|
+
Person.destroy_all
|
30
|
+
criteria = Person.includes(:game)
|
31
|
+
criteria.collect(&:game).should == []
|
32
|
+
end
|
26
33
|
end
|
27
34
|
end
|
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Mongoid::Criterion::EagerLoading do
|
4
4
|
|
5
5
|
describe "#includes" do
|
6
|
-
|
6
|
+
|
7
7
|
it "should return self" do
|
8
8
|
criteria = Mongoid::Criteria.new(Person)
|
9
9
|
criteria.includes(:game, :posts).should == criteria
|
@@ -23,86 +23,130 @@ describe Mongoid::Criterion::EagerLoading do
|
|
23
23
|
Post.destroy_all
|
24
24
|
Game.destroy_all
|
25
25
|
Person.destroy_all
|
26
|
-
|
27
|
-
person1 = Person.create(:title => "Sir", :age => 100, :aliases => ["D", "Durran"], :ssn => "666666666")
|
28
|
-
person2 = Person.create(:title => "Madam", :age => 1, :ssn => "098-76-5434")
|
29
|
-
|
30
|
-
person1.create_game(:score => 10)
|
31
|
-
person2.create_game(:score => 20)
|
32
|
-
|
33
|
-
person1.posts.create(:title => "post1")
|
34
|
-
person1.posts.create(:title => "post2")
|
35
|
-
person2.posts.create(:title => "post3")
|
36
|
-
person2.posts.create(:title => "post4")
|
37
|
-
|
38
|
-
person1.preferences.create(:name => "preference1")
|
39
|
-
person1.preferences.create(:name => "preference2")
|
40
|
-
person2.preferences.create(:name => "preference3")
|
41
|
-
person2.preferences.create(:name => "preference4")
|
26
|
+
|
27
|
+
@person1 = Person.create(:title => "Sir", :age => 100, :aliases => ["D", "Durran"], :ssn => "666666666")
|
28
|
+
@person2 = Person.create(:title => "Madam", :age => 1, :ssn => "098-76-5434")
|
29
|
+
|
30
|
+
@game1 = @person1.create_game(:score => 10)
|
31
|
+
@game2 = @person2.create_game(:score => 20)
|
32
|
+
|
33
|
+
@post1 = @person1.posts.create(:title => "post1")
|
34
|
+
@post2 = @person1.posts.create(:title => "post2")
|
35
|
+
@post3 = @person2.posts.create(:title => "post3")
|
36
|
+
@post4 = @person2.posts.create(:title => "post4")
|
37
|
+
|
38
|
+
@preference1 = @person1.preferences.create(:name => "preference1")
|
39
|
+
@preference2 = @person1.preferences.create(:name => "preference2")
|
40
|
+
@preference3 = @person2.preferences.create(:name => "preference3")
|
41
|
+
@preference4 = @person2.preferences.create(:name => "preference4")
|
42
42
|
end
|
43
43
|
|
44
44
|
it "preload references_one association" do
|
45
45
|
people = Person.all.to_a
|
46
46
|
games = Game.all.to_a
|
47
47
|
|
48
|
-
complex = stub(:key => :person_id, :operator => "in")
|
49
|
-
Mongoid::Criterion::Complex.expects(:new).with(:key => :person_id, :operator => "in").returns(complex)
|
50
|
-
Game.expects(:where).with(complex => people.collect(&:id)).returns(games)
|
51
|
-
|
52
48
|
criteria = Mongoid::Criteria.new(Person)
|
53
49
|
criteria.includes(:game)
|
54
50
|
criteria.preload(people)
|
55
51
|
|
56
|
-
|
57
|
-
|
52
|
+
id_documents_map = criteria.send(:id_documents_map)
|
53
|
+
id_documents_map[@person1.id].should == [@person1]
|
54
|
+
id_documents_map[@person2.id].should == [@person2]
|
55
|
+
|
56
|
+
id_associations_map = criteria.send(:id_associations_map)
|
57
|
+
id_associations_map[@person1.id].should == [@game1]
|
58
|
+
id_associations_map[@person2.id].should == [@game2]
|
59
|
+
|
60
|
+
@person1.game.should == @game1
|
61
|
+
@person2.game.should == @game2
|
58
62
|
end
|
59
63
|
|
60
64
|
it "preload references_many association" do
|
61
65
|
people = Person.all.to_a
|
62
66
|
posts = Post.all.to_a
|
63
|
-
person1_posts = Post.where(:person_id => people.first.id).to_a
|
64
|
-
person2_posts = Post.where(:person_id => people.last.id).to_a
|
65
67
|
|
66
|
-
complex = stub(:key => :person_id, :operator => "in")
|
67
|
-
Mongoid::Criterion::Complex.expects(:new).with(:key => :person_id, :operator => "in").returns(complex)
|
68
|
-
Post.expects(:where).with(complex => people.collect(&:id)).returns(posts)
|
69
|
-
|
70
68
|
criteria = Mongoid::Criteria.new(Person)
|
71
69
|
criteria.includes(:posts)
|
72
70
|
criteria.preload(people)
|
73
71
|
|
74
|
-
|
75
|
-
|
72
|
+
id_documents_map = criteria.send(:id_documents_map)
|
73
|
+
id_documents_map[@person1.id].should == [@person1]
|
74
|
+
id_documents_map[@person2.id].should == [@person2]
|
75
|
+
|
76
|
+
id_associations_map = criteria.send(:id_associations_map)
|
77
|
+
id_associations_map[@person1.id].should == [@post1, @post2]
|
78
|
+
id_associations_map[@person2.id].should == [@post3, @post4]
|
79
|
+
|
80
|
+
@person1.posts.should == [@post1, @post2]
|
81
|
+
@person2.posts.should == [@post3, @post4]
|
76
82
|
end
|
77
83
|
|
78
84
|
it "preload references_many_as_array association" do
|
79
85
|
people = Person.all.to_a
|
80
86
|
preferences = Preference.all.to_a
|
81
|
-
person1_preferences = Preference.find(people.first.preference_ids).to_a
|
82
|
-
person2_preferences = Preference.find(people.last.preference_ids).to_a
|
83
|
-
|
84
|
-
Preference.expects(:find).with(preferences.collect(&:id)).returns(preferences)
|
85
87
|
|
86
88
|
criteria = Mongoid::Criteria.new(Person)
|
87
89
|
criteria.includes(:preferences)
|
88
90
|
criteria.preload(people)
|
89
91
|
|
90
|
-
|
91
|
-
|
92
|
+
id_documents_map = criteria.send(:id_documents_map)
|
93
|
+
id_documents_map[@preference1.id].should == [@person1]
|
94
|
+
id_documents_map[@preference2.id].should == [@person1]
|
95
|
+
id_documents_map[@preference3.id].should == [@person2]
|
96
|
+
id_documents_map[@preference4.id].should == [@person2]
|
97
|
+
|
98
|
+
id_associations_map = criteria.send(:id_associations_map)
|
99
|
+
id_associations_map[@preference1.id].should == [@preference1]
|
100
|
+
id_associations_map[@preference2.id].should == [@preference2]
|
101
|
+
id_associations_map[@preference3.id].should == [@preference3]
|
102
|
+
id_associations_map[@preference4.id].should == [@preference4]
|
103
|
+
|
104
|
+
@person1.preferences.should == [@preference1, @preference2]
|
105
|
+
@person2.preferences.should == [@preference3, @preference4]
|
92
106
|
end
|
93
107
|
|
94
|
-
|
95
|
-
|
96
|
-
|
108
|
+
context "referenced_in" do
|
109
|
+
it "preload referenced_in association to references_one" do
|
110
|
+
people = Person.all.to_a
|
111
|
+
games = Game.all.to_a
|
112
|
+
|
113
|
+
criteria = Mongoid::Criteria.new(Game)
|
114
|
+
criteria.includes(:person)
|
115
|
+
criteria.preload(games)
|
116
|
+
|
117
|
+
id_documents_map = criteria.send(:id_documents_map)
|
118
|
+
id_documents_map[@person1.id].should == [@game1]
|
119
|
+
id_documents_map[@person2.id].should == [@game2]
|
120
|
+
|
121
|
+
id_associations_map = criteria.send(:id_associations_map)
|
122
|
+
id_associations_map[@person1.id].should == [@person1]
|
123
|
+
id_associations_map[@person2.id].should == [@person2]
|
124
|
+
|
125
|
+
@game1.person.should == @person1
|
126
|
+
@game2.person.should == @person2
|
127
|
+
end
|
128
|
+
|
129
|
+
it "preload referenced_in association to references_many" do
|
130
|
+
people = Person.all.to_a
|
131
|
+
posts = Post.all.to_a
|
132
|
+
|
133
|
+
criteria = Mongoid::Criteria.new(Game)
|
134
|
+
criteria.includes(:person)
|
135
|
+
criteria.preload(posts)
|
136
|
+
|
137
|
+
id_documents_map = criteria.send(:id_documents_map)
|
138
|
+
id_documents_map[@person1.id].should == [@post1, @post2]
|
139
|
+
id_documents_map[@person2.id].should == [@post3, @post4]
|
97
140
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
criteria.includes(:person)
|
102
|
-
criteria.preload(games)
|
141
|
+
id_associations_map = criteria.send(:id_associations_map)
|
142
|
+
id_associations_map[@person1.id].should == [@person1]
|
143
|
+
id_associations_map[@person2.id].should == [@person2]
|
103
144
|
|
104
|
-
|
105
|
-
|
145
|
+
@post1.person.should == @person1
|
146
|
+
@post2.person.should == @person1
|
147
|
+
@post3.person.should == @person2
|
148
|
+
@post4.person.should == @person2
|
149
|
+
end
|
106
150
|
end
|
107
151
|
end
|
108
152
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-eager-loading
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Richard Huang
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-01-19 00:00:00 +08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|