graphql 0.9.3 → 0.9.4

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: 90c4327894852ac5fa30563c6f75585be564033d
4
- data.tar.gz: b5ea5c2c7710196f76bb2773f55cda6380075336
3
+ metadata.gz: c7a6017d64f6fd507c50ac439cd6509e2fb163cd
4
+ data.tar.gz: 43f4acf1bd7a7b7bf43b9b0df7e87d34cea37339
5
5
  SHA512:
6
- metadata.gz: f939c511550ce296668dd3154863cb5401ef7d8710b5dd6a165387555ebce6f769ea587d1a798b9ce39b8b69f39ca1120adff150579e892c84fed22d0f26e7be
7
- data.tar.gz: b12940f1e651fe6de8fa33ac0ee1a68ed8041e4120a5c48b52a53d4e239f5470d547b616639876d8c6f01b194ea7ab59b0796a2dd5d3c1d98bd06ef79b4b77d9
6
+ metadata.gz: 313db517b3541bbf8f21a7d1fba1eb257d4be306e44e33f9f6f511d0d3fbfb034cfeca667a2025038bc85b88513fa329db7003922948dd64a78633c44231eb2c
7
+ data.tar.gz: 2a86be1427279e98dfb940ac59f2b8669c6d9638ad8a414a34ba80ee87a9d32bcde0a5ccef2d9c660d033b8d6a7be7ad0c1902869a33c5fe711b24d4cf9512b8
@@ -58,6 +58,7 @@ require 'graphql/schema'
58
58
 
59
59
  # Order does not matter for these:
60
60
 
61
+ require 'graphql/execution_error'
61
62
  require 'graphql/query'
62
63
  require 'graphql/repl'
63
64
  require 'graphql/static_validation'
@@ -53,6 +53,10 @@ module GraphQL
53
53
  def resolve_type=(new_proc)
54
54
  @resolve_type_proc = new_proc || DEFAULT_RESOLVE_TYPE
55
55
  end
56
+
57
+ def include?(type)
58
+ possible_types.include?(type)
59
+ end
56
60
  end
57
61
 
58
62
  # Print the human-readable name of this type
@@ -0,0 +1,27 @@
1
+ module GraphQL
2
+ # If a field's resolve function returns a {ExecutionError},
3
+ # the error will be inserted into the response's `"errors"` key
4
+ # and the field will resolve to `nil`.
5
+ class ExecutionError < RuntimeError
6
+ # @return [GraphQL::Language::Nodes::Field] the field where the error occured
7
+ attr_accessor :ast_node
8
+
9
+ # @return [Hash] An entry for the response's "errors" key
10
+ def to_h
11
+ hash = {
12
+ "message" => message,
13
+ }
14
+ if ast_node.nil?
15
+ hash["locations"] = []
16
+ else
17
+ hash["locations"] = [
18
+ {
19
+ "line" => ast_node.line,
20
+ "column" => ast_node.col,
21
+ }
22
+ ]
23
+ end
24
+ hash
25
+ end
26
+ end
27
+ end
@@ -1,4 +1,3 @@
1
- require 'graphql/query/base_execution/selected_object_resolution'
2
1
  require 'graphql/query/base_execution/value_resolution'
3
2
 
4
3
  module GraphQL
@@ -18,21 +17,15 @@ module GraphQL
18
17
  end
19
18
 
20
19
  def field_resolution
21
- get_class :FieldResolution
20
+ self.class::FieldResolution
22
21
  end
23
22
 
24
23
  def operation_resolution
25
- get_class :OperationResolution
24
+ self.class::OperationResolution
26
25
  end
27
26
 
28
27
  def selection_resolution
29
- get_class :SelectionResolution
30
- end
31
-
32
- private
33
-
34
- def get_class(class_name)
35
- self.class.const_get(class_name)
28
+ self.class::SelectionResolution
36
29
  end
37
30
  end
38
31
  end
@@ -29,12 +29,15 @@ module GraphQL
29
29
  end
30
30
 
31
31
  class ScalarResolution < BaseResolution
32
+ # Apply the scalar's defined `coerce` method to the value
32
33
  def result
33
34
  field_type.coerce(value)
34
35
  end
35
36
  end
36
37
 
37
38
  class ListResolution < BaseResolution
39
+ # For each item in the list,
40
+ # Resolve it with the "wrapped" type of this list
38
41
  def result
