ar_lazy_preload 0.3.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18865f27f303c041869d4cbeb759d90adde8f2255b970d0752d789b0604f3846
4
- data.tar.gz: f6818b6e38baf72a2bd8881c6727a70fc01a4c90916ed888cf0e51c837858851
3
+ metadata.gz: 0f5333ce93f4dabe64d5f71e9c838c883a7a40f859cec39b80eb60b60f7e0dea
4
+ data.tar.gz: 7795be2e1dc2f6661deeb3b5a014de62b927004c40911ee6dab0299d493efd56
5
5
  SHA512:
6
- metadata.gz: 81e6e8d0dc2ced79052f0b05018a87353abbf416ee234ff6f00c98fa22912a08b4161bece20f78187d25c9221a13ba2f4bea7450916f4f32900e0c60dac99d6e
7
- data.tar.gz: 5f970163332f177b5dbfbbe000fbbca4174bfe822d512ceb3bfa2263a769dfd438d39d7faf2cc516f7d05a7cfb1bd5b2bf1377ec7592312b9a6f7f75e92602fa
6
+ metadata.gz: 4a96f77158652b6cd1923c6e48f7f068f0d12950ad918718229b0bb2763c4c90183a6dadfdcff043be84a5eb06129efa199530648c009c326f0415616658b7d6
7
+ data.tar.gz: e3aadc85c581e91a17642547e2527f0b210e4a899f2bb0be2d77c2589fd9016fe811910af53232bf222bf223312261b38a6a1d7b29ff9e85a8efd94b8e49990c
data/README.md CHANGED
@@ -44,6 +44,22 @@ ArLazyPreload.config.auto_preload = true
44
44
 
45
45
  After that there is no need to call `#lazy_preload` on the association, everything would be loaded lazily.
46
46
 
47
+ If you want to turn automatic preload off for a specific record, you can call `.skip_preload` before any associations method:
48
+
49
+ ```ruby
50
+ users.first.skip_preload.posts # => SELECT * FROM posts WHERE user_id = ?
51
+ ```
52
+
53
+ ### Relation auto preloading
54
+
55
+ Another alternative for auto preloading is using relation `#preload_associations_lazily` method
56
+
57
+ ```ruby
58
+ posts = User.preload_associations_lazily.flat_map(&:posts)
59
+ # => SELECT * FROM users LIMIT 10
60
+ # => SELECT * FROM posts WHERE user_id in (...)
61
+ ```
62
+
47
63
  ## Installation
48
64
 
49
65
  Add this line to your application's Gemfile, and you're all set:
@@ -16,6 +16,7 @@ module ArLazyPreload
16
16
 
17
17
  def setup_preloading_context
18
18
  return if lazy_preload_context.nil?
19
+ return if lazy_preload_context.association_tree.nil?
19
20
 
20
21
  association_tree_builder = AssociationTreeBuilder.new(lazy_preload_context.association_tree)
21
22
  subtree = association_tree_builder.subtree_for(reflection.name)
@@ -5,10 +5,17 @@ module ArLazyPreload
5
5
  module Base
6
6
  def self.included(base)
7
7
  base.class.delegate :lazy_preload, to: :all
8
+ base.class.delegate :preload_associations_lazily, to: :all
8
9
  end
9
10
 
10
11
  attr_accessor :lazy_preload_context
11
12
 
12
13
  delegate :try_preload_lazily, to: :lazy_preload_context, allow_nil: true
14
+
15
+ def skip_preload
16
+ lazy_preload_context&.records&.delete(self)
17
+ self.lazy_preload_context = nil
18
+ self
19
+ end
13
20
  end
14
21
  end
@@ -8,7 +8,7 @@ module ArLazyPreload
8
8
  def merge
9
9
  result = super
10
10
 
11
- if other.lazy_preload_values
11
+ if other.lazy_preload_values.any?
12
12
  if other.klass == relation.klass
13
13
  merge_lazy_preloads
14
14
  else
@@ -5,6 +5,8 @@ require "ar_lazy_preload/context"
5
5
  module ArLazyPreload
6
6
  # ActiveRecord::Relation patch with lazy preloading support
7
7
  module Relation
8
+ attr_writer :preloads_associations_lazily
9
+
8
10
  # Enhanced #load method will check if association has not been loaded yet and add a context
9
11
  # for lazy preloading to loaded each record
10
12
  def load
@@ -13,12 +15,25 @@ module ArLazyPreload
13
15
  if need_context
14
16
  Context.register(
15
17
  records: ar_lazy_preload_records,
16
- association_tree: lazy_preload_values
18
+ association_tree: lazy_preload_values,
19
+ auto_preload: preloads_associations_lazily?
17
20
  )
18
21
  end
19
22
  result
20
23
  end
