ar_lazy_preload 0.1.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +50 -0
- data/Rakefile +8 -0
- data/lib/ar_lazy_preload.rb +20 -0
- data/lib/ar_lazy_preload/associated_context_builder.rb +58 -0
- data/lib/ar_lazy_preload/association_tree_builder.rb +26 -0
- data/lib/ar_lazy_preload/context.rb +54 -0
- data/lib/ar_lazy_preload/ext/association.rb +17 -0
- data/lib/ar_lazy_preload/ext/association_relation.rb +21 -0
- data/lib/ar_lazy_preload/ext/base.rb +17 -0
- data/lib/ar_lazy_preload/ext/merger.rb +37 -0
- data/lib/ar_lazy_preload/ext/relation.rb +63 -0
- data/lib/ar_lazy_preload/version.rb +5 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 18eb45f9e1c299f719a7bdde76d9da3c9de0175919ad71556c4dfee750405d35
|
4
|
+
data.tar.gz: cec719881cff10f3687c8a22461d0b27acf9ab064104cbb5fb380eb6bd836701
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 71d13fa6015289abc893816b695e920fb59c42d96691d5cd86c3ce41c2c5e4bb34e5c6ea343094aabd39136e4e01ef1e88cd1f5e50bf97968f074844b61b3d87
|
7
|
+
data.tar.gz: 5e4e2f0f95b42796d7f165afb7009db76fbbcfa083e2552c2b7c90e7bc9442445d533cdfd498dc8a39b4734e8c0e50641ea8d77f48a429a85568fb0421e72c3c
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 DmitryTsepelev
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
[](https://travis-ci.org/DmitryTsepelev/ar_lazy_preload)
|
2
|
+
[](https://codeclimate.com/github/DmitryTsepelev/ar_lazy_preload/maintainability)
|
3
|
+
[](https://coveralls.io/github/DmitryTsepelev/ar_lazy_preload?branch=master)
|
4
|
+
|
5
|
+
# ArLazyPreload
|
6
|
+
|
7
|
+
Lazy loading associations for the ActiveRecord models. `#includes`, `#eager_load` and `#preload` are built-in methods to avoid N+1 problem, but sometimes when DB request is made we don't know what associations we are going to need later (for instance when your API allows client to define a list of loaded associations dynamically). The only possible solution for such cases is to load _all_ the associations we might need, but it can be a huge overhead.
|
8
|
+
|
9
|
+
This gem allows to set up _lazy_ preloading for associations - it won't load anything until association is called for a first time, but when it happens - it loads all the associated records for all records from the initial relation in a single query.
|
10
|
+
|
11
|
+
For example, if we define a following relation
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
users = User.lazy_preload(:posts).limit(10)
|
15
|
+
```
|
16
|
+
|
17
|
+
and use it in a following way
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
users.map(&:first_name)
|
21
|
+
```
|
22
|
+
|
23
|
+
there will be one query because we've never accessed posts:
|
24
|
+
|
25
|
+
```sql
|
26
|
+
SELECT * FROM users LIMIT 10
|
27
|
+
```
|
28
|
+
|
29
|
+
Hovever, when we try to load posts
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
users.map(&:posts)
|
33
|
+
```
|
34
|
+
|
35
|
+
there will be one more request for posts:
|
36
|
+
|
37
|
+
```sql
|
38
|
+
SELECT * FROM posts WHERE user_id in (...)
|
39
|
+
```
|
40
|
+
|
41
|
+
## Installation
|
42
|
+
|
43
|
+
Add this line to your application's Gemfile, and you're all set:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
gem "ar_lazy_preload"
|
47
|
+
```
|
48
|
+
|
49
|
+
## License
|
50
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ar_lazy_preload/ext/base"
|
4
|
+
require "ar_lazy_preload/ext/relation"
|
5
|
+
require "ar_lazy_preload/ext/association"
|
6
|
+
require "ar_lazy_preload/ext/merger"
|
7
|
+
require "ar_lazy_preload/ext/association_relation"
|
8
|
+
|
9
|
+
module ArLazyPreload
|
10
|
+
ActiveRecord::Base.include(ArLazyPreload::Base)
|
11
|
+
|
12
|
+
ActiveRecord::Relation.prepend(ArLazyPreload::Relation)
|
13
|
+
ActiveRecord::AssociationRelation.prepend(ArLazyPreload::AssociationRelation)
|
14
|
+
ActiveRecord::Relation::Merger.prepend(ArLazyPreload::Merger)
|
15
|
+
|
16
|
+
[
|
17
|
+
ActiveRecord::Associations::CollectionAssociation,
|
18
|
+
ActiveRecord::Associations::Association
|
19
|
+
].each { |klass| klass.prepend(ArLazyPreload::Association) }
|
20
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ar_lazy_preload/association_tree_builder"
|
4
|
+
|
5
|
+
module ArLazyPreload
|
6
|
+
# This class is responsible for building context for associated records. Given a list of records
|
7
|
+
# belonging to the same context and association name it will create and attach a new context to
|
8
|
+
# the associated records based on the parent association tree.
|
9
|
+
class AssociatedContextBuilder
|
10
|
+
attr_reader :parent_context, :association_name
|
11
|
+
|
12
|
+
def initialize(parent_context:, association_name:)
|
13
|
+
@parent_context = parent_context
|
14
|
+
@association_name = association_name
|
15
|
+
end
|
16
|
+
|
17
|
+
delegate :records, :association_tree, :model, to: :parent_context
|
18
|
+
|
19
|
+
# Takes all the associated records for the records, attached to the :parent_context and creates
|
20
|
+
# a preloading context for them
|
21
|
+
def perform
|
22
|
+
return if child_association_tree.blank? || associated_records.blank?
|
23
|
+
|
24
|
+
Context.new(
|
25
|
+
model: reflection.klass,
|
26
|
+
records: associated_records,
|
27
|
+
association_tree: child_association_tree
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def child_association_tree
|
34
|
+
@child_association_tree ||= association_tree_builder.subtree_for(association_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def association_tree_builder
|
38
|
+
@association_tree_builder ||= AssociationTreeBuilder.new(association_tree)
|
39
|
+
end
|
40
|
+
|
41
|
+
def associated_records
|
42
|
+
@associated_records ||=
|
43
|
+
if reflection.collection?
|
44
|
+
record_associations.map(&:target).flatten
|
45
|
+
else
|
46
|
+
record_associations
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def reflection
|
51
|
+
@reflection = model.reflect_on_association(association_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def record_associations
|
55
|
+
@record_associations ||= records.map { |record| record.send(association_name) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArLazyPreload
|
4
|
+
# This class is responsible for building association subtrees from a given association tree
|
5
|
+
# For instance, given a following tree `[:users, { users: :comments }]`,
|
6
|
+
# #subtree_for will build a subtree `[:comments]` when :users argument is passed
|
7
|
+
class AssociationTreeBuilder
|
8
|
+
attr_reader :association_tree
|
9
|
+
|
10
|
+
def initialize(association_tree)
|
11
|
+
@association_tree = association_tree.select { |node| node.is_a?(Hash) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def subtree_for(association)
|
15
|
+
subtree_cache[association]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def subtree_cache
|
21
|
+
@subtree_cache ||= Hash.new do |hash, association|
|
22
|
+
hash[association] = association_tree.map { |node| node[association] }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ar_lazy_preload/associated_context_builder"
|
4
|
+
|
5
|
+
module ArLazyPreload
|
6
|
+
# This class is responsible for holding a connection between a list of ActiveRecord::Base objects
|
7
|
+
# which have been loaded by the same instance of ActiveRecord::Relation. It also contains a tree
|
8
|
+
# of associations, which were requested to be loaded lazily.
|
9
|
+
# Calling #preload_association method will cause loading of ALL associated objects for EACH
|
10
|
+
# ecord when requested association is found in the association tree.
|
11
|
+
class Context
|
12
|
+
attr_reader :model, :records, :association_tree
|
13
|
+
|
14
|
+
# :model - ActiveRecord class which records belong to
|
15
|
+
# :records - array of ActiveRecord instances
|
16
|
+
# :association_tree - list of symbols or hashes representing a tree of preloadable associations
|
17
|
+
def initialize(model:, records:, association_tree:)
|
18
|
+
@model = model
|
19
|
+
@records = records.compact
|
20
|
+
@association_tree = association_tree
|
21
|
+
|
22
|
+
@records.each { |record| record.lazy_preload_context = self }
|
23
|
+
end
|
24
|
+
|
25
|
+
# This method checks if the association is present in the association_tree and preloads for all
|
26
|
+
# objects in the context it if needed.
|
27
|
+
def try_preload_lazily(association_name)
|
28
|
+
return unless association_needs_preload?(association_name)
|
29
|
+
|
30
|
+
preloader.preload(records, association_name)
|
31
|
+
|
32
|
+
AssociatedContextBuilder.new(
|
33
|
+
parent_context: self,
|
34
|
+
association_name: association_name
|
35
|
+
).perform
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def association_needs_preload?(association_name)
|
41
|
+
association_tree.any? do |node|
|
42
|
+
if node.is_a?(Symbol)
|
43
|
+
node == association_name
|
44
|
+
elsif node.is_a?(Hash)
|
45
|
+
node.key?(association_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def preloader
|
51
|
+
@preloader ||= ActiveRecord::Associations::Preloader.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArLazyPreload
|
4
|
+
# ActiveRecord::Association patch with a hook for lazy preloading
|
5
|
+
module Association
|
6
|
+
def load_target
|
7
|
+
owner.try_preload_lazily(association_name)
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def association_name
|
14
|
+
@association_name ||= reflection.name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArLazyPreload
|
4
|
+
# ActiveRecord::AssociationRelation patch for setting up lazy_preload_values based on
|
5
|
+
# owner context
|
6
|
+
module AssociationRelation
|
7
|
+
def initialize(*args)
|
8
|
+
super(*args)
|
9
|
+
|
10
|
+
context = owner.lazy_preload_context
|
11
|
+
return if context.blank?
|
12
|
+
|
13
|
+
association_tree_builder = AssociationTreeBuilder.new(context.association_tree)
|
14
|
+
subtree = association_tree_builder.subtree_for(reflection.name)
|
15
|
+
|
16
|
+
lazy_preload!(subtree)
|
17
|
+
end
|
18
|
+
|
19
|
+
delegate :owner, :reflection, to: :proxy_association
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArLazyPreload
|
4
|
+
# ActiveRecord::Base patch with lazy preloading support
|
5
|
+
module Base
|
6
|
+
def self.included(base)
|
7
|
+
base.class.delegate :lazy_preload, to: :all
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :lazy_preload_context
|
11
|
+
|
12
|
+
# When context has been set, this method would cause preloading association with a given name
|
13
|
+
def try_preload_lazily(association_name)
|
14
|
+
lazy_preload_context.try_preload_lazily(association_name) if lazy_preload_context.present?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArLazyPreload
|
4
|
+
# ActiveRecord::Relation::Merger patch implementing merge functionality
|
5
|
+
# for lazy preloadable relations
|
6
|
+
module Merger
|
7
|
+
# Enhanced #merge implements merging lazy_preload_values
|
8
|
+
def merge
|
9
|
+
result = super
|
10
|
+
|
11
|
+
if other.lazy_preload_values
|
12
|
+
if other.klass == relation.klass
|
13
|
+
merge_lazy_preloads
|
14
|
+
else
|
15
|
+
reflect_and_merge_lazy_preloads
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def merge_lazy_preloads
|
25
|
+
relation.lazy_preload!(*other.lazy_preload_values)
|
26
|
+
end
|
27
|
+
|
28
|
+
def reflect_and_merge_lazy_preloads
|
29
|
+
reflection = relation.klass.reflect_on_all_associations.find do |r|
|
30
|
+
r.class_name == other.klass.name
|
31
|
+
end
|
32
|
+
return unless reflection
|
33
|
+
|
34
|
+
relation.lazy_preload!(reflection.name => other.lazy_preload_values)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ar_lazy_preload/context"
|
4
|
+
|
5
|
+
module ArLazyPreload
|
6
|
+
# ActiveRecord::Relation patch with lazy preloading support
|
7
|
+
module Relation
|
8
|
+
# Enhanced #load method will check if association has not been loaded yet and add a context
|
9
|
+
# for lazy preloading to loaded each record
|
10
|
+
def load
|
11
|
+
need_context = !loaded?
|
12
|
+
old_load_result = super
|
13
|
+
setup_lazy_preload_context if need_context
|
14
|
+
old_load_result
|
15
|
+
end
|
16
|
+
|
17
|
+
# Specify relationships to be loaded lazily when association is loaded for the first time. For
|
18
|
+
# example:
|
19
|
+
#
|
20
|
+
# users = User.lazy_preload(:posts)
|
21
|
+
# users.each do |user|
|
22
|
+
# user.first_name
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# will cause only one SQL request to load users, while
|
26
|
+
#
|
27
|
+
# users = User.lazy_preload(:posts)
|
28
|
+
# users.each do |user|
|
29
|
+
# user.posts.map(&:id)
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# will make an additional query.
|
33
|
+
def lazy_preload(*args)
|
34
|
+
check_if_method_has_arguments!(:lazy_preload, args)
|
35
|
+
spawn.lazy_preload!(*args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def lazy_preload!(*args)
|
39
|
+
args.reject!(&:blank?)
|
40
|
+
args.flatten!
|
41
|
+
self.lazy_preload_values += args
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def lazy_preload_values
|
46
|
+
@lazy_preload_values ||= []
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_writer :lazy_preload_values
|
52
|
+
|
53
|
+
def setup_lazy_preload_context
|
54
|
+
return if lazy_preload_values.blank? || @records.blank?
|
55
|
+
|
56
|
+
ArLazyPreload::Context.new(
|
57
|
+
model: model,
|
58
|
+
records: @records,
|
59
|
+
association_tree: lazy_preload_values
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ar_lazy_preload
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- DmitryTsepelev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-07-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: db-query-matchers
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coveralls
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: database_cleaner
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: factory_bot
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: lazy_preload implementation for ActiveRecord models
|
112
|
+
email:
|
113
|
+
- dmitry.a.tsepelev@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- MIT-LICENSE
|
119
|
+
- README.md
|
120
|
+
- Rakefile
|
121
|
+
- lib/ar_lazy_preload.rb
|
122
|
+
- lib/ar_lazy_preload/associated_context_builder.rb
|
123
|
+
- lib/ar_lazy_preload/association_tree_builder.rb
|
124
|
+
- lib/ar_lazy_preload/context.rb
|
125
|
+
- lib/ar_lazy_preload/ext/association.rb
|
126
|
+
- lib/ar_lazy_preload/ext/association_relation.rb
|
127
|
+
- lib/ar_lazy_preload/ext/base.rb
|
128
|
+
- lib/ar_lazy_preload/ext/merger.rb
|
129
|
+
- lib/ar_lazy_preload/ext/relation.rb
|
130
|
+
- lib/ar_lazy_preload/version.rb
|
131
|
+
homepage: https://github.com/DmitryTsepelev/ar_lazy_preload
|
132
|
+
licenses:
|
133
|
+
- MIT
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '2.3'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 2.7.6
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: lazy_preload implementation for ActiveRecord models
|
155
|
+
test_files: []
|