graphql-batch 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c839447dcaacc5db8e6e16d95a30c2fc2db4e899
4
- data.tar.gz: ca03f0ee057d56cd2311ef51df54de199baa53ca
3
+ metadata.gz: 8b725a9f32a436a6e9ee155242dbcff2b576c6b8
4
+ data.tar.gz: d2e42e370abdd6c28014ca0e10e10ae958854e28
5
5
  SHA512:
6
- metadata.gz: e5b0461239a98c5aa53924f2c9a721bfe8d3fc7a59ae70d261255ecf3421b574fc44626d55c514b57b403368ca94c7e2714f37ca66cf324fbdc3ca69735ea8fc
7
- data.tar.gz: abcf9f692f944ac758fa21d6bcd9929a1ceaa9edf8adb6c9c14e019c4c032445dc532cd564fca0010471b02f32903bbdcb13df4a8bae0adde74958bad11387a3
6
+ metadata.gz: aee2377e4fa101ddeec55f33a679af48776262a80087c0b9e033e280c49d7a02cd2ae225b15b3f466c242c359d429ec60e03291e5d6ab0f74dcd4044eb7ecac9
7
+ data.tar.gz: 200b341c757155b9fb23aa87e22cd228dc22bfca8d90c05102ddc54ef806034228472a9fc7d45f329cdc6be3ce1361096e9fa9f4985271ce2f51afc74d3042d1
data/README.md CHANGED
@@ -72,6 +72,12 @@ The loader class can be used from the resolve proc for a graphql field by callin
72
72
  resolve -> (obj, args, context) { RecordLoader.for(Product).load(args["id"]) }
73
73
  ```
74
74
 
75
+ Although this library doesn't have a dependency on active record,
76
+ the [examples directory](examples) has record and association loaders
77
+ for active record which handles edge cases like type casting ids
78
+ and overriding GraphQL::Batch::Loader#cache_key to load associations
79
+ on records with the same id.
80
+
75
81
  ### Promises
76
82
 
77
83
  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`
@@ -0,0 +1,48 @@
1
+ class AssociationLoader < GraphQL::Batch::Loader
2
+ def self.validate(model, association_name)
3
+ new(model, association_name)
4
+ nil
5
+ end
6
+
7
+ def initialize(model, association_name)
8
+ @model = model
9
+ @association_name = association_name
10
+ validate
11
+ end
12
+
13
+ def load(record)
14
+ raise TypeError, "#{@model} loader can't load association for #{record.class}" unless record.is_a?(@model)
15
+ return Promise.resolve(read_association(record)) if association_loaded?(record)
16
+ super
17
+ end
18
+
19
+ # We want to load the associations on all records, even if they have the same id
20
+ def cache_key(record)
21
+ record.object_id
22
+ end
23
+
24
+ def perform(records)
25
+ preload_association(records)
26
+ records.each { |record| fulfill(record, read_association(record)) }
27
+ end
28
+
29
+ private
30
+
31
+ def validate
32
+ unless @model.reflect_on_association(@association_name)
33
+ raise ArgumentError, "No association #{@association_name} on #{@model}"
34
+ end
35
+ end
36
+
37
+ def preload_association(records)
38
+ ::ActiveRecord::Associations::Preloader.new.preload(records, @association_name)
39
+ end
40
+
41
+ def read_association(record)
42
+ record.public_send(@association_name)
43
+ end
44
+
45
+ def association_loaded?(record)
46
+ record.association(@association_name).loaded?
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ class RecordLoader < GraphQL::Batch::Loader
2
+ def initialize(model, column: model.primary_key, where: nil)
3
+ @model = model
4
+ @column = column.to_s
5
+ @column_type = model.type_for_attribute(@column)
6
+ @where = where
7
+ end
8
+
9
+ def load(key)
10
+ super(@column_type.cast(key))
11
+ end
12
+
13
+ def perform(keys)
14
+ query(keys).each do |record|
15
+ value = @column_type.cast(record.public_send(@column))
16
+ fulfill(value, record)
17
+ end
18
+ keys.each { |key| fulfill(key, nil) unless fulfilled?(key) }
19
+ end
20
+
21
+ private
22
+
23
+ def query(keys)
24
+ scope = @model
25
+ scope = scope.where(@where) if @where
26
+ scope.where(@column => keys)
27
+ end
28
+ end
@@ -20,10 +20,15 @@ module GraphQL
20
20
  end
21
21
 
22
22
  def self.use(schema_defn)
23
+ schema = schema_defn.target
23
24
  if GraphQL::VERSION >= "1.6.0"
24
- schema_defn.instrument(:multiplex, GraphQL::Batch::SetupMultiplex)
25
+ instrumentation = GraphQL::Batch::SetupMultiplex.new(schema)
26
+ schema_defn.instrument(:multiplex, instrumentation)
27
+ schema_defn.instrument(:field, instrumentation)
25
28
  else
