class Graphql::EagerLoad::Builder
Given
- An initial set of includes, a hash - GraphQL query selections - The model corresponding to the type returned by a GraphQL resolver
This module will iterate and recurse into the selctions to find out if any of the fields requested for a given type corresponds to an association on the ActiveRecord model associated with the field's type.
For example given this query
salesOpportunities() {
soldEstimateGroup { estimates { lineItems } }
}
We'd return this “includes” hash
{sold_estimate_group: {estimates: {line_items: {}}}}
And our resolver will use it like `scope.includes(includes)` to prevent N+1s
Attributes
model[R]
selection[R]
Public Class Methods
call(selections:, model:)
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 34 def self.call(selections:, model:) selections.each.with_object({}) do |selection, includes| builder = new(selection: selection, model: model) if builder.association? hash = builder.includes hash[:blob] ||= {} if builder.active_storage_attachment? includes[builder.association_name] = hash else includes.merge!(builder.includes) end end end
new(selection:, model:)
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 48 def initialize(selection:, model:) @selection = selection @model = model end
Public Instance Methods
active_storage_attachment?()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 65 def active_storage_attachment? model.reflect_on_attachment(field_name).present? end
association?()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 57 def association? association.present? end
association_name()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 61 def association_name association.name end
includes()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 53 def includes self.class.call(selections: selection.selections, model: includes_model) end
Private Instance Methods
association()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 79 def association return if use_custom_method? return model.reflect_on_association("#{field_name}_attachment") if active_storage_attachment? model.reflect_on_association(field_name) end
custom_method_defined?()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 96 def custom_method_defined? field_owner.instance_methods.include?(field_name) end
field_name()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 104 def field_name selection.name end
field_owner()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 100 def field_owner selection.field.owner end
ignore_custom_method?()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 90 def ignore_custom_method? return false unless field_owner.respond_to?(:allow_include_builder_fields) field_owner.allow_include_builder_fields&.include?(field_name.to_sym) end
includes_model()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 73 def includes_model return ActiveStorage::Attachment if active_storage_attachment? association&.klass || model end
use_custom_method?()
click to toggle source
# File lib/graphql/eager_load/builder.rb, line 86 def use_custom_method? custom_method_defined? && !ignore_custom_method? end