39
42
  wrapped_type = field_type.of_type
40
43
  value.map do |item|
@@ -47,6 +50,7 @@ module GraphQL
47
50
  end
48
51
 
49
52
  class ObjectResolution < BaseResolution
53
+ # Resolve the selections on this object
50
54
  def result
51
55
  resolver = execution_strategy.selection_resolution.new(value, field_type, ast_field.selections, query, execution_strategy)
52
56
  resolver.result
@@ -54,12 +58,14 @@ module GraphQL
54
58
  end
55
59
 
56
60
  class EnumResolution < BaseResolution
61
+ # Get the string name for this enum value
57
62
  def result
58
63
  value.to_s
59
64
  end
60
65
  end
61
66
 
62
67
  class NonNullResolution < BaseResolution
68
+ # Get the "wrapped" type and resolve the value according to that type
63
69
  def result
64
70
  wrapped_type = field_type.of_type
65
71
  resolved_type = wrapped_type.resolve_type(value)
@@ -3,11 +3,23 @@ module GraphQL
3
3
  # Expose some query-specific info to field resolve functions.
4
4
  # It delegates `[]` to the hash that's passed to `GraphQL::Query#initialize`.
5
5
  class Context
6
- attr_accessor :execution_strategy, :ast_node
6
+ attr_accessor :execution_strategy
7
+
8
+ # The {GraphQL::Language::Nodes::Field} for the currently-executing field.
9
+ # @return [GraphQL::Language::Nodes::Field]
10
+ attr_accessor :ast_node
11
+
12
+ # @return [Array<GraphQL::ExecutionError>] errors returned during execution
13
+ attr_reader :errors
14
+
15
+ # Make a new context which delegates key lookup to `values`
16
+ # @param [Hash] A hash of arbitrary values which will be accessible at query-time
7
17
  def initialize(values:)
8
18
  @values = values
19
+ @errors = []
9
20
  end
10
21
 
22
+ # Lookup `key` from the hash passed to {Schema#execute} as `context`
11
23
  def [](key)
12
24
  @values[key]
13
25
  end
@@ -8,14 +8,23 @@ module GraphQL
8
8
  end
9
9
  end
10
10
 
11
- attr_reader :query, :operation_name
11
+ # @return [GraphQL::Query] the query being executed
12
+ attr_reader :query
13
+
14
+ # @return [String] the operation to run in {query}
15
+ attr_reader :operation_name
16
+
17
+
12
18
  def initialize(query, operation_name)
13
19
  @query = query
14
20
  @operation_name = operation_name
15
21
  end
16
22
 
23
+ # Evalute {operation_name} on {query}. Handle errors by putting them in the "errors" key.
24
+ # (Or, if `query.debug`, by re-raising them.)
25
+ # @return [Hash] A GraphQL response, with either a "data" key or an "errors" key
17
26
  def result
18
- {"data" => execute }
27
+ execute
19
28
  rescue OperationNameMissingError => err
20
29
  {"errors" => [{"message" => err.message}]}
21
30
  rescue StandardError => err
@@ -38,7 +47,15 @@ module GraphQL
38
47
  end
39
48
  execution_strategy = execution_strategy_class.new
40
49
  query.context.execution_strategy = execution_strategy
41
- result = execution_strategy.execute(operation, root_type, query)
50
+ data_result = execution_strategy.execute(operation, root_type, query)
51
+ result = { "data" => data_result }
52
+ error_result = query.context.errors.map(&:to_h)
53
+
54
+ if error_result.any?
55
+ result["errors"] = error_result
56
+ end
57
+
58
+ result
42
59
  end
43
60
 
44
61
  def find_operation(operation_name, operations)
@@ -1,11 +1,15 @@
1
1
  module GraphQL
2
2
  class Query
3
3
  class SerialExecution
4
- class FieldResolution < GraphQL::Query::BaseExecution::SelectedObjectResolution
5
- attr_reader :field, :arguments
4
+ class FieldResolution
5
+ attr_reader :ast_node, :parent_type, :target, :query, :execution_strategy, :field, :arguments
6
6
 
7
7
  def initialize(ast_node, parent_type, target, query, execution_strategy)
8
- super
8
+ @ast_node = ast_node
9
+ @parent_type = parent_type
10
+ @target = target
11
+ @query = query
12
+ @execution_strategy = execution_strategy
9
13
  @field = query.schema.get_field(parent_type, ast_node.name) || raise("No field found on #{parent_type.name} '#{parent_type}' for '#{ast_node.name}'")
