mongoload 0.0.2 → 0.0.3
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 +4 -4
- data/.travis.yml +2 -2
- data/README.md +47 -7
- data/lib/mongoload.rb +6 -4
- data/lib/mongoload/patches/{mongoid_contextual_mongo_patch.rb → contextual_mongo.rb} +2 -2
- data/lib/mongoload/patches/{mongoid_document_patch.rb → document.rb} +0 -0
- data/lib/mongoload/patches/relations_accessors.rb +35 -0
- data/lib/mongoload/patches/relations_metadata.rb +14 -0
- data/lib/mongoload/patches/relations_options.rb +19 -0
- data/lib/mongoload/patches/relations_targets_enumerable.rb +29 -0
- data/lib/mongoload/relation_loader.rb +1 -1
- data/lib/mongoload/version.rb +1 -1
- data/spec/db/models.rb +1 -1
- data/spec/mongoload/mongoload_spec.rb +67 -15
- metadata +9 -7
- data/lib/mongoload/patches/mongoid_relations_accessors_patch.rb +0 -29
- data/lib/mongoload/patches/mongoid_relations_targets_enumerable_patch.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96fce1e2c2f42caf74c0bfb5674dcf18953aea98
|
4
|
+
data.tar.gz: 01454a26063e7ddecbf4cb7c3948bd634d5abf05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8c5e970c9068f5b18c0bdd0bf6c361b633ca33353b5158961d771e59d9e4e049fa8cd4ab520aa2e21f7cd3d9a85cedf20930ef6de90a7187ca3ce4162d0a142
|
7
|
+
data.tar.gz: de7f5785b893aed061a9ed35221b5b624472edd47ed29253207c07fd5e8226bf54f370b3833f304ba000b6e48ba12325a575d6438e0c366f1ffa94751a1f3584
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Mongoload
|
2
|
-
|
2
|
+
[](https://badge.fury.io/rb/mongoload)
|
3
3
|
[](https://travis-ci.org/karloku/mongoload)
|
4
4
|
|
5
5
|
Mongoload is a gem to perform eager loading automatically for Mongoid, inspired by [Goldiloader](https://github.com/salsify/goldiloader).
|
@@ -18,13 +18,53 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
$ gem install mongoload
|
20
20
|
|
21
|
-
##
|
21
|
+
## Options
|
22
|
+
|
23
|
+
### :auto_include
|
24
|
+
|
25
|
+
Mark if Mongoload should perform eager loading on the relation.
|
26
|
+
Pass ```:auto_include``` option to the definition, the value should be ```true```(by default) or ```false```.
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class User
|
30
|
+
include Mongoid::Document
|
31
|
+
has_one :device, auto_include: false # Do not perform automatic eager loading on :device relation
|
32
|
+
has_many :posts
|
33
|
+
|
34
|
+
field :username
|
35
|
+
end
|
36
|
+
|
37
|
+
# Following call will not trigger automatic eager loading on device
|
38
|
+
User.all.each(&:device)
|
39
|
+
```
|
40
|
+
|
41
|
+
### :fully_load
|
42
|
+
|
43
|
+
Mark if Mongoload should perform eager loading on the relation, when accessed by following methods:
|
44
|
+
|
45
|
+
+ #first
|
46
|
+
+ #last
|
47
|
+
+ #size
|
48
|
+
+ #empty?
|
49
|
+
|
50
|
+
Pass ```:fully_load``` option to the definition, the value should be ```true``` or ```false```(by default).
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class Tag
|
54
|
+
include Mongoid::Document
|
55
|
+
has_and_belongs_to_many :posts, fully_load: true
|
56
|
+
|
57
|
+
field :name
|
58
|
+
end
|
59
|
+
|
60
|
+
# Following calls will trigger automatic eager loading on posts
|
61
|
+
Tag.all.each { |tag| tag.posts.first }
|
62
|
+
Tag.all.each { |tag| tag.posts.last }
|
63
|
+
Tag.all.each { |tag| tag.posts.size }
|
64
|
+
Tag.all.each { |tag| tag.posts.empty? }
|
65
|
+
```
|
22
66
|
|
23
|
-
|
24
|
-
+ size
|
25
|
-
+ first
|
26
|
-
+ last
|
27
|
-
+ option to disable eager loading on specific relation
|
67
|
+
PS: As for ```#second```, ```#third```, ```#fourth```, ```#fifth``` and ```#forty_two``` calls, mongoid will delegate them to the entries of a relation enumerable set, which makes them just same as a ```#to_a``` call.
|
28
68
|
|
29
69
|
## Copyright
|
30
70
|
|
data/lib/mongoload.rb
CHANGED
@@ -3,7 +3,9 @@ require 'mongoid'
|
|
3
3
|
require 'mongoload/version'
|
4
4
|
require 'mongoload/auto_include_context'
|
5
5
|
require 'mongoload/relation_loader'
|
6
|
-
require 'mongoload/patches/
|
7
|
-
require 'mongoload/patches/
|
8
|
-
require 'mongoload/patches/
|
9
|
-
require 'mongoload/patches/
|
6
|
+
require 'mongoload/patches/contextual_mongo'
|
7
|
+
require 'mongoload/patches/document'
|
8
|
+
require 'mongoload/patches/relations_accessors'
|
9
|
+
require 'mongoload/patches/relations_targets_enumerable'
|
10
|
+
require 'mongoload/patches/relations_options'
|
11
|
+
require 'mongoload/patches/relations_metadata'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Mongoload
|
3
|
-
module
|
3
|
+
module ContextWithAutoInclude
|
4
4
|
def documents_for_iteration
|
5
5
|
results = super
|
6
6
|
if results.is_a?(Mongo::Collection::View)
|
@@ -13,4 +13,4 @@ module Mongoload
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
Mongoid::Contextual::Mongo.prepend Mongoload::
|
16
|
+
Mongoid::Contextual::Mongo.prepend Mongoload::ContextWithAutoInclude
|
File without changes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Mongoload
|
3
|
+
module RelationsAccessorsWithAutoInclude
|
4
|
+
private_class_method
|
5
|
+
|
6
|
+
def self.assign_missing_proxy_method(relation)
|
7
|
+
if relation.class == Mongoid::Relations::Targets::Enumerable
|
8
|
+
relation.target.define_singleton_method :relation_metadata do
|
9
|
+
relation.relation_metadata
|
10
|
+
end
|
11
|
+
|
12
|
+
relation.target.define_singleton_method :base do
|
13
|
+
relation.base
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def get_relation(name, metadata, object, reload=false)
|
21
|
+
# has_one and belongs_to will return the value immediately
|
22
|
+
# while other relation are lazy
|
23
|
+
if [Mongoid::Relations::Referenced::In, Mongoid::Relations::Referenced::One].include?(metadata.relation)
|
24
|
+
Mongoload::RelationLoader.load(self, metadata) if !object.is_a?(metadata.klass) && ivar(name) == false
|
25
|
+
end
|
26
|
+
|
27
|
+
result = super
|
28
|
+
result.tap do |relation|
|
29
|
+
Mongoload::RelationsAccessorsWithAutoInclude.assign_missing_proxy_method(relation)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Mongoid::Document.prepend Mongoload::RelationsAccessorsWithAutoInclude
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Mongoload
|
3
|
+
module RelationsMetadataWithOptions
|
4
|
+
def auto_include?
|
5
|
+
fetch(:auto_include, true)
|
6
|
+
end
|
7
|
+
|
8
|
+
def fully_load?
|
9
|
+
fetch(:fully_load, false)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
::Mongoid::Relations::Metadata.include ::Mongoload::RelationsMetadataWithOptions
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Mongoload
|
3
|
+
module RelationsOptions
|
4
|
+
MONGOLOAD_OPTIONS = [
|
5
|
+
:auto_include,
|
6
|
+
:fully_load
|
7
|
+
].freeze
|
8
|
+
|
9
|
+
def validate!(options)
|
10
|
+
options_clone = options.clone
|
11
|
+
MONGOLOAD_OPTIONS.each { |key| options_clone.delete(key) }
|
12
|
+
super(options_clone)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << ::Mongoid::Relations::Options
|
18
|
+
prepend ::Mongoload::RelationsOptions
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Mongoload
|
3
|
+
module RelationsEnumerableWithAutoInclude
|
4
|
+
# methods which trigger Mongoload only when :fully_load is true
|
5
|
+
# other methods delegated to #target will be processed by #unloaded_documents
|
6
|
+
%w(first last size empty?).each do |method|
|
7
|
+
define_method method do
|
8
|
+
if !_loaded? && relation_metadata.fully_load? && Mongoload::RelationLoader.load(base, relation_metadata)
|
9
|
+
base.ivar(relation_metadata.name).public_send(method)
|
10
|
+
else
|
11
|
+
super()
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# perform eager loading when loading unloaded documents
|
19
|
+
def unloaded_documents
|
20
|
+
if !_loaded? && Mongoload::RelationLoader.load(base, relation_metadata)
|
21
|
+
base.ivar(relation_metadata.name)
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Mongoid::Relations::Targets::Enumerable.prepend Mongoload::RelationsEnumerableWithAutoInclude
|
data/lib/mongoload/version.rb
CHANGED
data/spec/db/models.rb
CHANGED
@@ -11,53 +11,53 @@ describe Mongoload do
|
|
11
11
|
let(:user3) do
|
12
12
|
User.create!(username: 'Cathy').tap { |u| u.create_device(uuid: '333') }
|
13
13
|
end
|
14
|
+
let(:build_users) { [user1, user2, user3] }
|
15
|
+
let(:users) { User.all.to_a }
|
16
|
+
let(:devices) { Device.all.to_a }
|
14
17
|
|
15
18
|
let(:tag1) { Tag.create!(name: 'tag1') }
|
16
19
|
let(:tag2) { Tag.create!(name: 'tag2') }
|
17
20
|
let(:tag3) { Tag.create!(name: 'tag3') }
|
18
21
|
let(:tag4) { Tag.create!(name: 'tag4') }
|
22
|
+
let(:tags) { Tag.all.to_a }
|
19
23
|
|
20
24
|
let(:post1) do
|
21
25
|
Post.create!(title: 'post1', user: user1).tap do |p|
|
22
26
|
p.tags << [tag1, tag2]
|
23
27
|
end
|
24
28
|
end
|
25
|
-
|
26
29
|
let(:post2) do
|
27
30
|
Post.create!(title: 'post2', user: user1).tap do |p|
|
28
31
|
p.tags << [tag2, tag3]
|
29
32
|
end
|
30
33
|
end
|
31
|
-
|
32
34
|
let(:post3) do
|
33
35
|
Post.create!(title: 'post3', user: user2).tap do |p|
|
34
36
|
p.tags << [tag1, tag3]
|
35
37
|
end
|
36
38
|
end
|
37
|
-
|
38
39
|
let(:post4) do
|
39
40
|
Post.create!(title: 'post4', user: user2).tap do |p|
|
40
41
|
p.tags << [tag2, tag4]
|
41
42
|
end
|
42
43
|
end
|
43
|
-
|
44
44
|
let(:post5) do
|
45
45
|
Post.create!(title: 'post5', user: user3).tap do |p|
|
46
46
|
p.tags << [tag1, tag4]
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
50
49
|
let(:post6) do
|
51
50
|
Post.create!(title: 'post6', user: user3).tap do |p|
|
52
51
|
p.tags << [tag2, tag4]
|
53
52
|
end
|
54
53
|
end
|
54
|
+
let(:build_posts) { [post1, post2, post3, post4, post5, post6] }
|
55
|
+
let(:posts) { Post.all.to_a }
|
55
56
|
|
56
57
|
describe 'has_one relation' do
|
57
|
-
before {
|
58
|
+
before { build_users }
|
58
59
|
|
59
60
|
it 'should eager load' do
|
60
|
-
users = User.all.to_a
|
61
61
|
users.each do |user|
|
62
62
|
expect(user.ivar(:device)).to be false
|
63
63
|
end
|
@@ -70,10 +70,9 @@ describe Mongoload do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
describe 'has_many relation' do
|
73
|
-
before {
|
73
|
+
before { build_posts }
|
74
74
|
|
75
75
|
it 'should eager load' do
|
76
|
-
users = User.all.to_a
|
77
76
|
users.each do |user|
|
78
77
|
expect(user.posts._loaded?).to be false
|
79
78
|
end
|
@@ -87,10 +86,9 @@ describe Mongoload do
|
|
87
86
|
|
88
87
|
describe 'belongs_to' do
|
89
88
|
context 'inverse of has_one' do
|
90
|
-
before {
|
89
|
+
before { build_users }
|
91
90
|
|
92
91
|
it 'should eager load' do
|
93
|
-
devices = Device.all.to_a
|
94
92
|
devices.each do |device|
|
95
93
|
expect(device.ivar(:user)).to be false
|
96
94
|
end
|
@@ -103,10 +101,9 @@ describe Mongoload do
|
|
103
101
|
end
|
104
102
|
|
105
103
|
context 'inverse of has_many' do
|
106
|
-
before {
|
104
|
+
before { build_posts }
|
107
105
|
|
108
106
|
it 'should eager load' do
|
109
|
-
posts = Post.all.to_a
|
110
107
|
posts.each do |post|
|
111
108
|
expect(post.ivar(:user)).to be false
|
112
109
|
end
|
@@ -120,10 +117,9 @@ describe Mongoload do
|
|
120
117
|
end
|
121
118
|
|
122
119
|
describe 'has_and_belongs_to_many' do
|
123
|
-
before {
|
120
|
+
before { build_posts }
|
124
121
|
|
125
122
|
it 'should eager load' do
|
126
|
-
posts = Post.all.to_a
|
127
123
|
posts.each do |post|
|
128
124
|
expect(post.tags._loaded?).to be false
|
129
125
|
end
|
@@ -134,4 +130,60 @@ describe Mongoload do
|
|
134
130
|
end
|
135
131
|
end
|
136
132
|
end
|
133
|
+
|
134
|
+
describe 'auto_include' do
|
135
|
+
before { build_users }
|
136
|
+
context 'is set to false' do
|
137
|
+
before do
|
138
|
+
UserWithoutAutoInclude = User.clone
|
139
|
+
UserWithoutAutoInclude.has_one :device, auto_include: false
|
140
|
+
end
|
141
|
+
it 'should not eager load' do
|
142
|
+
users = UserWithoutAutoInclude.all.to_a
|
143
|
+
users.each do |user|
|
144
|
+
expect(user.ivar(:device)).to be false
|
145
|
+
end
|
146
|
+
|
147
|
+
users.first.device
|
148
|
+
users[1..-1].each do |user|
|
149
|
+
expect(user.ivar(:device)).to be false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'fully_load' do
|
156
|
+
FULLY_LOAD_METHODS = %w(first last size empty?).freeze
|
157
|
+
before { build_posts }
|
158
|
+
|
159
|
+
context 'is set to true' do
|
160
|
+
FULLY_LOAD_METHODS.each do |method|
|
161
|
+
it "should eager load with ##{method}" do
|
162
|
+
tags.each do |tag|
|
163
|
+
expect(tag.posts._loaded?).to be false
|
164
|
+
end
|
165
|
+
|
166
|
+
tags.first.posts.public_send(method)
|
167
|
+
tags.each do |tag|
|
168
|
+
expect(tag.posts._loaded?).to be true
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'is set to false' do
|
175
|
+
FULLY_LOAD_METHODS.each do |method|
|
176
|
+
it "should not eager load with ##{method}" do
|
177
|
+
posts.each do |post|
|
178
|
+
expect(post.tags._loaded?).to be false
|
179
|
+
end
|
180
|
+
|
181
|
+
posts.first.tags.public_send(method)
|
182
|
+
posts[1..-1].each do |post|
|
183
|
+
expect(post.tags._loaded?).to be false
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
137
189
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoload
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kaloku Sang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mongoid
|
@@ -144,10 +144,12 @@ files:
|
|
144
144
|
- gemfiles/mongoid_master.gemfile
|
145
145
|
- lib/mongoload.rb
|
146
146
|
- lib/mongoload/auto_include_context.rb
|
147
|
-
- lib/mongoload/patches/
|
148
|
-
- lib/mongoload/patches/
|
149
|
-
- lib/mongoload/patches/
|
150
|
-
- lib/mongoload/patches/
|
147
|
+
- lib/mongoload/patches/contextual_mongo.rb
|
148
|
+
- lib/mongoload/patches/document.rb
|
149
|
+
- lib/mongoload/patches/relations_accessors.rb
|
150
|
+
- lib/mongoload/patches/relations_metadata.rb
|
151
|
+
- lib/mongoload/patches/relations_options.rb
|
152
|
+
- lib/mongoload/patches/relations_targets_enumerable.rb
|
151
153
|
- lib/mongoload/relation_loader.rb
|
152
154
|
- lib/mongoload/version.rb
|
153
155
|
- log/.keep
|
@@ -177,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
179
|
version: '0'
|
178
180
|
requirements: []
|
179
181
|
rubyforge_project:
|
180
|
-
rubygems_version: 2.6.
|
182
|
+
rubygems_version: 2.6.4
|
181
183
|
signing_key:
|
182
184
|
specification_version: 4
|
183
185
|
summary: Perform eager loading automatically for Mongoid
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Mongoload
|
3
|
-
module MongoRelationsAccessorsWithAutoInclude
|
4
|
-
private
|
5
|
-
|
6
|
-
def get_relation(name, metadata, object, reload=false)
|
7
|
-
# has_one and belongs_to will return the value immediately
|
8
|
-
# while other relation are lazy
|
9
|
-
if [Mongoid::Relations::Referenced::In, Mongoid::Relations::Referenced::One].include?(metadata.relation)
|
10
|
-
Mongoload::RelationLoader.load(self, metadata) if !object.is_a?(metadata.klass) && ivar(name) == false
|
11
|
-
end
|
12
|
-
|
13
|
-
result = super
|
14
|
-
result.tap do |relation|
|
15
|
-
if relation.class == Mongoid::Relations::Targets::Enumerable
|
16
|
-
relation.target.define_singleton_method :relation_metadata do
|
17
|
-
relation.relation_metadata
|
18
|
-
end
|
19
|
-
|
20
|
-
relation.target.define_singleton_method :base do
|
21
|
-
relation.base
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
Mongoid::Document.prepend Mongoload::MongoRelationsAccessorsWithAutoInclude
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Mongoload
|
3
|
-
module MongoRelationsEnumerableWithAutoInclude
|
4
|
-
private
|
5
|
-
|
6
|
-
def unloaded_documents
|
7
|
-
if Mongoload::RelationLoader.load(base, relation_metadata)
|
8
|
-
base.ivar(relation_metadata.name)
|
9
|
-
else
|
10
|
-
super
|
11
|
-
end
|
12
|
-
rescue NotImplementedError
|
13
|
-
super
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
Mongoid::Relations::Targets::Enumerable.prepend Mongoload::MongoRelationsEnumerableWithAutoInclude
|