README.md in graphql-batch-0.3.10 vs README.md in graphql-batch-0.4.0
- old
+ new
@@ -23,10 +23,12 @@
## Usage
### Basic Usage
+#### Schema Configuration
+
Require the library
```ruby
require 'graphql/batch'
```
@@ -47,12 +49,13 @@
```
Use `GraphQL::Batch` as a plugin in your schema (for graphql >= `1.5.0`).
```ruby
-MySchema = GraphQL::Schema.define do
+class MySchema < GraphQL::Schema
query MyQueryType
+ mutation MyMutationType
use GraphQL::Batch
end
```
@@ -64,20 +67,43 @@
GraphQL::Batch.use(self)
end
```
-The loader class can be used from the resolve proc for a graphql field by calling `.for` with the grouping arguments to get a loader instance, then call `.load` on that instance with the key to load.
+##### With `1.9.0`'s `Interpreter` runtime
+Add `GraphQL::Batch` _after_ the interpreter, so that `GraphQL::Batch` can detect the interpreter and attach the right integrations:
+
```ruby
-resolve -> (obj, args, context) { RecordLoader.for(Product).load(args["id"]) }
+use GraphQL::Execution::Interpreter
+use GraphQL::Batch
```
+#### Field Usage
+
+The loader class can be used from the resolver for a graphql field by calling `.for` with the grouping arguments to get a loader instance, then call `.load` on that instance with the key to load.
+
+```ruby
+field :product, Types::Product, null: true do
+ argument :id, ID, required: true
+end
+
+def product(id:)
+ RecordLoader.for(Product).load(id)
+end
+```
+
The loader also supports batch loading an array of records instead of just a single record, via `load_many`. For example:
```ruby
-resolve -> (obj, args, context) { RecordLoader.for(Product).load_many(args["ids"]) }
+field :products, [Types::Product, null: true], null: false do
+ argument :ids, [ID], required: true
+end
+
+def product(ids:)
+ RecordLoader.for(Product).load_many(ids)
+end
```
Although this library doesn't have a dependency on active record,
the [examples directory](examples) has record and association loaders
for active record which handles edge cases like type casting ids
@@ -87,31 +113,31 @@
### Promises
GraphQL::Batch::Loader#load returns a Promise using the [promise.rb gem](https://rubygems.org/gems/promise.rb) to provide a promise based API, so you can transform the query results using `.then`
```ruby
-resolve -> (obj, args, context) do
- RecordLoader.for(Product).load(args["id"]).then do |product|
+def product_title(id:)
+ RecordLoader.for(Product).load(id).then do |product|
product.title
end
end
```
You may also need to do another query that depends on the first one to get the result, in which case the query block can return another query.
```ruby
-resolve -> (obj, args, context) do
- RecordLoader.for(Product).load(args["id"]).then do |product|
+def product_image(id:)
+ RecordLoader.for(Product).load(id).then do |product|
RecordLoader.for(Image).load(product.image_id)
end
end
```
If the second query doesn't depend on the first one, then you can use Promise.all, which allows each query in the group to be batched with other queries.
```ruby
-resolve -> (obj, args, context) do
+def all_collections
Promise.all([
CountLoader.for(Shop, :smart_collections).load(context.shop_id),
CountLoader.for(Shop, :custom_collections).load(context.shop_id),
]).then do |results|
results.reduce(&:+)
@@ -120,11 +146,13 @@
```
`.then` can optionally take two lambda arguments, the first of which is equivalent to passing a block to `.then`, and the second one handles exceptions. This can be used to provide a fallback
```ruby
-resolve -> (obj, args, context) do
+def product(id:)
+ # Try the cache first ...
CacheLoader.for(Product).load(args["id"]).then(nil, lambda do |exc|
+ # But if there's a connection error, go to the underlying database
raise exc unless exc.is_a?(Redis::BaseConnectionError)
logger.warn err.message
RecordLoader.for(Product).load(args["id"])
end)
end