Class: ActiveShopifyGraphQL::Query::QueryBuilder
- Inherits:
-
Object
- Object
- ActiveShopifyGraphQL::Query::QueryBuilder
- Defined in:
- lib/active_shopify_graphql/query/query_builder.rb
Overview
Builds complete GraphQL queries from a LoaderContext. Handles both fragment construction and query wrapping. Delegates rendering to polymorphic Node subclasses.
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Class Method Summary collapse
- .build_collection_query(context, query_name:, variables:, include_page_info: false) ⇒ Object
- .build_connection_query(context, query_name:, variables:, parent_query: nil, singular: false) ⇒ Object
-
.build_current_customer_query(context, query_name: nil) ⇒ Object
Build a query that doesn't require an ID parameter (e.g., Customer Account API's current customer).
-
.build_paginated_collection_query(context, query_name:, variables:) ⇒ Object
Build a paginated collection query that includes pageInfo for cursor-based pagination.
-
.build_single_record_query(context) ⇒ Object
Class-level factory methods for building complete queries ===.
- .fragment_name(graphql_type) ⇒ Object
- .normalize_includes(includes) ⇒ Object
Instance Method Summary collapse
-
#build_connection_nodes ⇒ Object
Build Node objects for all connections.
-
#build_field_nodes ⇒ Object
Build field nodes from attribute definitions.
-
#build_fragment ⇒ Object
Build a complete fragment node with all fields and connections.
-
#initialize(context) ⇒ QueryBuilder
constructor
A new instance of QueryBuilder.
Constructor Details
#initialize(context) ⇒ QueryBuilder
Returns a new instance of QueryBuilder.
11 12 13 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 11 def initialize(context) @context = context end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
9 10 11 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 9 def context @context end |
Class Method Details
.build_collection_query(context, query_name:, variables:, include_page_info: false) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 42 def self.build_collection_query(context, query_name:, variables:, include_page_info: false) builder = new(context) fragment = builder.build_fragment Node::Collection.new( model_type: context.graphql_type, query_name: query_name, fragment_name: context.fragment_name, variables: variables, fragments: [fragment], include_page_info: include_page_info ).to_s end |
.build_connection_query(context, query_name:, variables:, parent_query: nil, singular: false) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 61 def self.build_connection_query(context, query_name:, variables:, parent_query: nil, singular: false) builder = new(context) fragment = builder.build_fragment if parent_query Node::NestedConnection.new( query_name: query_name, fragment_name: context.fragment_name, variables: variables, parent_query: parent_query, fragments: [fragment], singular: singular ).to_s else Node::RootConnection.new( query_name: query_name, fragment_name: context.fragment_name, variables: variables, fragments: [fragment], singular: singular ).to_s end end |
.build_current_customer_query(context, query_name: nil) ⇒ Object
Build a query that doesn't require an ID parameter (e.g., Customer Account API's current customer)
30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 30 def self.build_current_customer_query(context, query_name: nil) builder = new(context) fragment = builder.build_fragment Node::CurrentCustomer.new( model_type: context.graphql_type, query_name: query_name || context.query_name, fragment_name: context.fragment_name, fragments: [fragment] ).to_s end |
.build_paginated_collection_query(context, query_name:, variables:) ⇒ Object
Build a paginated collection query that includes pageInfo for cursor-based pagination
57 58 59 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 57 def self.build_paginated_collection_query(context, query_name:, variables:) build_collection_query(context, query_name: query_name, variables: variables, include_page_info: true) end |
.build_single_record_query(context) ⇒ Object
Class-level factory methods for building complete queries ===
17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 17 def self.build_single_record_query(context) builder = new(context) fragment = builder.build_fragment Node::SingleRecord.new( model_type: context.graphql_type, query_name: context.query_name, fragment_name: context.fragment_name, fragments: [fragment] ).to_s end |
.fragment_name(graphql_type) ⇒ Object
105 106 107 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 105 def self.fragment_name(graphql_type) "#{graphql_type}Fragment" end |
.normalize_includes(includes) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 85 def self.normalize_includes(includes) includes = Array(includes) includes.each_with_object({}) do |inc, normalized| case inc when Hash inc.each do |key, value| key = key.to_sym normalized[key] ||= [] case value when Hash then normalized[key] << value when Array then normalized[key].concat(value) else normalized[key] << value end end when Symbol, String normalized[inc.to_sym] ||= [] end end end |
Instance Method Details
#build_connection_nodes ⇒ Object
Build Node objects for all connections
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 159 def build_connection_nodes return [] if @context.included_connections.empty? connections = @context.connections return [] if connections.empty? normalized_includes = self.class.normalize_includes(@context.included_connections) normalized_includes.filter_map do |connection_name, nested_includes| connection_config = connections[connection_name] next unless connection_config build_connection_node(connection_config, nested_includes) end end |
#build_field_nodes ⇒ Object
Build field nodes from attribute definitions
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 130 def build_field_nodes path_tree = {} = {} raw_graphql_nodes = [] aliased_field_nodes = [] # Build a tree structure for nested paths @context.defined_attributes.each do |attr_name, config| if config[:raw_graphql] raw_graphql_nodes << build_raw_graphql_node(attr_name, config[:raw_graphql]) elsif config[:is_metafield] (, config) else path = config[:path] if path.include?('.') # Nested path - use tree structure (shared prefixes) build_path_tree(path_tree, path) else # Simple path - add aliased field node aliased_field_nodes << build_aliased_field_node(attr_name, path) end end end # Convert tree to Node objects nodes_from_tree(path_tree) + aliased_field_nodes + () + raw_graphql_nodes end |
#build_fragment ⇒ Object
Build a complete fragment node with all fields and connections
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/active_shopify_graphql/query/query_builder.rb', line 112 def build_fragment raise NotImplementedError, "#{@context.loader_class} must define attributes" if @context.defined_attributes.empty? fragment_node = Node::Fragment.new( name: @context.fragment_name, arguments: { on: @context.graphql_type } ) # Add field nodes from attributes build_field_nodes.each { |node| fragment_node.add_child(node) } # Add connection nodes build_connection_nodes.each { |node| fragment_node.add_child(node) } fragment_node end |