Class: GraphQL::Execution::Lookahead
- Inherits:
-
Object
- Object
- GraphQL::Execution::Lookahead
- Defined in:
- lib/graphql/execution/lookahead.rb
Overview
Lookahead creates a uniform interface to inspect the forthcoming selections.
It assumes that the AST it’s working with is valid. (So, it’s safe to use during execution, but if you’re using it directly, be sure to validate first.)
A field may get access to its lookahead by adding extras: [:lookahead]
to its configuration.
Direct Known Subclasses
Defined Under Namespace
Classes: NullLookahead
Constant Summary collapse
- NULL_LOOKAHEAD =
A singleton, so that misses don’t come with overhead.
NullLookahead.new
Instance Attribute Summary collapse
-
#ast_nodes ⇒ Array<GraphQL::Language::Nodes::Field>
readonly
-
#field ⇒ GraphQL::Schema::Field
readonly
-
#owner_type ⇒ GraphQL::Schema::Object, ...
readonly
Instance Method Summary collapse
-
#alias_selection(alias_name, selected_type: @selected_type, arguments: nil) ⇒ GraphQL::Execution::Lookahead
Like #selection, but for aliases.
-
#arguments ⇒ Hash<Symbol, Object>
-
#initialize(query:, ast_nodes:, field: nil, root_type: nil, owner_type: nil) ⇒ Lookahead
constructor
A new instance of Lookahead.
-
#inspect ⇒ Object
-
#name ⇒ Symbol
The method name of the field.
-
#selected? ⇒ Boolean
True if this lookahead represents a field that was requested.
-
#selection(field_name, selected_type: @selected_type, arguments: nil) ⇒ GraphQL::Execution::Lookahead
Like #selects?, but can be used for chaining.
-
#selections(arguments: nil) ⇒ Array<GraphQL::Execution::Lookahead>
Like #selection, but for all nodes.
-
#selects?(field_name, selected_type: @selected_type, arguments: nil) ⇒ Boolean
True if this node has a selection on
field_name
. -
#selects_alias?(alias_name, arguments: nil) ⇒ Boolean
True if this node has a selection with alias matching
alias_name
.
Constructor Details
#initialize(query:, ast_nodes:, field: nil, root_type: nil, owner_type: nil) ⇒ Lookahead
Returns a new instance of Lookahead.
34 35 36 37 38 39 40 41 |
# File 'lib/graphql/execution/lookahead.rb', line 34 def initialize(query:, ast_nodes:, field: nil, root_type: nil, owner_type: nil) @ast_nodes = ast_nodes.freeze @field = field @root_type = root_type @query = query @selected_type = @field ? @field.type.unwrap : root_type @owner_type = owner_type end |
Instance Attribute Details
#ast_nodes ⇒ Array<GraphQL::Language::Nodes::Field> (readonly)
44 45 46 |
# File 'lib/graphql/execution/lookahead.rb', line 44 def ast_nodes @ast_nodes end |
#field ⇒ GraphQL::Schema::Field (readonly)
47 48 49 |
# File 'lib/graphql/execution/lookahead.rb', line 47 def field @field end |
#owner_type ⇒ GraphQL::Schema::Object, ... (readonly)
50 51 52 |
# File 'lib/graphql/execution/lookahead.rb', line 50 def owner_type @owner_type end |
Instance Method Details
#alias_selection(alias_name, selected_type: @selected_type, arguments: nil) ⇒ GraphQL::Execution::Lookahead
Like #selection, but for aliases. It returns a null object (check with #selected?)
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/graphql/execution/lookahead.rb', line 147 def alias_selection(alias_name, selected_type: @selected_type, arguments: nil) alias_cache_key = [alias_name, arguments] return alias_selections[key] if alias_selections.key?(alias_name) alias_node = lookup_alias_node(ast_nodes, alias_name) return NULL_LOOKAHEAD unless alias_node next_field_defn = @query.types.field(selected_type, alias_node.name) alias_arguments = @query.arguments_for(alias_node, next_field_defn) if alias_arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments) alias_arguments = alias_arguments.keyword_arguments end return NULL_LOOKAHEAD if arguments && arguments != alias_arguments alias_selections[alias_cache_key] = lookahead_for_selection(next_field_defn, selected_type, alias_arguments, alias_name) end |
#arguments ⇒ Hash<Symbol, Object>
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/graphql/execution/lookahead.rb', line 53 def arguments if defined?(@arguments) @arguments else @arguments = if @field @query.after_lazy(@query.arguments_for(@ast_nodes.first, @field)) do |args| case args when Execution::Interpreter::Arguments args.keyword_arguments when GraphQL::ExecutionError EmptyObjects::EMPTY_HASH else args end end else nil end end end |
#inspect ⇒ Object
216 217 218 |
# File 'lib/graphql/execution/lookahead.rb', line 216 def inspect "#<GraphQL::Execution::Lookahead #{@field ? "@field=#{@field.path.inspect}": "@root_type=#{@root_type}"} @ast_nodes.size=#{@ast_nodes.size}>" end |
#name ⇒ Symbol
The method name of the field. It returns the method_sym of the Lookahead’s field.
212 213 214 |
# File 'lib/graphql/execution/lookahead.rb', line 212 def name @field && @field.original_name end |
#selected? ⇒ Boolean
Returns True if this lookahead represents a field that was requested.
107 108 109 |
# File 'lib/graphql/execution/lookahead.rb', line 107 def selected? true end |
#selection(field_name, selected_type: @selected_type, arguments: nil) ⇒ GraphQL::Execution::Lookahead
Like #selects?, but can be used for chaining. It returns a null object (check with #selected?)
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/graphql/execution/lookahead.rb', line 115 def selection(field_name, selected_type: @selected_type, arguments: nil) next_field_defn = case field_name when String @query.types.field(selected_type, field_name) when Symbol # Try to avoid the `.to_s` below, if possible all_fields = if selected_type.kind.fields? @query.types.fields(selected_type) else # Handle unions by checking possible @query.types .possible_types(selected_type) .map { |t| @query.types.fields(t) } .tap(&:flatten!) end if (match_by_orig_name = all_fields.find { |f| f.original_name == field_name }) match_by_orig_name else # Symbol#name is only present on 3.0+ sym_s = field_name.respond_to?(:name) ? field_name.name : field_name.to_s guessed_name = Schema::Member::BuildType.camelize(sym_s) @query.types.field(selected_type, guessed_name) end end lookahead_for_selection(next_field_defn, selected_type, arguments) end |
#selections(arguments: nil) ⇒ Array<GraphQL::Execution::Lookahead>
Like #selection, but for all nodes. It returns a list of Lookaheads for all Selections
If arguments:
is provided, each provided key/value will be matched
against the arguments in each selection. This method will filter the selections
if any of the given arguments:
do not match the given selection.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/graphql/execution/lookahead.rb', line 181 def selections(arguments: nil) subselections_by_type = {} subselections_on_type = subselections_by_type[@selected_type] = {} @ast_nodes.each do |node| find_selections(subselections_by_type, subselections_on_type, @selected_type, node.selections, arguments) end subselections = [] subselections_by_type.each do |type, ast_nodes_by_response_key| ast_nodes_by_response_key.each do |response_key, ast_nodes| field_defn = @query.types.field(type, ast_nodes.first.name) lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type) subselections.push(lookahead) end end subselections end |
#selects?(field_name, selected_type: @selected_type, arguments: nil) ⇒ Boolean
True if this node has a selection on field_name
.
If field_name
is a String, it is treated as a GraphQL-style (camelized)
field name and used verbatim. If field_name
is a Symbol, it is
treated as a Ruby-style (underscored) name and camelized before comparing.
If arguments:
is provided, each provided key/value will be matched
against the arguments in the next selection. This method will return false
if any of the given arguments:
are not present and matching in the next selection.
(But, the next selection may contain more than the given arguments.)
86 87 88 |
# File 'lib/graphql/execution/lookahead.rb', line 86 def selects?(field_name, selected_type: @selected_type, arguments: nil) selection(field_name, selected_type: selected_type, arguments: arguments).selected? end |
#selects_alias?(alias_name, arguments: nil) ⇒ Boolean
True if this node has a selection with alias matching alias_name
.
If alias_name
is a String, it is treated as a GraphQL-style (camelized)
field name and used verbatim. If alias_name
is a Symbol, it is
treated as a Ruby-style (underscored) name and camelized before comparing.
If arguments:
is provided, each provided key/value will be matched
against the arguments in the next selection. This method will return false
if any of the given arguments:
are not present and matching in the next selection.
(But, the next selection may contain more than the given arguments.)
102 103 104 |
# File 'lib/graphql/execution/lookahead.rb', line 102 def selects_alias?(alias_name, arguments: nil) alias_selection(alias_name, arguments: arguments).selected? end |