Class: Pipeloader::ProjectionExtension
- Inherits:
-
GraphQL::Schema::FieldExtension
- Object
- GraphQL::Schema::FieldExtension
- Pipeloader::ProjectionExtension
- Defined in:
- lib/pipeloader/field_exact.rb
Overview
Narrows a returned ActiveRecord::Relation to exactly the columns the query needs — and bails to a whole-row fetch the moment a selected field can’t be proven to read only known columns, so it can never raise MissingAttributeError.
Instance Method Summary collapse
Instance Method Details
#resolve(object:, arguments:, context:) ⇒ Object
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 |
# File 'lib/pipeloader/field_exact.rb', line 42 def resolve(object:, arguments:, context:, **) lookahead = arguments[:lookahead] inner = arguments.key?(:lookahead) ? arguments.reject { |k, _| k == :lookahead } : arguments # A belongs_to is loaded whole-row by `object.assoc`, so resolve it via a # projected query instead (still pipelined). Skipped if the type defines a # custom resolver, or the selection is opaque (then fall through to default). record = object.respond_to?(:object) ? object.object : object if lookahead && record.is_a?(ActiveRecord::Base) && !field.owner.instance_methods(false).include?(field.resolver_method) && (assoc = record.class.reflect_on_association(field.method_str.to_sym))&.belongs_to? fk = record.public_send(assoc.foreign_key) return nil if fk.nil? cols = Pipeloader.project_columns(assoc.klass, lookahead) return assoc.klass.where(assoc.klass.primary_key => fk).select(*cols).first if cols end value = yield(object, inner) return value unless lookahead && value.is_a?(ActiveRecord::Relation) cols = Pipeloader.project_columns(value.klass, lookahead) return value unless cols # opaque field selected -> fetch whole rows # Keep a has_many's foreign key so AR can still group / wire the inverse. if value.respond_to?(:proxy_association) && (proxy = value.proxy_association) cols += Array(proxy.reflection.foreign_key) end value.select(*cols.uniq) end |