README.md in batch-loader-2.0.1 vs README.md in batch-loader-2.0.2
- old
+ new
@@ -1,8 +1,7 @@
# BatchLoader
-[![Build Status](https://travis-ci.org/exAspArk/batch-loader.svg?branch=master)](https://travis-ci.org/exAspArk/batch-loader)
[![Coverage Status](https://coveralls.io/repos/github/exAspArk/batch-loader/badge.svg)](https://coveralls.io/github/exAspArk/batch-loader)
[![Code Climate](https://img.shields.io/codeclimate/maintainability/exAspArk/batch-loader.svg)](https://codeclimate.com/github/exAspArk/batch-loader/maintainability)
[![Downloads](https://img.shields.io/gem/dt/batch-loader.svg)](https://rubygems.org/gems/batch-loader)
[![Latest Version](https://img.shields.io/gem/v/batch-loader.svg)](https://rubygems.org/gems/batch-loader)
@@ -254,11 +253,11 @@
name "Post"
field :user, UserType, null: false
def user
- post.user # N+1 queries
+ object.user # N+1 queries
end
end
end
module Types
@@ -293,11 +292,11 @@
name "Post"
field :user, UserType, null: false
def user
- BatchLoader::GraphQL.for(post.user_id).batch do |user_ids, loader|
+ BatchLoader::GraphQL.for(object.user_id).batch do |user_ids, loader|
User.where(id: user_ids).each { |user| loader.call(user.id, user) }
end
end
end
end
@@ -310,10 +309,42 @@
query Types::QueryType
use BatchLoader::GraphQL
end
```
-That's it.
+---
+
+If you need to use BatchLoader with ActiveRecord in multiple places, you can use this `preload:` helper shared by [Aha!](https://www.aha.io/engineering/articles/automatically-avoiding-graphql-n-1s):
+
+```rb
+field :user, UserType, null: false, preload: :user
+# ^^^^^^^^^^^^^^
+# Simply add this instead of defining custom `user` method with BatchLoader
+```
+
+And add this custom field resolver that uses ActiveRecord's preload functionality with BatchLoader:
+
+```rb
+# app/graphql/types/base_object.rb
+field_class Types::PreloadableField
+
+# app/graphql/types/preloadable_field.rb
+class Types::PreloadableField < Types::BaseField
+ def initialize(*args, preload: nil, **kwargs, &block)
+ @preloads = preload
+ super(*args, **kwargs, &block)
+ end
+
+ def resolve(type, args, ctx)
+ return super unless @preloads
+
+ BatchLoader::GraphQL.for(type).batch(key: self) do |records, loader|
+ ActiveRecord::Associations::Preloader.new.preload(records.map(&:object), @preloads)
+ records.each { |r| loader.call(r, super(r, args, ctx)) }
+ end
+ end
+end
+```
### Loading multiple items
For batches where there is no item in response to a call, we normally return `nil`. However, you can use `:default_value` to return something else instead: