graphql 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/analyze_query.rb +4 -2
  3. data/lib/graphql/analysis/field_usage.rb +4 -4
  4. data/lib/graphql/analysis/query_complexity.rb +16 -21
  5. data/lib/graphql/argument.rb +13 -6
  6. data/lib/graphql/base_type.rb +2 -1
  7. data/lib/graphql/compatibility/execution_specification.rb +76 -0
  8. data/lib/graphql/compatibility/query_parser_specification.rb +16 -2
  9. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -5
  10. data/lib/graphql/compatibility/schema_parser_specification.rb +6 -0
  11. data/lib/graphql/define/assign_argument.rb +8 -2
  12. data/lib/graphql/define/instance_definable.rb +12 -15
  13. data/lib/graphql/directive.rb +2 -1
  14. data/lib/graphql/enum_type.rb +5 -7
  15. data/lib/graphql/field.rb +6 -11
  16. data/lib/graphql/field/resolve.rb +1 -0
  17. data/lib/graphql/input_object_type.rb +9 -9
  18. data/lib/graphql/interface_type.rb +2 -1
  19. data/lib/graphql/internal_representation.rb +1 -0
  20. data/lib/graphql/internal_representation/node.rb +31 -9
  21. data/lib/graphql/internal_representation/rewrite.rb +26 -26
  22. data/lib/graphql/internal_representation/selections.rb +41 -0
  23. data/lib/graphql/introspection/input_value_type.rb +6 -2
  24. data/lib/graphql/language/generation.rb +2 -0
  25. data/lib/graphql/language/lexer.rl +4 -0
  26. data/lib/graphql/language/nodes.rb +3 -0
  27. data/lib/graphql/language/parser.rb +525 -509
  28. data/lib/graphql/language/parser.y +2 -0
  29. data/lib/graphql/object_type.rb +2 -2
  30. data/lib/graphql/query.rb +21 -0
  31. data/lib/graphql/query/context.rb +52 -4
  32. data/lib/graphql/query/serial_execution.rb +3 -4
  33. data/lib/graphql/query/serial_execution/field_resolution.rb +35 -36
  34. data/lib/graphql/query/serial_execution/operation_resolution.rb +9 -15
  35. data/lib/graphql/query/serial_execution/selection_resolution.rb +14 -11
  36. data/lib/graphql/query/serial_execution/value_resolution.rb +18 -17
  37. data/lib/graphql/query/variables.rb +1 -1
  38. data/lib/graphql/relay/mutation.rb +5 -8
  39. data/lib/graphql/scalar_type.rb +1 -2
  40. data/lib/graphql/schema.rb +2 -13
  41. data/lib/graphql/schema/build_from_definition.rb +28 -13
  42. data/lib/graphql/schema/loader.rb +4 -1
  43. data/lib/graphql/schema/printer.rb +10 -3
  44. data/lib/graphql/schema/timeout_middleware.rb +18 -2
  45. data/lib/graphql/schema/unique_within_type.rb +6 -3
  46. data/lib/graphql/static_validation/literal_validator.rb +3 -1
  47. data/lib/graphql/union_type.rb +1 -2
  48. data/lib/graphql/version.rb +1 -1
  49. data/readme.md +1 -0
  50. data/spec/graphql/analysis/analyze_query_spec.rb +6 -8
  51. data/spec/graphql/argument_spec.rb +18 -0
  52. data/spec/graphql/define/assign_argument_spec.rb +48 -0
  53. data/spec/graphql/define/instance_definable_spec.rb +4 -2
  54. data/spec/graphql/execution_error_spec.rb +66 -0
  55. data/spec/graphql/input_object_type_spec.rb +81 -0
  56. data/spec/graphql/internal_representation/rewrite_spec.rb +104 -21
  57. data/spec/graphql/introspection/input_value_type_spec.rb +43 -6
  58. data/spec/graphql/introspection/schema_type_spec.rb +1 -0
  59. data/spec/graphql/introspection/type_type_spec.rb +2 -0
  60. data/spec/graphql/language/generation_spec.rb +3 -2
  61. data/spec/graphql/query/arguments_spec.rb +17 -4
  62. data/spec/graphql/query/context_spec.rb +23 -0
  63. data/spec/graphql/query/variables_spec.rb +15 -1
  64. data/spec/graphql/relay/mutation_spec.rb +42 -2
  65. data/spec/graphql/schema/build_from_definition_spec.rb +4 -2
  66. data/spec/graphql/schema/loader_spec.rb +59 -1
  67. data/spec/graphql/schema/printer_spec.rb +2 -0
  68. data/spec/graphql/schema/reduce_types_spec.rb +1 -1
  69. data/spec/graphql/schema/timeout_middleware_spec.rb +2 -2
  70. data/spec/graphql/schema/unique_within_type_spec.rb +9 -0
  71. data/spec/graphql/schema/validation_spec.rb +15 -3
  72. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +122 -0
  73. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +78 -0
  74. data/spec/support/dairy_app.rb +9 -0
  75. data/spec/support/minimum_input_object.rb +4 -0
  76. data/spec/support/star_wars_schema.rb +1 -1
  77. metadata +5 -5
  78. data/lib/graphql/query/serial_execution/execution_context.rb +0 -37
  79. data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -54
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d1d8b93486b17d67f6714c1ad867c5f5eb403a4
4
- data.tar.gz: 68dc546c4124fd8fb3752c911b63be9f9753ffc2
3
+ metadata.gz: 8e06bd99f6bb6350c2d7111d5014ef9c71154f8a
4
+ data.tar.gz: 1b90cfb31081700c64abab2f8f26a665bd2fe6fa
5
5
  SHA512:
6
- metadata.gz: eb42f273418ba3eda88ca784f3af4a20b0a57223b02adbf64736953446312e87ece3392f2c7b3d696ebbd66cecc8a38809ff6ff79bb623942dd6bced33c4f5bc
7
- data.tar.gz: 54669eb238917fedceba3df22ac927461a0a427b1d259a3277e6be1ffef420ada7ee1fc5abd63f605a4d5397e88a23d1d8ea73f95ebfd9cbaa97554b09b05089
6
+ metadata.gz: d8c0847198e4c6403cffac42b6cf8ab3cf1446d04ebcb91d2cb916244e170f0072d6ef9ee1ac355c4585ab62d0eac73048d34cb89e990b0cf62bde639d8fd166
7
+ data.tar.gz: ce1ea3d57512c38593c50ba2531994b5ce5ed83b0cb91ee13e4e78402d3ed4494c8d8ec88db2c037460e0379820b47821c0fcdb03a18cc804de17157fc252acd
@@ -32,8 +32,10 @@ module GraphQL
32
32
  def reduce_node(irep_node, reducer_states)
33
33
  visit_analyzers(:enter, irep_node, reducer_states)
34
34
 
35
- irep_node.children.each do |name, child_irep_node|
36
- reduce_node(child_irep_node, reducer_states)
35
+ irep_node.typed_children.each do |type_defn, children|
36
+ children.each do |name, child_irep_node|
37
+ reduce_node(child_irep_node, reducer_states)
38
+ end
37
39
  end
38
40
 
39
41
  visit_analyzers(:leave, irep_node, reducer_states)
@@ -26,10 +26,10 @@ module GraphQL
26
26
 
27
27
  def call(memo, visit_type, irep_node)
28
28
  if irep_node.ast_node.is_a?(GraphQL::Language::Nodes::Field) && visit_type == :leave
29
- irep_node.definitions.each do |type_defn, field_defn|
30
- field = "#{type_defn.name}.#{field_defn.name}"
31
- memo[:used_fields] << field
32
- memo[:used_deprecated_fields] << field if field_defn.deprecation_reason
29
+ field = "#{irep_node.owner_type.name}.#{irep_node.definition.name}"
30
+ memo[:used_fields] << field
31
+ if irep_node.definition.deprecation_reason
32
+ memo[:used_deprecated_fields] << field
33
33
  end
34
34
  end
35
35
 
@@ -46,7 +46,7 @@ module GraphQL
46
46
  type_complexities = memo[:complexities_on_type].pop
47
47
  child_complexity = type_complexities.max_possible_complexity
48
48
  own_complexity = get_complexity(irep_node, memo[:query], child_complexity)
49
- memo[:complexities_on_type].last.merge(irep_node.definitions, own_complexity)
49
+ memo[:complexities_on_type].last.merge(irep_node.owner_type, own_complexity)
50
50
  end
51
51
  end
52
52
  end
@@ -65,24 +65,18 @@ module GraphQL
65
65
  # Get a complexity value for a field,
66
66
  # by getting the number or calling its proc
67
67
  def get_complexity(irep_node, query, child_complexity)
68
- max_possible_complexity = 0
69
- irep_node.definitions.each do |type_defn, field_defn|
70
- defined_complexity = field_defn.complexity
71
- type_cpx = case defined_complexity
72
- when Proc
73
- args = query.arguments_for(irep_node, field_defn)
74
- defined_complexity.call(query.context, args, child_complexity)
75
- when Numeric
76
- defined_complexity + (child_complexity || 0)
77
- else
78
- raise("Invalid complexity: #{defined_complexity.inspect} on #{field_defn.name}")
79
- end
80
-
81
- if type_cpx > max_possible_complexity
82
- max_possible_complexity = type_cpx
83
- end
68
+ type_defn = irep_node.owner_type
69
+ field_defn = irep_node.definition
70
+ defined_complexity = field_defn.complexity
71
+ case defined_complexity
72
+ when Proc
73
+ args = query.arguments_for(irep_node, field_defn)
74
+ defined_complexity.call(query.context, args, child_complexity)
75
+ when Numeric
76
+ defined_complexity + (child_complexity || 0)
77
+ else
78
+ raise("Invalid complexity: #{defined_complexity.inspect} on #{field_defn.name}")
84
79
  end
85
- max_possible_complexity
86
80
  end
87
81
 
88
82
  # Selections on an object may apply differently depending on what is _actually_ returned by the resolve function.
@@ -112,9 +106,10 @@ module GraphQL
112
106
  max_complexity
113
107
  end
114
108
 
115
- # Store the complexity score for each of `types`
116
- def merge(definitions, complexity)
117
- definitions.each { |type_defn, field_defn| @types[type_defn] += complexity }
109
+ # Store the complexity for the branch on `type_defn`.
110
+ # Later we will see if this is the max complexity among branches.
111
+ def merge(type_defn, complexity)
112
+ @types[type_defn] += complexity
118
113
  end
119
114
 
120
115
  private
@@ -17,24 +17,31 @@ module GraphQL
17
17
  class Argument
18
18
  include GraphQL::Define::InstanceDefinable
19
19
  accepts_definitions :name, :type, :description, :default_value
20
- lazy_defined_attr_accessor :type, :description, :default_value, :name
20
+ attr_accessor :type, :description, :default_value, :name
21
+
22
+ ensure_defined(:name, :description, :default_value, :type=, :type)
23
+
24
+ def default_value?
25
+ !!@has_default_value
26
+ end
27
+
28
+ def default_value=(new_default_value)
29
+ @has_default_value = true
30
+ @default_value = new_default_value
31
+ end
21
32
 
22
33
  # @!attribute name
23
34
  # @return [String] The name of this argument on its {GraphQL::Field} or {GraphQL::InputObjectType}
24
35
 
25
36
  # @param new_input_type [GraphQL::BaseType, Proc] Assign a new input type for this argument (if it's a proc, it will be called after schema initialization)
26
37
  def type=(new_input_type)
27
- ensure_defined
28
38
  @clean_type = nil
29
39
  @dirty_type = new_input_type
30
40
  end
31
41
 
32
42
  # @return [GraphQL::BaseType] the input type for this argument
33
43
  def type
34
- @clean_type ||= begin
35
- ensure_defined
36
- GraphQL::BaseType.resolve_related_type(@dirty_type)
37
- end
44
+ @clean_type ||= GraphQL::BaseType.resolve_related_type(@dirty_type)
38
45
  end
39
46
  end
40
47
  end
@@ -8,7 +8,8 @@ module GraphQL
8
8
  global_id_field: GraphQL::Define::AssignGlobalIdField,
9
9
  }
10
10
 
11
- lazy_defined_attr_accessor :name, :description
11
+ attr_accessor :name, :description
12
+ ensure_defined(:name, :description)
12
13
 
13
14
  # @!attribute name
14
15
  # @return [String] the name of this type, must be unique within a Schema
@@ -407,6 +407,82 @@ module GraphQL
407
407
  error_messages = res["errors"].map { |e| e["message"] }
408
408
  assert_equal ["Error on Nullable"], error_messages
409
409
  end
410
+
411
+ def test_it_only_resolves_fields_once_on_typed_fragments
412
+ count = 0
413
+ counter_type = nil
414
+
415
+ has_count_interface = GraphQL::InterfaceType.define do
416
+ name "HasCount"
417
+ field :count, types.Int
418
+ field :counter, ->{ counter_type }
419
+ end
420
+
421
+ counter_type = GraphQL::ObjectType.define do
422
+ name "Counter"
423
+ interfaces [has_count_interface]
424
+ field :count, types.Int, resolve: ->(o,a,c) { count += 1 }
425
+ field :counter, has_count_interface, resolve: ->(o,a,c) { :counter }
426
+ end
427
+
428
+ alt_counter_type = GraphQL::ObjectType.define do
429
+ name "AltCounter"
430
+ interfaces [has_count_interface]
431
+ field :count, types.Int, resolve: ->(o,a,c) { count += 1 }
432
+ field :counter, has_count_interface, resolve: ->(o,a,c) { :counter }
433
+ end
434
+
435
+ has_counter_interface = GraphQL::InterfaceType.define do
436
+ name "HasCounter"
437
+ field :counter, counter_type
438
+ end
439
+
440
+ query_type = GraphQL::ObjectType.define do
441
+ name "Query"
442
+ interfaces [has_counter_interface]
443
+ field :counter, has_count_interface, resolve: ->(o,a,c) { :counter }
444
+ end
445
+
446
+ schema = GraphQL::Schema.define(
447
+ query: query_type,
448
+ resolve_type: ->(o, c) { o == :counter ? counter_type : nil },
449
+ orphan_types: [alt_counter_type],
450
+ )
451
+
452
+ res = schema.execute("
453
+ {
454
+ counter { count }
455
+ ... on HasCounter {
456
+ counter { count }
457
+ }
458
+ }
459
+ ")
460
+
461
+ expected_data = {
462
+ "counter" => { "count" => 1 }
463
+ }
464
+ assert_equal expected_data, res["data"]
465
+ assert_equal 1, count
466
+
467
+ # Deep typed children are correctly distinguished:
468
+ res = schema.execute("
469
+ {
470
+ counter {
471
+ ... on Counter {
472
+ counter { count }
473
+ }
474
+ ... on AltCounter {
475
+ counter { count, t: __typename }
476
+ }
477
+ }
478
+ }
479
+ ")
480
+
481
+ expected_data = {
482
+ "counter" => { "counter" => { "count" => 2 } }
483
+ }
484
+ assert_equal expected_data, res["data"]
485
+ end
410
486
  end
411
487
  end
412
488
  end
@@ -57,12 +57,15 @@ module GraphQL
57
57
  int: 3,
58
58
  float: 4.7e-24,
59
59
  bool: false,
60
- string: "☀︎🏆\\n \\" \u00b6 /",
60
+ string: "☀︎🏆 \\b \\f \\n \\r \\t \\" \u00b6 \\u00b6 / \\/",
61
61
  enum: ENUM_NAME,
62
62
  array: [7, 8, 9]
63
63
  object: {a: [1,2,3], b: {c: "4"}}
64
64
  unicode_bom: "\xef\xbb\xbfquery"
65
65
  keywordEnum: on
66
+ nullValue: null
67
+ nullValueInObject: {a: null, b: "b"}
68
+ nullValueInArray: ["a", null, "b"]
66
69
  )
67
70
  }
68
71
  |