10
14
  @arguments = GraphQL::Query::Arguments.new(ast_node.arguments, field.arguments, query.variables)
11
15
  end
@@ -21,6 +25,10 @@ module GraphQL
21
25
  def get_finished_value(raw_value)
22
26
  if raw_value.nil?
23
27
  nil
28
+ elsif raw_value.is_a?(GraphQL::ExecutionError)
29
+ raw_value.ast_node = ast_node
30
+ query.context.errors << raw_value
31
+ nil
24
32
  else
25
33
  resolved_type = field.type.resolve_type(raw_value)
26
34
  strategy_class = GraphQL::Query::BaseExecution::ValueResolution.get_strategy_for_kind(resolved_type.kind)
@@ -1,3 +1,3 @@
1
1
  module GraphQL
2
- VERSION = "0.9.3"
2
+ VERSION = "0.9.4"
3
3
  end
data/readme.md CHANGED
@@ -6,6 +6,8 @@
6
6
  [![Test Coverage](https://codeclimate.com/github/rmosolgo/graphql-ruby/badges/coverage.svg)](https://codeclimate.com/github/rmosolgo/graphql-ruby)
7
7
  [![built with love](https://cloud.githubusercontent.com/assets/2231765/6766607/d07992c6-cfc9-11e4-813f-d9240714dd50.png)](http://rmosolgo.github.io/react-badges/)
8
8
 
9
+ A Ruby implementation of [GraphQL](http://graphql.org/).
10
+
9
11
  - [Introduction](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/introduction.md)
10
12
  - [API Documentation](http://www.rubydoc.info/github/rmosolgo/graphql-ruby)
11
13
 
@@ -92,13 +94,13 @@ If you're building a backend for [Relay](http://facebook.github.io/relay/), you'
92
94
  - Code clean-up
93
95
  - Raise if you try to configure an attribute which doesn't suit the type
94
96
  - ie, if you try to define `resolve` on an ObjectType, it should somehow raise
97
+ - Incoming enums should be exposed as `EnumValue`s, not `Nodes::Enum`s
95
98
  - Big ideas:
96
- - Write Ruby bindings for [libgraphqlparser](https://github.com/graphql/libgraphqlparser) and use that instead of Parslet
99
+ - Use [graphql-parser](https://github.com/shopify/graphql-parser) (Ruby bindings for [libgraphqlparser](https://github.com/graphql/libgraphqlparser)) instead of Parslet
97
100
  - Add instrumentation
98
101
  - Some way to expose what queries are run, what types & fields are accessed, how long things are taking, etc
99
102
  - before-hooks for every field?
100
103
 
101
-
102
104
  ## Goals
103
105
 
104
106
  - Implement the GraphQL spec & support a Relay front end
@@ -112,14 +114,12 @@ If you're building a backend for [Relay](http://facebook.github.io/relay/), you'
112
114
  - __Features & patches__ are welcome! Consider discussing it in an [issue](https://github.com/rmosolgo/graphql-ruby/issues) or in the [#ruby channel on Slack](https://graphql-slack.herokuapp.com/) to make sure we're on the same page.
113
115
  - __Run the tests__ with `rake test` or start up guard with `bundle exec guard`.
114
116
 
115
- ## Other Resources
117
+ ## Related Projects
116
118
 
117
- - [GraphQL Spec](http://facebook.github.io/graphql/)
118
- - Other implementations: [graphql-links](https://github.com/emmenko/graphql-links)
119
119
  - `graphql-ruby` + Rails demo ([src](https://github.com/rmosolgo/graphql-ruby-demo) / [heroku](http://graphql-ruby-demo.herokuapp.com))
120
- - [GraphQL Slack](https://graphql-slack.herokuapp.com/)
121
- - [Example Relay support](https://github.com/rmosolgo/graphql-relay-ruby) in Ruby
120
+ - [`graphql-batch`](https://github.com/shopify/graphql-batch), a batched query execution strategy
122
121
  - [`graphql-parallel`](https://github.com/rmosolgo/graphql-parallel), an asynchronous query execution strategy
122
+ - [Example Relay support](https://github.com/rmosolgo/graphql-relay-ruby) in Ruby
123
123
 
124
124
  ## P.S.
125
125
 
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe GraphQL::ExecutionError do
4
+ let(:result) { DummySchema.execute(query_string) }
5
+ describe "when returned from a field" do
6
+ let(:query_string) {%|
7
+ {
8
+ cheese(id: 1) {
9
+ id
10
+ error1: similarCheese(source: [YAK]) {
11
+ ... similarCheeseFields
12
+ }
13
+ error2: similarCheese(source: [YAK]) {
14
+ ... similarCheeseFields
15
+ }
16
+ nonError: similarCheese(source: [SHEEP]) {
17
+ ... similarCheeseFields
18
+ }
19
+ flavor
20
+ }
21
+ }
22
+
23
+ fragment similarCheeseFields on Cheese {
24
+ id, flavor
25
+ }
26
+ |}
27
+ it "the error is inserted into the errors key and the rest of the query is fulfilled" do
28
+ expected_result = {
29
+ "data"=>{
30
+ "cheese"=>{
31
+ "id" => 1,
32
+ "error1"=> nil,
33
+ "error2"=> nil,
34
+ "nonError"=> {
35
+ "id" => 3,
36
+ "flavor" => "Manchego",
37
+ },
38
+ "flavor" => "Brie",
39
+ }
40
+ },
41
+ "errors"=>[
42
+ {
43
+ "message"=>"No cheeses are made from Yak milk!",
44
+ "locations"=>[{"line"=>5, "column"=>9}]
45
+ },
46
+ {
47
+ "message"=>"No cheeses are made from Yak milk!",
48
+ "locations"=>[{"line"=>8, "column"=>9}]
49
+ },
50
+ ]
51
+ }
52
+ assert_equal(expected_result, result)
53
+ end
54
+ end
55
+ end
@@ -23,6 +23,7 @@ describe GraphQL::Introspection::SchemaType do
23
23
  {"name"=>"dairy"},
24
24
  {"name"=>"fromSource"},
25
25
  {"name"=>"favoriteEdible"},
26
+ {"name"=>"cow"},
26
27
  {"name"=>"searchDairy"},
27
28
  {"name"=>"error"},
28
29
  {"name"=>"maybeNull"},
@@ -15,7 +15,7 @@ describe GraphQL::Introspection::TypeType do
15
15
  {"name"=>"id", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "Int"}}},
16
16
  {"name"=>"flavor", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "String"}}},
17
17
  {"name"=>"source", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "DairyAnimal"}}},
18
- {"name"=>"similarCheeses", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
18
+ {"name"=>"similarCheese", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
19
19
  ]}
20
20
 
21
21
  let(:dairy_animals) {[
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe GraphQL::Query::TypeResolver do
4
+ it 'resolves correcty when child_type is UnionType' do
5
+ type = GraphQL::Query::TypeResolver.new(MILKS[1], DairyProductUnion, MilkType).type
6
+ assert_equal(MilkType, type)
7
+ end
8
+ end
@@ -63,7 +63,7 @@ describe GraphQL::Query do
63
63
  maybeNull {
64
64
  cheese {
65
65
  flavor,
66
- similarCheeses(source: [SHEEP]) { flavor }
66
+ similarCheese(source: [SHEEP]) { flavor }
67
67
  }
68
68
  }
69
69
  }
@@ -147,14 +147,14 @@ describe GraphQL::Query do
147
147
  describe "whitespace-only" do
148
148
  let(:query_string) { " " }
149
149
  it "doesn't blow up" do
150
- assert_equal({"data"=> {}}, result)
150
+ assert_equal({}, result)
151
151
  end
152
152
  end
153
153
 
154
154
  describe "empty string" do
155
155
  let(:query_string) { "" }
156
156
  it "doesn't blow up" do
157
- assert_equal({"data"=> {}}, result)
157
+ assert_equal({}, result)
158
158
  end
159
159
  end
160
160
  end
@@ -10,7 +10,7 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
10
10
  }
11
11
 
12
12
  fragment cheeseFields on Cheese {
13
- similarCheeses(source: 4.5)
13
+ similarCheese(source: 4.5)
14
14
  }
15
15
  |)}
16
16
 
@@ -33,7 +33,7 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
33
33
  assert_includes(errors, input_object_error)
34
34
 
35
35
  fragment_error = {
36
- "message"=>"Argument source on Field 'similarCheeses' has an invalid value",
36
+ "message"=>"Argument source on Field 'similarCheese' has an invalid value",
37
37
  "locations"=>[{"line"=>10, "column"=>7}]
38
38
  }
39
39
  assert_includes(errors, fragment_error)
@@ -8,7 +8,7 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
8
8
  }
9
9
 
10
10
  fragment cheeseFields on Cheese {
11
- similarCheeses(source: SHEEP, nonsense: 1)
11
+ similarCheese(source: SHEEP, nonsense: 1)
12
12
  id @skip(something: 3.4)
13
13
  }
14
14
  ")}
@@ -26,7 +26,7 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
26
26
  assert_includes(errors, query_root_error)
27
27
 
28
28
  fragment_error = {
29
- "message"=>"Field 'similarCheeses' doesn't accept argument nonsense",
29
+ "message"=>"Field 'similarCheese' doesn't accept argument nonsense",
30
30
  "locations"=>[{"line"=>8, "column"=>7}]
31
31
  }
32
32
  assert_includes(errors, fragment_error)
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
4
4
  let(:document) { GraphQL.parse("
5
5
  query getCheese {
6
- okCheese: cheese(id: 1) { fatContent, similarCheeses(source: YAK) { source } }
6
+ okCheese: cheese(id: 1) { fatContent, similarCheese(source: YAK) { source } }
7
7
  missingFieldsCheese: cheese(id: 1)
8
8
  illegalSelectionCheese: cheese(id: 1) { id { something, ... someFields } }
9
9
  }
@@ -9,22 +9,22 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
9
9
  nickname: fatContent,
10
10
  fatContent
11
11
  differentLevel: fatContent
12
- similarCheeses(source: $sourceVar)
12
+ similarCheese(source: $sourceVar)
13
13
 
14
- similarCow: similarCheeses(source: COW) {
14
+ similarCow: similarCheese(source: COW) {
15
15
  similarCowSource: source,
16
16
  differentLevel: fatContent
17
17
  }
18
18
  ...cheeseFields
19
19
  ... on Cheese {
20
20
  fatContent: name
21
- similarCheeses(source: SHEEP)
21
+ similarCheese(source: SHEEP)
22
22
  }
23
23
  }
24
24
  }
25
25
  fragment cheeseFields on Cheese {
26
26
  fatContent,
27
- similarCow: similarCheeses(source: COW) { similarCowSource: id, id }
27
+ similarCow: similarCheese(source: COW) { similarCowSource: id, id }
28
28
  id @someFlag
29
29
  }
30
30
  ")}
@@ -39,7 +39,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
39
39
  "Field 'id' has a directive argument conflict: [] or [{}]?", # not sure this is a great way to handle it but here we are!
40
40
  "Field 'nickname' has a field conflict: name or fatContent?", # alias conflict in query
41
41
  "Field 'fatContent' has a field conflict: fatContent or name?", # alias/name conflict in query and fragment
42
- "Field 'similarCheeses' has an argument conflict: {\"source\":\"sourceVar\"} or {\"source\":\"SHEEP\"}?", # different arguments
42
+ "Field 'similarCheese' has an argument conflict: {\"source\":\"sourceVar\"} or {\"source\":\"SHEEP\"}?", # different arguments
43
43
  "Field 'similarCowSource' has a field conflict: source or id?", # nested conflict
44
44
  ]
45
45
  assert_equal(expected_errors, error_messages)
@@ -8,7 +8,7 @@ describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
8
8
  }
9
9
 
10
10
  fragment cheeseFields on Cheese {
11
- similarCheeses(id: 1)
11
+ similarCheese(id: 1)
12
12
  flavor @include(if: true)
13
13
  id @skip
14
14
  }
@@ -27,7 +27,7 @@ describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
27
27
  assert_includes(errors, query_root_error)
28
28
 
29
29
  fragment_error = {
30
- "message"=>"Field 'similarCheeses' is missing required arguments: source",
30
+ "message"=>"Field 'similarCheese' is missing required arguments: source",
31
31
  "locations"=>[{"line"=>8, "column"=>7}]
32
32
  }
33
33
  assert_includes(errors, fragment_error)
@@ -16,9 +16,9 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
16
16
  badCheese: cheese(id: $badInt) { source }
17
17
  badStrCheese: cheese(id: $badStr) { source }
18
18
  cheese(id: 1) {
19
- similarCheeses(source: $goodAnimals)
20
- other: similarCheeses(source: $badAnimals)
21
- tooDeep: similarCheeses(source: $deepAnimals)
19
+ similarCheese(source: $goodAnimals)
20
+ other: similarCheese(source: $badAnimals)
21
+ tooDeep: similarCheese(source: $deepAnimals)
22
22
  }
23
23
 
24
24
  milk(id: 1) {
@@ -43,11 +43,11 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
43
43
  },
44
44
  {
45
45
  "message"=>"Nullability mismatch on variable $badAnimals and argument source ([DairyAnimal]! / [DairyAnimal!]!)",
46
- "locations"=>[{"line"=>17, "column"=>31}]
46
+ "locations"=>[{"line"=>17, "column"=>30}]
47
47
  },
48
48
  {
49
49
  "message"=>"List dimension mismatch on variable $deepAnimals and argument source ([[DairyAnimal!]!]! / [DairyAnimal!]!)",
50
- "locations"=>[{"line"=>18, "column"=>33}]
50
+ "locations"=>[{"line"=>18, "column"=>32}]
51
51
  }
52
52
  ]
53
53
  assert_equal(expected, errors)
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  describe GraphQL::UnionType do
4
4
  let(:type_1) { OpenStruct.new(kind: GraphQL::TypeKinds::OBJECT)}
5
5
  let(:type_2) { OpenStruct.new(kind: GraphQL::TypeKinds::OBJECT)}
6
+ let(:type_3) { OpenStruct.new(kind: GraphQL::TypeKinds::SCALAR)}
6
7
  let(:union) {
7
8
  types = [type_1, type_2]
8
9
  GraphQL::UnionType.define {
@@ -18,4 +19,12 @@ describe GraphQL::UnionType do
18
19
  it 'infers type from an object' do
19
20
  assert_equal(CheeseType, DairyProductUnion.resolve_type(CHEESES[1]))
20
21
  end
22
+
23
+ it '#include? returns true if type in in possible_types' do
24
+ assert union.include?(type_1)
25
+ end
26
+
27
+ it '#include? returns false if type is not in possible_types' do
28
+ assert_equal(false, union.include?(type_3))
29
+ end
21
30
  end
@@ -36,12 +36,16 @@ CheeseType = GraphQL::ObjectType.define do
36
36
  description("Animal which produced the milk for this cheese")
37
37
  end
38
38
 
39
- field :similarCheeses do
40
- type -> { CheeseType }
41
- description("Cheeses like this one")
39
+ field :similarCheese, -> { CheeseType }, "Cheeses like this one" do
42
40
  argument :source, !types[!DairyAnimalEnum]
43
41
  resolve -> (t, a, c) {
44
- CHEESES.values.find { |c| c.source == a["source"] }
42
+ # get the strings out:
43
+ sources = a["source"].map(&:name)
44
+ if sources.include?("YAK")
45
+ GraphQL::ExecutionError.new("No cheeses are made from Yak milk!")
46
+ else
47
+ CHEESES.values.find { |c| sources.include?(c.source) }
48
+ end
45
49
  }
46
50
  end
47
51
 
@@ -84,6 +88,20 @@ DairyProductUnion = GraphQL::UnionType.define do
84
88
  possible_types [MilkType, CheeseType]
85
89
  end
86
90
 
91
+ CowType = GraphQL::ObjectType.define do
92
+ name 'Cow'
93
+ description 'A farm where milk is harvested and cheese is produced'
94
+ field :id, !types.ID
95
+ field :name, types.String
96
+ field :last_produced_dairy, DairyProductUnion
97
+ end
98
+
99
+ MaybeNullType = GraphQL::ObjectType.define do
100
+ name "MaybeNull"
101
+ description "An object whose fields return nil"
102
+ field :cheese, CheeseType
103
+ end
104
+
87
105
  DairyProductInputType = GraphQL::InputObjectType.define {
88
106
  name "DairyProductInput"
89
107
  description "Properties for finding a dairy product"
@@ -142,6 +160,7 @@ QueryType = GraphQL::ObjectType.define do
142
160
  field :dairy, field: SingletonField.create(type: DairyType, data: DAIRY)
143
161
  field :fromSource, &SourceFieldDefn
144
162
  field :favoriteEdible, &FavoriteFieldDefn
163
+ field :cow, field: SingletonField.create(type: CowType, data: COW)
145
164
  field :searchDairy do
146
165
  description "Find dairy products matching a description"
147
166
  type !DairyProductUnion
@@ -192,7 +211,7 @@ MutationType = GraphQL::ObjectType.define do
192
211
  argument :input, !ReplaceValuesInputType
193
212
  resolve -> (o, args, ctx) {
194
213
  GLOBAL_VALUES.clear
195
- GLOBAL_VALUES += args[:input][:values]
214
+ GLOBAL_VALUES.push(*args[:input][:values])
196
215
  GLOBAL_VALUES
197
216
  }
198
217
  end
@@ -15,3 +15,9 @@ DAIRY = OpenStruct.new(
15
15
  cheese: CHEESES[1],
16
16
  milks: [MILKS[1]]
17
17
  )
18
+
19
+ COW = OpenStruct.new(
20
+ id: 1,
21
+ name: 'Billy',
22
+ last_produced_dairy: MILKS[1]
23
+ )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-15 00:00:00.000000000 Z
11
+ date: 2015-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -172,6 +172,7 @@ files:
172
172
  - lib/graphql/directive/include_directive.rb
173
173
  - lib/graphql/directive/skip_directive.rb
174
174
  - lib/graphql/enum_type.rb
175
+ - lib/graphql/execution_error.rb
175
176
  - lib/graphql/field.rb
176
177
  - lib/graphql/float_type.rb
177
178
  - lib/graphql/id_type.rb
@@ -208,7 +209,6 @@ files:
208
209
  - lib/graphql/query.rb
209
210
  - lib/graphql/query/arguments.rb
210
211
  - lib/graphql/query/base_execution.rb
211
- - lib/graphql/query/base_execution/selected_object_resolution.rb
212
212
  - lib/graphql/query/base_execution/value_resolution.rb
213
213
  - lib/graphql/query/context.rb
214
214
  - lib/graphql/query/directive_chain.rb
@@ -258,6 +258,7 @@ files:
258
258
  - spec/graphql/base_type_spec.rb
259
259
  - spec/graphql/directive_spec.rb
260
260
  - spec/graphql/enum_type_spec.rb
261
+ - spec/graphql/execution_error_spec.rb
261
262
  - spec/graphql/field_spec.rb
262
263
  - spec/graphql/id_type_spec.rb
263
264
  - spec/graphql/input_object_type_spec.rb
@@ -271,6 +272,7 @@ files:
271
272
  - spec/graphql/language/visitor_spec.rb
272
273
  - spec/graphql/object_type_spec.rb
273
274
  - spec/graphql/query/executor_spec.rb
275
+ - spec/graphql/query/type_resolver_spec.rb
274
276
  - spec/graphql/query_spec.rb
275
277
  - spec/graphql/schema/field_validator_spec.rb
276
278
  - spec/graphql/schema/type_reducer_spec.rb
@@ -327,6 +329,7 @@ test_files:
327
329
  - spec/graphql/base_type_spec.rb
328
330
  - spec/graphql/directive_spec.rb
329
331
  - spec/graphql/enum_type_spec.rb
332
+ - spec/graphql/execution_error_spec.rb
330
333
  - spec/graphql/field_spec.rb
331
334
  - spec/graphql/id_type_spec.rb
332
335
  - spec/graphql/input_object_type_spec.rb
@@ -340,6 +343,7 @@ test_files:
340
343
  - spec/graphql/language/visitor_spec.rb
341
344
  - spec/graphql/object_type_spec.rb
342
345
  - spec/graphql/query/executor_spec.rb
346
+ - spec/graphql/query/type_resolver_spec.rb
343
347
  - spec/graphql/query_spec.rb
344
348
  - spec/graphql/schema/field_validator_spec.rb
345
349
  - spec/graphql/schema/type_reducer_spec.rb
@@ -1,16 +0,0 @@
1
- module GraphQL
2
- class Query
3
- class BaseExecution
4
- class SelectedObjectResolution
5
- attr_reader :ast_node, :parent_type, :target, :query, :execution_strategy
6
- def initialize(ast_node, parent_type, target, query, execution_strategy)
7
- @ast_node = ast_node
8
- @parent_type = parent_type
9
- @target = target
10
- @query = query
11
- @execution_strategy = execution_strategy
12
- end
13
- end
14
- end
15
- end
16
- end