21
24
 
25
+ # Lazily autoloads all associations. For example:
26
+ #
27
+ # users = User.preload_associations_lazily
28
+ # users.each do |user|
29
+ # user.posts.flat_map {|post| post.comments.map(&:id)}
30
+ # end
31
+ #
32
+ # Same effect can be achieved by User.lazy_preload(posts: :comments)
33
+ def preload_associations_lazily
34
+ spawn.tap { |relation| relation.preloads_associations_lazily = true }
35
+ end
36
+
22
37
  # Specify relationships to be loaded lazily when association is loaded for the first time. For
23
38
  # example:
24
39
  #
@@ -56,6 +71,10 @@ module ArLazyPreload
56
71
  @records
57
72
  end
58
73
 
74
+ def preloads_associations_lazily?
75
+ @preloads_associations_lazily ||= false
76
+ end
77
+
59
78
  attr_writer :lazy_preload_values
60
79
  end
61
80
  end
@@ -8,8 +8,8 @@ module ArLazyPreload
8
8
  # the associated records based on the parent association tree.
9
9
  class AssociatedContextBuilder
10
10
  # Initiates lazy preload context the records loaded lazily
11
- def self.prepare(*args)
12
- new(*args).perform
11
+ def self.prepare(**args)
12
+ new(**args).perform
13
13
  end
14
14
 
15
15
  attr_reader :parent_context, :association_name
@@ -23,6 +23,7 @@ module ArLazyPreload
23
23
 
24
24
  # Takes all the associated records for the records, attached to the :parent_context and creates
25
25
  # a preloading context for them
26
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
26
27
  def perform
27
28
  associated_records = parent_context.records.flat_map do |record|
28
29
  next if record.nil?
@@ -32,14 +33,19 @@ module ArLazyPreload
32
33
  reflection.collection? ? record_association.target : record_association.reader
33
34
  end
34
35
 
35
- Context.register(records: associated_records, association_tree: child_association_tree)
36
+ Context.register(
37
+ records: associated_records,
38
+ association_tree: child_association_tree,
39
+ auto_preload: parent_context.auto_preload?
40
+ )
36
41
  end
42
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
37
43
 
38
44
  private
39
45
 
40
46
  def child_association_tree
41
47
  # `association_tree` is unnecessary when auto preload is enabled
42
- return nil if ArLazyPreload.config.auto_preload?
48
+ return nil if parent_context.auto_preload?
43
49
 
44
50
  AssociationTreeBuilder.new(parent_context.association_tree).subtree_for(association_name)
45
51
  end
@@ -7,10 +7,10 @@ require "ar_lazy_preload/contexts/lazy_preload_context"
7
7
  module ArLazyPreload
8
8
  class Context
9
9
  # Initiates lazy preload context for given records
10
- def self.register(records:, association_tree:)
10
+ def self.register(records:, association_tree:, auto_preload: false)
11
11
  return if records.empty?
12
12
 
13
- if ArLazyPreload.config.auto_preload?
13
+ if ArLazyPreload.config.auto_preload? || auto_preload
14
14
  Contexts::AutoPreloadContext.new(records: records)
15
15
  elsif association_tree.any?
16
16
  Contexts::LazyPreloadContext.new(
@@ -4,6 +4,10 @@ module ArLazyPreload
4
4
  module Contexts
5
5
  # This class is responsible for automatic association preloading
6
6
  class AutoPreloadContext < BaseContext
7
+ def auto_preload?
8
+ true
9
+ end
10
+
7
11
  protected
8
12
 
9
13
  def association_needs_preload?(_association_name)
@@ -19,6 +19,9 @@ module ArLazyPreload
19
19
  @records.each { |record| record.lazy_preload_context = self }
20
20
  end
21
21
 
22
+ # @api
23
+ def association_tree; nil; end
24
+
22
25
  # This method checks if the association should be loaded and preloads it for all
23
26
  # objects in the context it if needed.
24
27
  def try_preload_lazily(association_name)
@@ -28,6 +31,10 @@ module ArLazyPreload
28
31
  perform_preloading(association_name)
29
32
  end
30
33
 
34
+ def auto_preload?
35
+ false
36
+ end
37
+
31
38
  protected
32
39
 
33
40
  def association_needs_preload?(_association_name)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArLazyPreload
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_lazy_preload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-14 00:00:00.000000000 Z
11
+ date: 2020-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 0.81.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: 0.81.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: db-query-matchers
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -196,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
196
  - !ruby/object:Gem::Version
197
197
  version: '0'
198
198
  requirements: []
199
- rubygems_version: 3.0.3
199
+ rubygems_version: 3.1.2
200
200
  signing_key:
201
201
  specification_version: 4
202
202
  summary: lazy_preload implementation for ActiveRecord models