@@ -71,7 +74,7 @@ module GraphQL
71
74
  assert_equal 3, inputs[0].value, "Integers"
72
75
  assert_equal 0.47e-23, inputs[1].value, "Floats"
73
76
  assert_equal false, inputs[2].value, "Booleans"
74
- assert_equal %|☀︎🏆\n " ¶ /|, inputs[3].value, "Strings"
77
+ assert_equal %|☀︎🏆 \b \f \n \r \t " ¶ ¶ / /|, inputs[3].value, "Strings"
75
78
  assert_instance_of GraphQL::Language::Nodes::Enum, inputs[4].value
76
79
  assert_equal "ENUM_NAME", inputs[4].value.name, "Enums"
77
80
  assert_equal [7,8,9], inputs[5].value, "Lists"
@@ -85,6 +88,17 @@ module GraphQL
85
88
 
86
89
  assert_equal %|\xef\xbb\xbfquery|, inputs[7].value, "Unicode BOM"
87
90
  assert_equal "on", inputs[8].value.name, "Enum value 'on'"
91
+
92
+ assert_instance_of GraphQL::Language::Nodes::NullValue, inputs[9].value
93
+
94
+ args = inputs[10].value.arguments
95
+ assert_instance_of GraphQL::Language::Nodes::NullValue, args.find{ |arg| arg.name == 'a' }.value
96
+ assert_equal 'b', args.find{ |arg| arg.name == 'b' }.value
97
+
98
+ values = inputs[11].value
99
+ assert_equal 'a', values[0]
100
+ assert_instance_of GraphQL::Language::Nodes::NullValue, values[1]
101
+ assert_equal 'b', values[2]
88
102
  end
89
103
  end
90
104
  end
@@ -70,11 +70,6 @@ module GraphQL
70
70
  assert_raises_parse_error("{ ...on }")
71
71
  assert_raises_parse_error("fragment on on Type { field }")
72
72
  end
73
-
74
- def test_it_rejects_null
75
- err = assert_raises_parse_error("{ field(input: null) }")
76
- assert_includes(err.message, "null")
77
- end
78
73
  end
79
74
  end
80
75
  end
@@ -184,6 +184,11 @@ module GraphQL
184
184
  assert_equal GraphQL::Language::Nodes::InterfaceTypeDefinition, interface_type_definition.class
185
185
  assert_equal 'Comment for interface definitions', interface_type_definition.description
186
186
  assert_equal 'Amount of wheels', interface_type_definition.fields[0].description
187
+
188
+ brand_field = interface_type_definition.fields[1]
189
+ assert_equal 1, brand_field.arguments.length
190
+ assert_equal 'argument', brand_field.arguments[0].name
191
+ assert_instance_of GraphQL::Language::Nodes::NullValue, brand_field.arguments[0].default_value
187
192
  end
188
193
  end
189
194
  end
@@ -230,6 +235,7 @@ module GraphQL
230
235
  interface Vehicle {
231
236
  # Amount of wheels
232
237
  wheels: Int!
238
+ brand(argument: String = null): String!
233
239
  }
234
240
 
235
241
  # Comment at the end of schema
@@ -2,16 +2,22 @@ module GraphQL
2
2
  module Define
3
3
  # Turn argument configs into a {GraphQL::Argument}.
4
4
  module AssignArgument
5
- def self.call(target, name, type = nil, description = nil, default_value: nil, &block)
5
+ def self.call(target, name, type = nil, description = nil, **rest, &block)
6
6
  argument = if block_given?
7
7
  GraphQL::Argument.define(&block)
8
8
  else
9
9
  GraphQL::Argument.new
10
10
  end
11
+
12
+ unsupported_keys = rest.keys - [:default_value]
13
+ if unsupported_keys.any?
14
+ raise ArgumentError.new("unknown keyword#{unsupported_keys.length > 1 ? 's' : ''}: #{unsupported_keys.join(', ')}")
15
+ end
16
+
11
17
  argument.name = name.to_s
12
18
  type && argument.type = type
13
19
  description && argument.description = description
