Class: ActiveShopifyGraphQL::Response::ResponseMapper

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

Overview

Handles mapping GraphQL responses to model attributes. Refactored to use LoaderContext and unified mapping methods.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context) ⇒ ResponseMapper

Returns a new instance of ResponseMapper.



10
11
12
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 10

def initialize(context)
  @context = context
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



8
9
10
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 8

def context
  @context
end

Instance Method Details

#extract_connection_data(response_data, root_path: nil, parent_instance: nil) ⇒ Object

Extract connection data from GraphQL response for eager loading



39
40
41
42
43
44
45
46
47
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 39

def extract_connection_data(response_data, root_path: nil, parent_instance: nil)
  return {} if @context.included_connections.empty?

  root_path ||= ["data", @context.query_name]
  root_data = response_data.dig(*root_path)
  return {} unless root_data

  extract_connections_from_node(root_data, parent_instance)
end

#extract_connections_from_node(node_data, parent_instance = nil) ⇒ Object

Extract connections from a node (reusable for nested connections)



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 50

def extract_connections_from_node(node_data, parent_instance = nil)
  return {} if @context.included_connections.empty?

  connections = @context.connections
  return {} if connections.empty?

  normalized_includes = Query::QueryBuilder.normalize_includes(@context.included_connections)
  connection_cache = {}

  normalized_includes.each do |connection_name, nested_includes|
    connection_config = connections[connection_name]
    next unless connection_config

    records = extract_connection_records(node_data, connection_config, nested_includes, parent_instance: parent_instance)
    connection_cache[connection_name] = records if records
  end

  connection_cache
end

#map_connection_response(response_data, query_name, connection_config = nil) ⇒ Object

Map root connection response Returns attributes instead of instances



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

def map_connection_response(response_data, query_name, connection_config = nil)
  connection_type = connection_config&.dig(:type) || :connection

  if connection_type == :singular
    node_data = response_data.dig("data", query_name)
    return nil unless node_data

    map_node_to_attributes(node_data)
  else
    nodes = response_data.dig("data", query_name, "nodes")
    return [] unless nodes

    nodes.filter_map do |node_data|
      map_node_to_attributes(node_data) if node_data
    end
  end
end

#map_nested_connection_response(response_data, connection_field_name, parent, connection_config = nil) ⇒ Object

Map nested connection response (when loading via parent query) Returns attributes instead of instances



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 72

def map_nested_connection_response(response_data, connection_field_name, parent, connection_config = nil)
  parent_type = parent.class.graphql_type_for_loader(@context.loader_class)
  parent_query_name = parent_type.camelize(:lower)
  connection_type = connection_config&.dig(:type) || :connection

  if connection_type == :singular
    node_data = response_data.dig("data", parent_query_name, connection_field_name)
    return nil unless node_data

    map_node_to_attributes(node_data)
  else
    nodes = response_data.dig("data", parent_query_name, connection_field_name, "nodes")
    return [] unless nodes

    nodes.filter_map do |node_data|
      map_node_to_attributes(node_data) if node_data
    end
  end
end

#map_node_to_attributes(node_data) ⇒ Object

Map a single node's data to attributes (used for both root and nested)



27
28
29
30
31
32
33
34
35
36
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 27

def map_node_to_attributes(node_data)
  return {} unless node_data

  result = {}
  @context.defined_attributes.each do |attr_name, config|
    value = extract_and_transform_value(node_data, config, attr_name)
    result[attr_name] = value
  end
  result
end

#map_response(response_data, root_path: nil) ⇒ Hash

Map GraphQL response to attributes using declared attribute metadata

Parameters:

  • response_data (Hash)

    The full GraphQL response

  • root_path (Array<String>) (defaults to: nil)

    Path to the data root (e.g., ["data", "customer"])

Returns:

  • (Hash)

    Mapped attributes



18
19
20
21
22
23
24
# File 'lib/active_shopify_graphql/response/response_mapper.rb', line 18

def map_response(response_data, root_path: nil)
  root_path ||= ["data", @context.query_name]
  root_data = response_data.dig(*root_path)
  return {} unless root_data

  map_node_to_attributes(root_data)
end