goldiloader 3.0.2 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cea2be18413e1cc1e5d2dc0a325a808f64165a52
4
- data.tar.gz: b9ea0538d9894df028174a7e081acd5b96b4455b
3
+ metadata.gz: 5f23e35eaad8987983cf1c95ec9c99e281e23715
4
+ data.tar.gz: 9882b6e39452af1d0a9d55b28b7d1d40e3e3513a
5
5
  SHA512:
6
- metadata.gz: 28df2ae2eed0bc12cd4d29458aebbc16cf5f667d2950d8b113bf92859447b75a2380d83abf59ef1b36ec0d707fe3954ef25d12b642b69502850d142aa590607e
7
- data.tar.gz: 1ebb5abe80281c1a76fc3b3dd8eed50367ccde1dce353493d90d7da468750e436c4d273e39e1d1388800d31ba2676e4729fbc37ee271e063267a83b6612c96c5
6
+ metadata.gz: 22065fba51aa33fbc113ddc113a84d998de8b5915108c0dd54a878b182684155b957be4aa86bec6971010ff6f930a94116e4ebc4ff3490e6c0257975e0e26272
7
+ data.tar.gz: 03244b1b7fc590389d9a89a0a5f26376c0198b1e0ce68e5605e5e254ad116e203ae88573da24ca671ed2b5bb44fe0d58cc19f9509a754c462fa9d0e9e2c36129
@@ -4,7 +4,7 @@ require 'active_support/all'
4
4
  require 'active_record'
5
5
  require 'goldiloader/compatibility'
6
6
  require 'goldiloader/auto_include_context'
7
- require 'goldiloader/association_info'
7
+ require 'goldiloader/scope_info'
8
8
  require 'goldiloader/association_options'
9
9
  require 'goldiloader/association_loader'
10
10
  require 'goldiloader/active_record_patches'
@@ -76,6 +76,35 @@ module Goldiloader
76
76
  end
77
77
  ActiveRecord::Relation::Merger.prepend(::Goldiloader::MergerPatch)
78
78
 
79
+ module AssociationReflectionPatch
80
+ def eager_loadable?
81
+ return @eager_loadable if instance_variable_defined?(:@eager_loadable)
82
+
83
+ @eager_loadable = if scope.nil?
84
+ # Associations without any scoping options are eager loadable
85
+ true
86
+ elsif scope.arity > 0
87
+ # The scope will be evaluated for every model instance so it can't
88
+ # be eager loaded
89
+ false
90
+ else
91
+ scope_info = if Goldiloader::Compatibility.rails_4?
92
+ Goldiloader::ScopeInfo.new(klass.unscoped.instance_exec(&scope) || klass.unscoped)
93
+ else
94
+ Goldiloader::ScopeInfo.new(scope_for(klass.unscoped))
95
+ end
96
+ scope_info.auto_include? &&
97
+ !scope_info.limit? &&
98
+ !scope_info.offset? &&
99
+ (!has_one? || !scope_info.order?) &&
100
+ (::Goldiloader::Compatibility.group_eager_loadable? || !scope_info.group?) &&
101
+ (::Goldiloader::Compatibility.from_eager_loadable? || !scope_info.from?)
102
+ end
103
+ end
104
+ end
105
+ ActiveRecord::Reflection::AssociationReflection.include(::Goldiloader::AssociationReflectionPatch)
106
+ ActiveRecord::Reflection::ThroughReflection.include(::Goldiloader::AssociationReflectionPatch)
107
+
79
108
  module AssociationPatch
80
109
  extend ActiveSupport::Concern
81
110
 
@@ -97,25 +126,26 @@ module Goldiloader
97
126
  private
98
127
 
99
128
  def eager_loadable?
100
- association_info = Goldiloader::AssociationInfo.new(self)
101
- association_info.auto_include? &&
102
- !association_info.limit? &&
103
- !association_info.offset? &&
104
- (!association_info.has_one? || !association_info.order?) &&
105
- (::Goldiloader::Compatibility.group_eager_loadable? || !association_info.group?) &&
106
- (::Goldiloader::Compatibility.from_eager_loadable? || !association_info.from?) &&
107
- (::Goldiloader::Compatibility.destroyed_model_associations_eager_loadable? || !owner.destroyed?) &&
108
- !association_info.instance_dependent?
129
+ reflection.eager_loadable? &&
130
+ (::Goldiloader::Compatibility.destroyed_model_associations_eager_loadable? || !owner.destroyed?)
109
131
  end
110
132
 
111
133
  def load_with_auto_include
112
134
  if loaded? && !stale_target?
113
135
  target
