graphql-ruby-client
Advanced tools
Changelog
1.6.0 (27 May 2017)
InternalRepresentation::Node#return_type
will now return the wrapping type. Use return_type.unwrap
to access the old value #704
instrument(:query, ...)
instrumenters are applied as a stack instead of a queue #735. If you depend on queue-based behavior, move your before_query
and after_query
hooks to separate instrumenters.
In a Relay::Mutation
, Raising or returning a GraphQL::Execution
will nullify the mutation field, not the field's children. #731
args.to_h
returns a slightly different hash #714
String
sas:
, the alias is used as the keyInternalRepresentation::Node#return_type
includes the original "wrapper" types (non-null or list types), call .unwrap
to get the inner type #20
# before
irep_node.return_type
# after
irep_node.return_type.unwrap
Argument prepare
functions which take one argument are deprecated #730
# before
argument :id, !types.ID, prepare: ->(val) { ... }
# after
argument :id, !types.ID, prepare: ->(val, ctx) { ... }
Schema#multiplex(queries)
runs multiple queries concurrently #691GraphQL::RakeTask
supports dumping the schema to IDL or JSON #687Schema.from_definition
#699 :
coerce_input
and coerce_result
functionsresolve_type
function will be used for abstract typesobj
for a method and call it with 0, 1, or 2 arguments.ctx.skip
may be returned from field resolve functions to exclude the field from the response entirely #688instrument(:field, ..., after_built_ins: true)
to apply field instrumentation after Relay wrappers #740prepare
functions are invoked with (val, ctx)
(previously, it was only (val)
) #730args.to_h
returns stringified, aliased arguments #714ctx.namespace(:my_namespace)
provides namespaced key-value storage #689GraphQL::Query
can be initialized without a query_string; it can be added after initialization #710Schema.execute(only:, except:)
accept a callable or an array of callables (multiple filters)Query#merge_filters(only:, except:)
. You can add a filter to every query by merging it in during query instrumentation.max_page_size
in Relay::RelationConnection
and Relay::ArrayConnection
#728Changelog
1.5.0 (10 Mar 2017), yanked
Only UTF-8-encoded strings will be returned by String
fields. Strings with other encodings (or objects whose #to_s
method returns a string with a different encoding) will return nil
instead of that string. #517
To opt into the previous behavior, you can modify GraphQL::STRING_TYPE
:
# app/graphql/my_schema.rb
# Restore previous string behavior:
GraphQL::STRING_TYPE.coerce_result = ->(value) { value.to_s }
MySchema = GraphQL::Schema.define { ... }
Substantial changes to the internal query representation (#512, #536). Query analyzers may notice some changes:
Node#owner_type
always returns an object type. (Interfaces and Unions are replaced with concrete object types which are valid in the current scope.)See changes to Analysis::QueryComplexity
for an example migration. Here are some other specific changes:
Node#children
and Node#path
were removed#included
was removedInternalRepresentation::Selection
was removed (no longer needed)Node#spreads
was replaced by Node#ast_spreads
which returns a SetSchema#validate
returns a list of errors for a query string #513implements ...
adds interfaces to object types without inherit-by-default #548, #574GraphQL::Relay::RangeAdd
for implementing RANGE_ADD
mutations #587use ...
definition method for plugins #565GraphQL::Function
for reusable resolve behavior with arguments & return type #545node
& nodes
field can be extended with a custom block #552Arguments
objects #500FieldResult
s #482ensure_defined
#483has_next_page
while fetching items in RelationConnection
#556Schema.from_definition
#567, #584@skip
ped nodes when parallel branches are not skipped #536frozen_string_literal
comments #589Changelog
1.4.1 (16 Jan 2017)
args
#479last
only #476Schema#default_mask
& query only:
/except:
are combined, not overridden #485Changelog
1.4.0 (8 Jan 2017)
One-argument schema filters are deprecated. Schema filters are now called with two arguments, (member, ctx)
. #463 To update, add a second argument to your schema filter.
The arity of middleware #call
methods has changed. Instead of next_middleware
being the last argument, it is passed as a block. To update, call yield
to continue the middleware chain or use &next_middleware
to capture next_middleware
into a local variable.
# Previous:
def call(*args, next_middleware)
next_middleware.call
end
# Current
def call(*args)
yield
end
# Or
def call(*args, &next_middleware)
next_middleware.call
end
You can add a nodes
field directly to a connection. #451 That way you can say { friends { nodes } }
instead of { freinds { edges { node } } }
. Either pass nodes_field: true
when defining a custom connection type, for example:
FriendsConnectionType = FriendType.define_connection(nodes_field: true)
Or, set GraphQL::Relay::ConnectionType.default_nodes_field = true
before defining your schema, for example:
GraphQL::Relay::ConnectionType.default_nodes_field = true
MySchema = GraphQL::Schema.define { ... }
Middleware performance was dramatically improved by reducing object allocations. #462 next_middleware
is now passed as a block. In general, yield
is faster than calling a captured block.
Improve error messages for wrongly-typed variable values #423
Cache the value of resolve_type
per object per query #462
Pass ctx
to schema filters #463
Accept whitelist schema filters as only:
#463
Add Schema#to_definition
which accepts only:/except:
to filter the schema when printing #463
Add Schema#default_mask
as a default except:
filter #463
Add reflection methods to types #473
#introspection?
marks built-in introspection types#default_scalar?
marks built-in scalars#default_relay?
marks built-in Relay types#default_directive?
marks built-in directiveslast
without before
#362Changelog
1.3.0 (8 Dec 2016)
__
prefix is reserved for built-in names only. This is currently deprecated and will be invalid in a future version. #427, #450Schema#lazy_resolve
allows you to define handlers for a second pass of resolution #386Field#lazy_resolve
can be instrumented to track lazy resolution #429Schema#type_error
allows you to handle InvalidNullError
s and UnresolvedTypeErrors
in your own way #416Schema#cursor_encoder
can be specified for transforming cursors from built-in Connection implementations #345#dup
correctly: they shallowly copy their state into new instances #444Query#provided_variables
is now public #430quirks_mode: true
when serializing values (to support non-stdlib JSON
s) #449#redefine
on a Schema member copies state outside of previous #define
blocks (uses #dup
) #444Changelog
1.2.0 (7 Nov 2016)
A breaking change from 1.1.0 was reverted: two-character "\\u"
is longer treated as the Unicode escape character #372
Due to the execution bug described below, the internal representation of a query has changed. Although Node
responds to the same methods, tree is built differently and query analyzers visit it differently. #373, #379
The difference is in cases like this:
outer {
... on A { inner1 { inner2 } }
... on B { inner1 { inner3 } }
}
Previously, visits would be:
outer
, which has one child:
inner1
, which has two definitions (one on A
, another on B
), then visit its two children
:
inner2
which has one definition (on the return type of inner1
)inner3
which has one definition (on the return type of inner1
)This can be wrong for some cases. For example, if A
and B
are mutually exclusive (both object types, or union types with no shared members), then inner2
and inner3
will never be executed together.
Now, the visit goes like this:
outer
which has two entries in typed_children
, one on A
and another on B
. Visit each typed_chidren
branch:
inner1
, then its one typed_children
branch:
inner2
inner1
, then its one typed_children
branch:
inner3
As you can see, we visit inner1
twice, once for each type condition. inner2
and inner3
are no longer visited as siblings. Instead they're visited as ... cousins? (They share a grandparent, not a parent.)
Although Node#children
is still present, it may not contain all children actually resolved at runtime, since multiple typed_children
branches could apply to the same runtime type (eg, two branches on interface types can apply to the same object type). To track all children, you have to do some bookkeeping during visitation, see QueryComplexity
for an example.
You can see PR #373 for how built-in analyzers were changed to reflect this.
InternalRepresentation::Node#children
and InternalRepresentation::Node#definitions
are deprecated due to the bug described below and the breaking change described above. Instead, use InternalRepresentation::Node#typed_children
and InternalRepresentation::Node#definition
. #373null
support for the whole library: as a query literal, variable value, and argument default value. To check for the presence of a nullable, use Arguments#key?
#369
GraphQL::Schema::UniqueWithinType.default_id_separator
may be assigned to a custom value #381
Context#add_error(err)
may be used to add a GraphQL::ExecutionError
to the response's "errors"
key (and the resolve function can still return a value) #367
The third argument of resolve
is now a FieldResolutionContext
, which behaves just like a Query::Context
, except that it is not modified during query execution. This means you can capture a reference to that context and access some field-level details after the fact: #path
, #ast_node
, #irep_node
. (Other methods are delegated to the underlying Query::Context
) #379
TimeoutMiddleware
's second argument is a proxied query object: it's #context
method returns the FieldResolutionContext
(see above) for the timed-out field. Other methods are delegated to the underlying Query
#379
Fix deep selection merging on divergently-typed fragments. #370, #373, #379 Previously, nested selections on different fragments were not distinguished. Consider a case like this:
... on A { inner1 { inner2 } }
... on B { inner1 { inner3 } }
Previously, an object of type A
would resolve inner1
, then the result would receive both inner2
and inner3
. The same was true for an object of type B
.
Now, those are properly distinguished. An object of type A
resolves inner1
, then its result receives inner2
. An object of type B
receives inner1
, then inner3
.
Changelog
1.1.0 (1 Nov 2016)
"\\u"
is no longer treated as the Unicode escape character, only the Unicode escape character "\u"
is treated that way. (This behavior was a bug, the migration path is to use the Unicode escape character.) #366GraphQL::Language::ParserTests
was removed, use GraphQL::Compatibility
instead. #366Schema.from_definition(definition_string)
builds a GraphQL::Schema
out of a schema definition. #346except:
option #300GraphQL::Compatibility
contains .build_suite
functions for testing user-provided parsers and execution strategies with GraphQL internals. #366#redefine { ... }
for making shallow copies with extended definitions. #357Schema#instrument
provides an avenue for observing query and field resolution with no overhead.SerialExecution
objects were converted to functions, resulting in a modest performance improvement for query resolution.NonNullType
and ListType
have no name (nil
), as per the spec #355