Class: LcpRuby::Presenter::IncludesResolver::LoadingStrategy
- Inherits:
-
Object
- Object
- LcpRuby::Presenter::IncludesResolver::LoadingStrategy
- Defined in:
- lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb
Overview
Holds the resolved eager loading instructions and applies them to an AR scope.
Three separate lists mirror the three ActiveRecord eager loading methods:
- includes: separate query by default (AR may use LEFT JOIN when combined with where/references)
- eager_load: always LEFT OUTER JOIN (needed for WHERE/ORDER on association columns)
- joins: INNER JOIN (used alongside includes for has_many query deps)
Instance Attribute Summary collapse
-
#api_preloads ⇒ Object
readonly
Returns the value of attribute api_preloads.
-
#eager_load ⇒ Object
readonly
Returns the value of attribute eager_load.
-
#includes ⇒ Object
readonly
Returns the value of attribute includes.
-
#joins ⇒ Object
readonly
Returns the value of attribute joins.
Instance Method Summary collapse
-
#apply(scope) ⇒ Object
Chains all loading instructions onto the given AR scope.
-
#apply_api_preloads(records) ⇒ Object
Batch-preloads API associations for materialized records.
- #empty? ⇒ Boolean
-
#initialize(includes: [], eager_load: [], joins: [], api_preloads: []) ⇒ LoadingStrategy
constructor
A new instance of LoadingStrategy.
Constructor Details
#initialize(includes: [], eager_load: [], joins: [], api_preloads: []) ⇒ LoadingStrategy
Returns a new instance of LoadingStrategy.
13 14 15 16 17 18 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 13 def initialize(includes: [], eager_load: [], joins: [], api_preloads: []) @includes = includes @eager_load = eager_load @joins = joins @api_preloads = api_preloads end |
Instance Attribute Details
#api_preloads ⇒ Object (readonly)
Returns the value of attribute api_preloads.
11 12 13 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 11 def api_preloads @api_preloads end |
#eager_load ⇒ Object (readonly)
Returns the value of attribute eager_load.
11 12 13 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 11 def eager_load @eager_load end |
#includes ⇒ Object (readonly)
Returns the value of attribute includes.
11 12 13 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 11 def includes @includes end |
#joins ⇒ Object (readonly)
Returns the value of attribute joins.
11 12 13 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 11 def joins @joins end |
Instance Method Details
#apply(scope) ⇒ Object
Chains all loading instructions onto the given AR scope. When virtual columns add custom .select() to the scope, switches :display dependencies to .preload() to avoid breaking the custom SELECT.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 23 def apply(scope) has_custom_select = scope.respond_to?(:select_values) && scope.select_values.any? if @includes.any? if has_custom_select # .preload() always uses separate queries, unaffected by custom SELECT scope = scope.preload(*@includes) else scope = scope.includes(*@includes) end end if @eager_load.any? if has_custom_select # Merge eager_loaded table columns into existing SELECT so they # survive the custom .select() from virtual columns @eager_load.each do |assoc_name| assoc_name = assoc_name.to_s if assoc_name.is_a?(Symbol) next unless assoc_name.is_a?(String) reflection = scope.klass.reflect_on_association(assoc_name.to_sym) next unless reflection scope = scope.select("#{reflection.klass.table_name}.*") end end scope = scope.eager_load(*@eager_load) end scope = scope.joins(*@joins) if @joins.any? scope end |
#apply_api_preloads(records) ⇒ Object
Batch-preloads API associations for materialized records. Call after the AR scope has been loaded (e.g. after pagination).
56 57 58 59 60 61 62 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 56 def apply_api_preloads(records) return if @api_preloads.empty? || records.blank? @api_preloads.each do |preload| DataSource::ApiPreloader.preload(records, preload[:name], preload[:association]) end end |
#empty? ⇒ Boolean
64 65 66 |
# File 'lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb', line 64 def empty? @includes.empty? && @eager_load.empty? && @joins.empty? && @api_preloads.empty? end |