26
- schema_defn.instrument(:query, GraphQL::Batch::Setup)
29
+ instrumentation = GraphQL::Batch::Setup.new(schema)
30
+ schema_defn.instrument(:query, instrumentation)
31
+ schema_defn.instrument(:field, instrumentation)
27
32
  end
28
33
  schema_defn.lazy_resolve(::Promise, :sync)
29
34
  end
@@ -58,7 +58,6 @@ module GraphQL::Batch
58
58
  # For Promise#sync
59
59
  def wait #:nodoc:
60
60
  if executor
61
- executor.loaders.delete(loader_key)
62
61
  executor.resolve(self)
63
62
  else
64
63
  resolve
@@ -9,11 +9,13 @@ module GraphQL::Batch
9
9
  strategy = execution_context.strategy
10
10
  return super if strategy.enable_batching
11
11
 
12
+ GraphQL::Batch::Executor.current.clear
12
13
  begin
13
14
  strategy.enable_batching = true
14
15
  strategy.deep_sync(Promise.sync(super))
15
16
  ensure
16
17
  strategy.enable_batching = false
18
+ GraphQL::Batch::Executor.current.clear
17
19
  end
18
20
  end
19
21
  end
@@ -1,14 +1,54 @@
1
1
  module GraphQL::Batch
2
- module Setup
3
- extend self
2
+ class Setup
3
+ class << self
4
+ def start_batching
5
+ raise NestedError if GraphQL::Batch::Executor.current
6
+ GraphQL::Batch::Executor.current = GraphQL::Batch::Executor.new
7
+ end
8
+
9
+ def end_batching
10
+ GraphQL::Batch::Executor.current = nil
11
+ end
12
+
13
+ def instrument_field(schema, type, field)
14
+ return field unless type == schema.mutation
15
+ old_resolve_proc = field.resolve_proc
16
+ field.redefine do
17
+ resolve ->(obj, args, ctx) {
18
+ GraphQL::Batch::Executor.current.clear
19
+ begin
20
+ Promise.sync(old_resolve_proc.call(obj, args, ctx))
21
+ ensure
22
+ GraphQL::Batch::Executor.current.clear
23
+ end
24
+ }
25
+ end
26
+ end
27
+
28
+ def before_query(query)
29
+ warn "Deprecated graphql-batch setup `instrument(:query, GraphQL::Batch::Setup)`, replace with `use GraphQL::Batch`"
30
+ start_batching
31
+ end
32
+
33
+ def after_query(query)
34
+ end_batching
35
+ end
36
+ end
37
+
38
+ def initialize(schema)
39
+ @schema = schema
40
+ end
4
41
 
5
42
  def before_query(query)
6
- raise NestedError if GraphQL::Batch::Executor.current
7
- GraphQL::Batch::Executor.current = GraphQL::Batch::Executor.new
43
+ Setup.start_batching
8
44
  end
9
45
 
10
46
  def after_query(query)
11
- GraphQL::Batch::Executor.current = nil
47
+ Setup.end_batching
48
+ end
49
+
50
+ def instrument(type, field)
51
+ Setup.instrument_field(@schema, type, field)
12
52
  end
13
53
  end
14
54
  end
@@ -1,14 +1,19 @@
1
1
  module GraphQL::Batch
2
- module SetupMultiplex
3
- extend self
2
+ class SetupMultiplex
3
+ def initialize(schema)
4
+ @schema = schema
5
+ end
4
6
 
5
7
  def before_multiplex(multiplex)
6
- raise NestedError if GraphQL::Batch::Executor.current
7
- GraphQL::Batch::Executor.current = GraphQL::Batch::Executor.new
8
+ Setup.start_batching
8
9
  end
9
10
 
10
11
  def after_multiplex(multiplex)
11
- GraphQL::Batch::Executor.current = nil
12
+ Setup.end_batching
13
+ end
14
+
15
+ def instrument(type, field)
16
+ Setup.instrument_field(@schema, type, field)
12
17
  end
13
18
  end
14
19
  end
@@ -1,5 +1,5 @@
1
1
  module GraphQL
2
2
  module Batch
3
- VERSION = "0.3.4"
3
+ VERSION = "0.3.5"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-batch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Thacker-Smith
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-08-10 00:00:00.000000000 Z
11
+ date: 2017-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -116,6 +116,8 @@ files:
116
116
  - Rakefile
117
117
  - bin/console
118
118
  - bin/setup
119
+ - examples/association_loader.rb
120
+ - examples/record_loader.rb
119
121
  - graphql-batch.gemspec
120
122
  - lib/graphql/batch.rb
121
123
  - lib/graphql/batch/execution_strategy.rb