1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
---
layout: guide
doc_stub: false
search: true
section: Queries
title: Lookahead
desc: Detecting child selections during field resolution
index: 11
---
GraphQL-Ruby 1.9+ includes {{ "GraphQL::Execution::Lookahead" | api_doc }} for checking whether child fields are selected. You can use this to optimize database access, for example, selecting only the _needed_ fields from the database.
## Getting a Lookahead
Add `extras: [:lookahead]` to your field configuration to recieve an injected lookahead:
```ruby
field :files, [Types::File], null: false, extras: [:lookahead]
```
Then, update your resolver method to accept a `lookahead:` argument:
```ruby
def files(lookahead:)
# ...
end
```
That argument will be injected by the GraphQL runtime.
## Using a lookahead
Inside your field resolver, you can use the lookahead to check for child fields. For example, you can check for a __specific selection__:
```ruby
def files(lookahead:)
if lookahead.selects?(:full_path)
# This is a query like `files { fullPath ... }`
else
# This query doesn't have `fullPath`
end
end
```
Or, you can list __all the selected fields__:
```ruby
def files(lookahead:)
all_selections = lookahead.selections.map(&:name)
if all_selections == [:name]
# Only `files { name }` was selected, use a fast cached value:
object.file_names.map { |n| { name: n }}
else
# Lots of fields were selected, fall back to a more resource-intensive approach
FileSystemHelper.load_files_for(object)
end
end
```
Lookaheads are _chainable_, so you can use them to check __nested selections__ too:
```ruby
def files(lookahead:)
if lookahead.selection(:history).selects?(:author)
# For example, `files { history { author { ... } } }`
# We're checking for commit authors, so load those objects appropriately ...
else
# Not selecting commit authors ...
end
end
```
Nested lookaheads return empty objects when there's no selection (not `nil`), so the code above will never have a "no method error on `nil`".
## Lookaheads with connections
If you want to see what selections were made on the items in a connection, you can use nested lookaheads. However, don't forget to check for `edges { node }` _and_ `nodes { ... }`, if you support that shortcut field. For example:
```ruby
field :products, Types::Product.connection_type, null: false, extras: [:lookahead]
def products(lookahead:)
selects_quantity_available = lookahead.selection(:nodes).selects?(:quantity_available) ||
# ^^ check for `products { nodes { quantityAvailable } }`
lookahead.selection(:edges).selection(:node).selects?(:quantity_available)
# ^^ check for `products { edges { node { quantityAvailable } } }`
if selects_quantity_available
# ...
else
# ...
end
end
```
That way, you can check for specific selections on the nodes in a connection.
|