graphql-batch 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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