Class: LcpRuby::Presenter::IncludesResolver::StrategyResolver
- Inherits:
-
Object
- Object
- LcpRuby::Presenter::IncludesResolver::StrategyResolver
- Defined in:
- lib/lcp_ruby/presenter/includes_resolver/strategy_resolver.rb
Overview
Maps a collection of AssociationDependency objects into a LoadingStrategy.
Strategy matrix:
display only query (or both)
belongs_to/has_one includes eager_load has_many includes joins + includes
Rationale: eager_load on has_many causes cartesian products that break Kaminari pagination. Using joins (for query) + includes (for preload) avoids this.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(dependencies, model_def) ⇒ StrategyResolver
constructor
A new instance of StrategyResolver.
- #resolve ⇒ Object
Constructor Details
#initialize(dependencies, model_def) ⇒ StrategyResolver
Returns a new instance of StrategyResolver.
22 23 24 25 |
# File 'lib/lcp_ruby/presenter/includes_resolver/strategy_resolver.rb', line 22 def initialize(dependencies, model_def) @dependencies = dependencies @model_def = model_def end |
Class Method Details
.resolve(dependencies, model_def) ⇒ LoadingStrategy
18 19 20 |
# File 'lib/lcp_ruby/presenter/includes_resolver/strategy_resolver.rb', line 18 def self.resolve(dependencies, model_def) new(dependencies, model_def).resolve end |
Instance Method Details
#resolve ⇒ Object
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/lcp_ruby/presenter/includes_resolver/strategy_resolver.rb', line 27 def resolve includes_list = [] eager_load_list = [] joins_list = [] api_preloads_list = [] # Group dependencies by association name to determine combined reason grouped = @dependencies.group_by(&:association_name) grouped.each do |assoc_name, deps| assoc = @model_def.associations.find { |a| a.name == assoc_name.to_s } assoc_type = resolve_assoc_type(assoc, assoc_name) next unless assoc_type # Check if this association targets an API model (cross-source) if assoc && api_target?(assoc) api_preloads_list << { name: assoc_name.to_s, association: assoc } next end has_query = deps.any?(&:query?) # Use the most nested path among the deps for this association path = select_path(deps) if has_query # Query reason: need JOIN for WHERE/ORDER if assoc_type == "has_many" # has_many + query: joins for query, includes for preload joins_list << path includes_list << path else # belongs_to/has_one + query: eager_load (LEFT JOIN) eager_load_list << path end else # Display only: includes (separate query or LEFT JOIN, AR decides) includes_list << path end end LoadingStrategy.new( includes: includes_list.uniq, eager_load: eager_load_list.uniq, joins: joins_list.uniq, api_preloads: api_preloads_list ) end |