Skip to content
This repository was archived by the owner on Sep 24, 2019. It is now read-only.

Commit e96e9dc

Browse files
authored
Merge pull request #23 from GraphQLAcademy/graphql-batch
Use GraphQL Batch for find by id fields
2 parents 7e66c35 + 1857ed2 commit e96e9dc

File tree

8 files changed

+56
-41
lines changed

8 files changed

+56
-41
lines changed

Gemfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ end
77

88
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
99
gem 'rails', '~> 5.0.1'
10-
# use PG in prod for heroku
11-
gem 'pg'
1210
# Use Puma as the app server
1311
gem 'puma', '~> 3.0'
1412
# Use GraphQL!
1513
gem 'graphql', '~> 1.4.3'
14+
gem 'graphql-batch'
1615
# GraphiQL Interface
1716
gem 'graphiql-rails', '~> 1.4.1'
1817

@@ -24,6 +23,10 @@ group :development, :test do
2423
gem 'sqlite3'
2524
end
2625

26+
group :production do
27+
gem 'pg'
28+
end
29+
2730
group :development do
2831
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
2932
gem 'web-console', '>= 3.3.0'

Gemfile.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ GEM
5151
graphiql-rails (1.4.1)
5252
rails
5353
graphql (1.4.3)
54+
graphql-batch (0.3.1)
55+
graphql (>= 0.8, < 2)
56+
promise.rb (~> 0.7.2)
5457
i18n (0.8.0)
5558
json (2.0.2)
5659
listen (3.0.8)
@@ -70,6 +73,7 @@ GEM
7073
nokogiri (1.7.0.1)
7174
mini_portile2 (~> 2.1.0)
7275
pg (0.19.0)
76+
promise.rb (0.7.2)
7377
puma (3.7.0)
7478
rack (2.0.1)
7579
rack-test (0.6.3)
@@ -137,6 +141,7 @@ DEPENDENCIES
137141
byebug
138142
graphiql-rails (~> 1.4.1)
139143
graphql (~> 1.4.3)
144+
graphql-batch
140145
listen (~> 3.0.5)
141146
pg
142147
puma (~> 3.0)

app/models/graph.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module Graph
2+
class << self
3+
def find_by_id_field(type, model)
4+
GraphQL::Field.define do
5+
type type
6+
argument :id, !types.ID
7+
resolve ->(_, args, _) do
8+
gid = GlobalID.parse(args[:id])
9+
10+
return unless gid.model_name == type.name
11+
12+
Graph::FindLoader.for(model).load(gid.model_id.to_i)
13+
end
14+
end
15+
end
16+
end
17+
end

app/models/graph/find_loader.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Graph::FindLoader < GraphQL::Batch::Loader
2+
def initialize(model)
3+
@model = model
4+
end
5+
6+
def perform(ids)
7+
records = @model.where(id: ids.uniq)
8+
records.each { |record| fulfill(record.id, record) }
9+
ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
10+
end
11+
end

app/models/graph/schema.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,8 @@ module Graph
1919

2020
Object.const_get(gid.model_name).find(gid.model_id)
2121
end
22+
23+
lazy_resolve(Promise, :sync)
24+
instrument(:query, GraphQL::Batch::Setup)
2225
end
2326
end

app/models/graph/types/query.rb

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,32 @@ module Types
88
field :node, GraphQL::Relay::Node.field
99
field :nodes, GraphQL::Relay::Node.plural_field
1010

11-
field :person, Graph::Types::Person do
12-
argument :id, types.ID
13-
resolve ->(_, args, _) { ::Person.find_by(id: args['id']) }
14-
end
15-
11+
field :person, Graph.find_by_id_field(Graph::Types::Person, ::Person)
1612
field :people, types[Graph::Types::Person] do
1713
resolve ->(_, _, _) { ::Person.all }
1814
end
1915

20-
field :planet, Graph::Types::Planet do
21-
argument :id, types.ID
22-
resolve ->(_, args, _) { ::Planet.find(args['id']) }
23-
end
24-
16+
field :planet, Graph.find_by_id_field(Graph::Types::Planet, ::Planet)
2517
field :planets, types[Graph::Types::Planet] do
2618
resolve ->(_, _, _) { ::Planet.all }
2719
end
2820

29-
field :film, Graph::Types::Film do
30-
argument :id, types.ID
31-
resolve ->(_, args, _) { ::Film.find(args['id']) }
32-
end
33-
21+
field :film, Graph.find_by_id_field(Graph::Types::Film, ::Film)
3422
field :films, types[Graph::Types::Film] do
3523
resolve ->(_, _, _) { ::Film.all }
3624
end
3725

38-
field :species, Graph::Types::Species do
39-
argument :id, types.ID
40-
resolve ->(_, args, _) { ::Species.find(args['id']) }
41-
end
42-
26+
field :species, Graph.find_by_id_field(Graph::Types::Species, ::Species)
4327
field :allSpecies, types[Graph::Types::Species] do
4428
resolve ->(_, _, _) { ::Species.all }
4529
end
4630

47-
field :starship, Graph::Types::Starship do
48-
argument :id, types.ID
49-
resolve ->(_, args, _) { ::Starship.find(args['id']) }
50-
end
51-
31+
field :starship, Graph.find_by_id_field(Graph::Types::Starship, ::Starship)
5232
field :starships, types[Graph::Types::Starship] do
5333
resolve ->(_, _, _) { ::Starship.all }
5434
end
5535

56-
field :vehicle, Graph::Types::Vehicle do
57-
argument :id, types.ID
58-
resolve ->(_, args, _) { ::Vehicle.find(args['id']) }
59-
end
60-
36+
field :vehicle, Graph.find_by_id_field(Graph::Types::Vehicle, ::Vehicle)
6137
field :vehicles, types[Graph::Types::Vehicle] do
6238
resolve ->(_, _, _) { ::Vehicle.all }
6339
end

config/secrets.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
development:
2-
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
2+
secret_key_base: secret-for-development-not-so-secret
33

44
test:
5-
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
5+
secret_key_base: secret-for-test-not-so-secret
66

77
production:
88
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

test/controllers/graphql_controller_test.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class GraphQLControllerTest < ActionDispatch::IntegrationTest
113113

114114
def full_graphql_query
115115
"
116-
query Full($personID: ID, $filmID: ID, $planetID: ID, $starshipID: ID, $speciesID: ID, $vehicleID: ID) {
116+
query Full($personID: ID!, $filmID: ID!, $planetID: ID!, $starshipID: ID!, $speciesID: ID!, $vehicleID: ID!) {
117117
person(id: $personID) {
118118
birthYear
119119
eyeColor
@@ -204,12 +204,12 @@ def default_variables
204204
vehicle = vehicles(:snowspeeder)
205205

206206
{
207-
"starshipID" => starship.id,
208-
"personID" => person.id,
209-
"filmID" => film.id,
210-
"planetID" => planet.id,
211-
"speciesID" => species.id,
212-
"vehicleID" => vehicle.id
207+
"starshipID" => starship.to_global_id,
208+
"personID" => person.to_global_id,
209+
"filmID" => film.to_global_id,
210+
"planetID" => planet.to_global_id,
211+
"speciesID" => species.to_global_id,
212+
"vehicleID" => vehicle.to_global_id,
213213
}
214214
end
215215
end

0 commit comments

Comments
 (0)