Class: ActiveShopifyGraphQL::Loader

Inherits:
Object
  • Object
show all
Defined in:
lib/active_shopify_graphql/loader.rb

Overview

The Loader acts as a stateless orchestrator that:

  • Receives a model class and delegates to it for GraphQL type and attribute definitions
  • Builds a LoaderContext that encapsulates all query-building parameters
  • Delegates query construction to Query::QueryBuilder
  • Delegates response mapping to Response::ResponseMapper
  • Executes GraphQL queries via subclass-specific implementations (perform_graphql_query)

Subclass Requirements

Subclasses must implement:

  • perform_graphql_query(query, **variables) - Execute the query against the appropriate API

Usage

loader = AdminApiLoader.new(Customer, selected_attributes: [:id, :email])
attributes = loader.load_attributes("gid://shopify/Customer/123")
customer = Customer.new(attributes)

Instance Method Summary collapse

Constructor Details

#initialize(model_class, selected_attributes: nil, included_connections: nil) ⇒ Loader

Initialize loader with model class and configuration



30
31
32
33
34
# File 'lib/active_shopify_graphql/loader.rb', line 30

def initialize(model_class, selected_attributes: nil, included_connections: nil, **)
  @model_class = model_class
  @selected_attributes = selected_attributes&.map(&:to_sym)
  @included_connections = included_connections || []
end

Instance Method Details

#contextObject

Build the LoaderContext for this loader instance



37
38
39
40
41
42
43
44
45
# File 'lib/active_shopify_graphql/loader.rb', line 37

def context
  @context ||= LoaderContext.new(
    graphql_type: resolve_graphql_type,
    loader_class: self.class,
    defined_attributes: defined_attributes,
    model_class: @model_class,
    included_connections: @included_connections
  )
end

#defined_attributesObject

Get defined attributes for this loader instance



48
49
50
# File 'lib/active_shopify_graphql/loader.rb', line 48

def defined_attributes
  filter_selected_attributes(@model_class.attributes_for_loader(self.class))
end

#execute_query(query, **variables) ⇒ Object



120
121
122
123
# File 'lib/active_shopify_graphql/loader.rb', line 120

def execute_query(query, **variables)
  log_query(self.class.name, query, variables)
  perform_graphql_query(query, **variables)
end

#has_included_connections?Boolean

Check if this loader has included connections

Returns:

  • (Boolean)


68
69
70
# File 'lib/active_shopify_graphql/loader.rb', line 68

def has_included_connections?
  @included_connections&.any?
end

#initialization_argsArray

Returns the arguments needed to initialize a new loader of the same type Subclasses should override this if they require additional initialization arguments

Returns:

  • (Array)

    Array of arguments to pass to the loader initializer



55
56
57
# File 'lib/active_shopify_graphql/loader.rb', line 55

def initialization_args
  []
end

#load_attributes(id) ⇒ Hash?

Executes the GraphQL query and returns the mapped attributes hash

Parameters:

  • id (String)

    The GID of the record to load

Returns:

  • (Hash, nil)

    Attribute hash with connection cache, or nil if not found



75
76
77
78
79
80
81
# File 'lib/active_shopify_graphql/loader.rb', line 75

def load_attributes(id)
  query = Query::QueryBuilder.build_single_record_query(context)
  response_data = perform_graphql_query(query, id: id)
  return nil if response_data.nil?

  map_response_to_attributes(response_data)
end

#load_connection_records(query_name, variables, parent = nil, connection_config = nil) ⇒ Object

Load records for a connection query



115
116
117
118
# File 'lib/active_shopify_graphql/loader.rb', line 115

def load_connection_records(query_name, variables, parent = nil, connection_config = nil)
  connection_loader = Connections::ConnectionLoader.new(context, loader_instance: self)
  connection_loader.load_records(query_name, variables, parent, connection_config)
end

#load_paginated_collection(conditions:, per_page:, query_scope:, after: nil, before: nil, sort_key: nil, reverse: nil) ⇒ PaginatedResult

Executes a paginated collection query that returns attributes and page info Executes a paginated collection query that returns attributes and page info

Parameters:

  • conditions (Hash)

    Search conditions

  • per_page (Integer)

    Number of records per page

  • after (String, nil) (defaults to: nil)

    Cursor to fetch records after

  • before (String, nil) (defaults to: nil)

    Cursor to fetch records before

  • sort_key (String, nil) (defaults to: nil)

    The Shopify sort key (e.g., "CREATED_AT")

  • reverse (Boolean, nil) (defaults to: nil)

    Whether to reverse the sort order

  • query_scope (Query::Scope)

    The query scope for navigation

Returns:

  • (PaginatedResult)

    A paginated result with attribute hashes and page info



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/active_shopify_graphql/loader.rb', line 93

def load_paginated_collection(conditions:, per_page:, query_scope:, after: nil, before: nil, sort_key: nil, reverse: nil)
  collection_query_name = context.query_name.pluralize
  variables = build_collection_variables(
    conditions,
    per_page: per_page,
    after: after,
    before: before,
    sort_key: sort_key,
    reverse: reverse
  )

  query = Query::QueryBuilder.build_paginated_collection_query(
    context,
    query_name: collection_query_name,
    variables: variables
  )

  response = execute_query_and_validate_search_response(query, **variables)
  map_paginated_response(response, collection_query_name, query_scope)
end

#map_response_to_attributes(response_data, parent_instance: nil) ⇒ Object

Map the GraphQL response to model attributes



60
61
62
63
64
65
# File 'lib/active_shopify_graphql/loader.rb', line 60

def map_response_to_attributes(response_data, parent_instance: nil)
  mapper = Response::ResponseMapper.new(context)
  attributes = mapper.map_response(response_data)
  cache_connections(mapper, response_data, target: attributes, parent_instance: parent_instance)
  attributes
end

#perform_graphql_query(query, **variables) ⇒ Object

Abstract method for executing GraphQL queries

Raises:

  • (NotImplementedError)


126
127
128
# File 'lib/active_shopify_graphql/loader.rb', line 126

def perform_graphql_query(query, **variables)
  raise NotImplementedError, "#{self.class} must implement perform_graphql_query"
end