14
- !default_value.nil? && argument.default_value = default_value
20
+ rest.key?(:default_value) && argument.default_value = rest[:default_value]
15
21
 
16
22
  target.arguments[name.to_s] = argument
17
23
  end
@@ -71,13 +71,13 @@ module GraphQL
71
71
  module InstanceDefinable
72
72
  def self.included(base)
73
73
  base.extend(ClassMethods)
74
+ base.ensure_defined(:metadata)
74
75
  end
75
76
 
76
77
  # `metadata` can store arbitrary key-values with an object.
77
78
  #
78
79
  # @return [Hash<Object, Object>] Hash for user-defined storage
79
80
  def metadata
80
- ensure_defined
81
81
  @metadata ||= {}
82
82
  end
83
83
 
@@ -174,21 +174,18 @@ module GraphQL
174
174
  @own_dictionary = own_dictionary.merge(new_assignments)
175
175
  end
176
176
 
177
- # Define a reader and writer for each of `attr_names` which
178
- # ensures that the definition block was called before accessing it.
179
- def lazy_defined_attr_accessor(*attr_names)
180
- attr_names.each do |attr_name|
181
- ivar_name = :"@#{attr_name}"
182
- define_method(attr_name) do
183
- ensure_defined
184
- instance_variable_get(ivar_name)
185
- end
186
-
187
- define_method("#{attr_name}=") do |new_value|
188
- ensure_defined
189
- instance_variable_set(ivar_name, new_value)
177
+ def ensure_defined(*method_names)
178
+ ensure_defined_module = Module.new
179
+ ensure_defined_module.module_eval {
180
+ method_names.each do |method_name|
181
+ define_method(method_name) { |*args, &block|
182
+ ensure_defined
183
+ super(*args, &block)
184
+ }
190
185
  end
191
- end
186
+ }
187
+ self.prepend(ensure_defined_module)
188
+ nil
192
189
  end
193
190
 
194
191
  # @return [Hash] combined definitions for self and ancestors
@@ -9,7 +9,8 @@ module GraphQL
9
9
  include GraphQL::Define::InstanceDefinable
10
10
  accepts_definitions :locations, :name, :description, :arguments, argument: GraphQL::Define::AssignArgument
11
11
 
12
- lazy_defined_attr_accessor :locations, :arguments, :name, :description
12
+ attr_accessor :locations, :arguments, :name, :description
13
+ ensure_defined(:locations, :arguments, :name, :description)
13
14
 