114
- elsif auto_include?
136
+ elsif !auto_include?
137
+ yield
138
+ elsif owner.auto_include_context.size == 1
139
+ # Bypassing the preloader for a single model reduces object allocations by ~5% in benchmarks
140
+ result = yield
141
+ # As of https://github.com/rails/rails/commit/bd3b28f7f181dce53e872daa23dda101498b8fb4
142
+ # ActiveRecord does not use ActiveRecord::Relation#exec_queries to resolve association
143
+ # queries
144
+ Goldiloader::AutoIncludeContext.register_models(result)
145
+ result
146
+ else
115
147
  Goldiloader::AssociationLoader.load(owner, reflection.name)
116
148
  target
117
- else
118
- yield
119
149
  end
120
150
  end
121
151
  end
@@ -18,10 +18,10 @@ module Goldiloader
18
18
  end
19
19
 
20
20
  def register
21
- if ::ActiveRecord::VERSION::MAJOR >= 5
22
- ActiveRecord::Associations::Builder::Association.extensions << AssociationBuilderExtension
23
- else
21
+ if Goldiloader::Compatibility.rails_4?
24
22
  ActiveRecord::Associations::Builder::Association.valid_options.concat(OPTIONS)
23
+ else
24
+ ActiveRecord::Associations::Builder::Association.extensions << AssociationBuilderExtension
25
25
  end
26
26
  end
27
27
  end
@@ -4,6 +4,8 @@ module Goldiloader
4
4
  class AutoIncludeContext
5
5
  attr_reader :models
6
6
 
7
+ delegate :size, to: :models
8
+
7
9
  def initialize
8
10
  @models = []
9
11
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Goldiloader
4
+ class ScopeInfo
5
+ attr_reader :scope
6
+
7
+ def initialize(scope)
8
+ @scope = scope
9
+ end
10
+
11
+ def offset?
12
+ scope.offset_value.present?
13
+ end
14
+
15
+ def limit?
16
+ scope.limit_value.present?
17
+ end
18
+
19
+ def auto_include?
20
+ scope.auto_include_value
21
+ end
22
+
23
+ def from?
24
+ if Goldiloader::Compatibility.rails_4?
25
+ scope.from_value.present?
26
+ else
27
+ scope.from_clause.present?
28
+ end
29
+ end
30
+
31
+ def group?
32
+ scope.group_values.present?
33
+ end
34
+
35
+ def order?
36
+ scope.order_values.present?
37
+ end
38
+ end
39
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Goldiloader
4
- VERSION = '3.0.2'
4
+ VERSION = '3.0.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: goldiloader
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Turkel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-05 00:00:00.000000000 Z
11
+ date: 2018-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -64,6 +64,20 @@ dependencies:
64
64
  - - ">="
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: benchmark-ips
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
67
81
  - !ruby/object:Gem::Dependency
68
82
  name: coveralls
69
83
  requirement: !ruby/object:Gem::Requirement
@@ -186,11 +200,11 @@ files:
186
200
  - LICENSE.txt
187
201
  - lib/goldiloader.rb
188
202
  - lib/goldiloader/active_record_patches.rb
189
- - lib/goldiloader/association_info.rb
190
203
  - lib/goldiloader/association_loader.rb
191
204
  - lib/goldiloader/association_options.rb
192
205
  - lib/goldiloader/auto_include_context.rb
193
206
  - lib/goldiloader/compatibility.rb
207
+ - lib/goldiloader/scope_info.rb
194
208
  - lib/goldiloader/version.rb
195
209
  homepage: https://github.com/salsify/goldiloader
196
210
  licenses:
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Goldiloader
4
- class AssociationInfo
5
-
6
- def initialize(association)
7
- @association = association
8
- end
9
-
10
- delegate :association_scope, :reflection, to: :@association
11
-
12
- def has_one? # rubocop:disable Naming/PredicateName
13
- reflection.has_one?
14
- end
15
-
16
- def offset?
17
- association_scope && association_scope.offset_value.present?
18
- end
19
-
20
- def limit?
21
- association_scope && association_scope.limit_value.present?
22
- end
23
-
24
- def auto_include?
25
- association_scope.nil? || association_scope.auto_include_value
26
- end
27
-
28
- def from?
29
- if ActiveRecord::VERSION::MAJOR >= 5
30
- association_scope && association_scope.from_clause.present?
31
- else
32
- association_scope && association_scope.from_value.present?
33
- end
34
- end
35
-
36
- def group?
37
- association_scope && association_scope.group_values.present?
38
- end
39
-
40
- def order?
41
- association_scope && association_scope.order_values.present?
42
- end
43
-
44
- def instance_dependent?
45
- reflection.scope.present? && reflection.scope.arity > 0
46
- end
47
- end
48
- end