goldiloader 3.0.2 → 3.0.3

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
  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