14
15
  LOCATIONS = [
15
16
  QUERY = :QUERY,
@@ -72,6 +72,7 @@ module GraphQL
72
72
 
73
73
  class EnumType < GraphQL::BaseType
74
74
  accepts_definitions :values, value: GraphQL::Define::AssignEnumValue
75
+ ensure_defined(:values, :validate_non_null_input, :coerce_non_null_input, :coerce_result)
75
76
 
76
77
  def initialize
77
78
  @values_by_name = {}
@@ -90,7 +91,6 @@ module GraphQL
90
91
 
91
92
  # @return [Hash<String => EnumValue>] `{name => value}` pairs contained in this type
92
93
  def values
93
- ensure_defined
94
94
  @values_by_name
95
95
  end
96
96
 
@@ -99,7 +99,6 @@ module GraphQL
99
99
  end
100
100
 
101
101
  def validate_non_null_input(value_name, warden)
102
- ensure_defined
103
102
  result = GraphQL::Query::InputValidationResult.new
104
103
  allowed_values = warden.enum_values(self)
105
104
  matching_value = allowed_values.find { |v| v.name == value_name }
@@ -120,7 +119,6 @@ module GraphQL
120
119
  # @param value_name [String] the string representation of this enum value
121
120
  # @return [Object] the underlying value for this enum value
122
121
  def coerce_non_null_input(value_name)
123
- ensure_defined
124
122
  if @values_by_name.key?(value_name)
125
123
  @values_by_name.fetch(value_name).value
126
124
  else
@@ -129,7 +127,6 @@ module GraphQL
129
127
  end
130
128
 
131
129
  def coerce_result(value, warden = nil)
132
- ensure_defined
133
130
  all_values = warden ? warden.enum_values(self) : @values_by_name.each_value
134
131
  enum_value = all_values.find { |val| val.value == value }
135
132
  if enum_value
@@ -148,9 +145,10 @@ module GraphQL
148
145
  # Created with the `value` helper
149
146
  class EnumValue
150
147
  include GraphQL::Define::InstanceDefinable
151
- accepts_definitions :name, :description, :deprecation_reason, :value
152
-
153
- lazy_defined_attr_accessor :name, :description, :deprecation_reason, :value
148
+ ATTRIBUTES = [:name, :description, :deprecation_reason, :value]
149
+ accepts_definitions(*ATTRIBUTES)
150
+ attr_accessor(*ATTRIBUTES)
151
+ ensure_defined(*ATTRIBUTES)
154
152
  end
155
153
 
156
154
  class UnresolvedValueError < GraphQL::Error
@@ -126,7 +126,11 @@ module GraphQL
126
126
  argument: GraphQL::Define::AssignArgument
127
127
 
128
128
 
129
- lazy_defined_attr_accessor :name, :deprecation_reason, :description, :property, :hash_key, :mutation, :arguments, :complexity
129
+ attr_accessor :name, :deprecation_reason, :description, :property, :hash_key, :mutation, :arguments, :complexity
130
+ ensure_defined(
131
+ :name, :deprecation_reason, :description, :property, :hash_key, :mutation, :arguments, :complexity,
132
+ :resolve, :resolve=, :type, :type=, :name=, :property=, :hash_key=
133
+ )
130
134
 
131
135
  # @!attribute [r] resolve_proc
132
136
  # @return [<#call(obj, args,ctx)>] A proc-like object which can be called to return the field's value
@@ -158,7 +162,6 @@ module GraphQL
158
162
  # @param arguments [Hash] Arguments declared in the query
159
163
  # @param context [GraphQL::Query::Context]
160
164
  def resolve(object, arguments, context)
161
- ensure_defined
162
165
  resolve_proc.call(object, arguments, context)
163
166
  end
164
167
 
@@ -166,22 +169,17 @@ module GraphQL
166
169
  # a new resolve proc will be build based on its {#name}, {#property} or {#hash_key}.
167
170
  # @param new_resolve_proc [<#call(obj, args, ctx)>, nil]
168
171
  def resolve=(new_resolve_proc)
169
- ensure_defined
170
172
  @resolve_proc = new_resolve_proc || build_default_resolver
171
173
  end
172
174
 
173
175
  def type=(new_return_type)
174
- ensure_defined
175
176
  @clean_type = nil
176
177
  @dirty_type = new_return_type
177
178
  end
178
179
 
179
180
  # Get the return type for this field.
180
181
  def type
181
- @clean_type ||= begin
182
- ensure_defined
183
- GraphQL::BaseType.resolve_related_type(@dirty_type)
184
- end
182
+ @clean_type ||= GraphQL::BaseType.resolve_related_type(@dirty_type)
185
183
  end
186
184
 
187
185
  # You can only set a field's name _once_ -- this to prevent
@@ -189,7 +187,6 @@ module GraphQL
189
187
  #
190
188
  # This is important because {#name} may be used by {#resolve}.
191
189
  def name=(new_name)
192
- ensure_defined
193
190
  if @name.nil?
194
191
  @name = new_name
195
192
  elsif @name != new_name
@@ -199,14 +196,12 @@ module GraphQL
199
196
 
200
197
  # @param new_property [Symbol] A method to call to resolve this field. Overrides the existing resolve proc.
201
198
  def property=(new_property)
202
- ensure_defined
203
199
  @property = new_property
204
200
  self.resolve = nil # reset resolve proc
205
201
  end
206
202
 
207
203
  # @param new_hash_key [Symbol] A key to access with `#[key]` to resolve this field. Overrides the existing resolve proc.
208
204
  def hash_key=(new_hash_key)
209
- ensure_defined
210
205
  @hash_key = new_hash_key
211
206
  self.resolve = nil # reset resolve proc
212
207
  end