mongoload 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/mongoload.svg)](https://badge.fury.io/rb/mongoload)
|
3
3
|
[![Build Status](https://travis-ci.org/karloku/mongoload.svg?branch=master)](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
|