graphql 1.3.0 → 1.4.0

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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/base_type.rb +33 -5
  3. data/lib/graphql/boolean_type.rb +1 -0
  4. data/lib/graphql/compatibility/execution_specification.rb +1 -1
  5. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -0
  6. data/lib/graphql/directive.rb +10 -2
  7. data/lib/graphql/directive/deprecated_directive.rb +1 -0
  8. data/lib/graphql/directive/include_directive.rb +1 -0
  9. data/lib/graphql/directive/skip_directive.rb +1 -0
  10. data/lib/graphql/enum_type.rb +1 -0
  11. data/lib/graphql/execution/execute.rb +1 -13
  12. data/lib/graphql/float_type.rb +1 -0
  13. data/lib/graphql/id_type.rb +1 -0
  14. data/lib/graphql/input_object_type.rb +12 -2
  15. data/lib/graphql/int_type.rb +1 -0
  16. data/lib/graphql/interface_type.rb +1 -0
  17. data/lib/graphql/introspection/directive_location_enum.rb +1 -0
  18. data/lib/graphql/introspection/directive_type.rb +1 -0
  19. data/lib/graphql/introspection/enum_value_type.rb +1 -0
  20. data/lib/graphql/introspection/field_type.rb +1 -0
  21. data/lib/graphql/introspection/input_fields_field.rb +1 -1
  22. data/lib/graphql/introspection/input_value_type.rb +1 -0
  23. data/lib/graphql/introspection/schema_type.rb +2 -0
  24. data/lib/graphql/introspection/type_kind_enum.rb +1 -0
  25. data/lib/graphql/introspection/type_type.rb +1 -0
  26. data/lib/graphql/list_type.rb +1 -0
  27. data/lib/graphql/non_null_type.rb +1 -0
  28. data/lib/graphql/object_type.rb +1 -0
  29. data/lib/graphql/query.rb +50 -13
  30. data/lib/graphql/query/context.rb +5 -4
  31. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -22
  32. data/lib/graphql/relay/array_connection.rb +3 -1
  33. data/lib/graphql/relay/connection_type.rb +15 -1
  34. data/lib/graphql/relay/node.rb +1 -0
  35. data/lib/graphql/relay/page_info.rb +1 -0
  36. data/lib/graphql/relay/relation_connection.rb +2 -0
  37. data/lib/graphql/schema.rb +21 -13
  38. data/lib/graphql/schema/catchall_middleware.rb +2 -2
  39. data/lib/graphql/schema/middleware_chain.rb +71 -13
  40. data/lib/graphql/schema/null_mask.rb +10 -0
  41. data/lib/graphql/schema/printer.rb +85 -59
  42. data/lib/graphql/schema/rescue_middleware.rb +2 -2
  43. data/lib/graphql/schema/timeout_middleware.rb +2 -2
  44. data/lib/graphql/schema/validation.rb +1 -12
  45. data/lib/graphql/schema/warden.rb +48 -24
  46. data/lib/graphql/static_validation/literal_validator.rb +2 -2
  47. data/lib/graphql/string_type.rb +1 -0
  48. data/lib/graphql/union_type.rb +7 -1
  49. data/lib/graphql/version.rb +1 -1
  50. data/readme.md +0 -19
  51. data/spec/graphql/directive/skip_directive_spec.rb +8 -0
  52. data/spec/graphql/directive_spec.rb +9 -3
  53. data/spec/graphql/input_object_type_spec.rb +67 -0
  54. data/spec/graphql/query/variables_spec.rb +1 -1
  55. data/spec/graphql/relay/array_connection_spec.rb +9 -0
  56. data/spec/graphql/relay/connection_type_spec.rb +20 -0
  57. data/spec/graphql/relay/node_spec.rb +6 -0
  58. data/spec/graphql/relay/page_info_spec.rb +4 -0
  59. data/spec/graphql/relay/relation_connection_spec.rb +8 -0
  60. data/spec/graphql/scalar_type_spec.rb +4 -0
  61. data/spec/graphql/schema/middleware_chain_spec.rb +27 -13
  62. data/spec/graphql/schema/printer_spec.rb +121 -6
  63. data/spec/graphql/schema/rescue_middleware_spec.rb +4 -4
  64. data/spec/graphql/schema/warden_spec.rb +16 -12
  65. data/spec/graphql/schema_spec.rb +9 -0
  66. data/spec/graphql/string_type_spec.rb +10 -4
  67. data/spec/spec_helper.rb +2 -1
  68. data/spec/support/star_wars_schema.rb +2 -2
  69. metadata +19 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0019d58e7660531d537f4318a9f77df48ee6c501
4
- data.tar.gz: b1b229e62437f03ce0f5003a92c2546b733121ad
3
+ metadata.gz: 54eddb1e7e7ebdbe1ada0ab8286bda07a4141ebc
4
+ data.tar.gz: d9cc5078d078b0d9d8eded46a17ae224d33b738c
5
5
  SHA512:
6
- metadata.gz: 7d9f28b11005ac84e02b4528cd6c75ace38368c7bed476bc08a7c8b5b88e6a2643a2e5a3779da11babcf983aacc30bcc4bf6a69e53da83cc8e0b4ecac042a5f9
7
- data.tar.gz: 22249283811a82bda630d4d5f24149cfbdea7ad2a7aa9a4583810a318f054093c077b87d6f84550c129e3d431f3a504fa0b97ad109c65b1b89dd0f6e7716e256
6
+ metadata.gz: f918ba8ec64d8e3157d454ef76002b4087644fcb1f92a50821f5fd189f40806b4daec24d27049c022a59c27dc9a698742ad099546ce53b20645a7e0f6ebd8c28
7
+ data.tar.gz: 21140eaea9b18fd8405cb195f67d8f380d08dbf7d537e191c4672bd65240b1f589074927e0a62951f6506eaf0762efcd351e35b0e7951c4012b3552d70b747e0
@@ -4,12 +4,22 @@ module GraphQL
4
4
  class BaseType
5
5
  include GraphQL::Define::NonNullWithBang
6
6
  include GraphQL::Define::InstanceDefinable
7
- accepts_definitions :name, :description, {
8
- connection: GraphQL::Define::AssignConnection,
9
- global_id_field: GraphQL::Define::AssignGlobalIdField,
10
- }
7
+ accepts_definitions :name, :description,
8
+ :introspection,
9
+ :default_scalar,
10
+ :default_relay,
11
+ {
12
+ connection: GraphQL::Define::AssignConnection,
13
+ global_id_field: GraphQL::Define::AssignGlobalIdField,
14
+ }
11
15
 
12
- ensure_defined(:name, :description)
16
+ ensure_defined(:name, :description, :introspection?, :default_scalar?)
17
+
18
+ def initialize
19
+ @introspection = false
20
+ @default_scalar = false
21
+ @default_relay = false
22
+ end
13
23
 
14
24
  def initialize_copy(other)
15
25
  super
@@ -24,6 +34,24 @@ module GraphQL
24
34
  # @return [String, nil] a description for this type
25
35
  attr_accessor :description
26
36
 
37
+ # @return [Boolean] Is this type a predefined introspection type?
38
+ def introspection?
39
+ @introspection
40
+ end
41
+
42
+ # @return [Boolean] Is this type a built-in scalar type? (eg, `String`, `Int`)
43
+ def default_scalar?
44
+ @default_scalar
45
+ end
46
+
47
+ # @return [Boolean] Is this type a built-in Relay type? (`Node`, `PageInfo`)
48
+ def default_relay?
49
+ @default_relay
50
+ end
51
+
52
+ # @api private
53
+ attr_writer :introspection, :default_scalar, :default_relay
54
+
27
55
  # @param other [GraphQL::BaseType] compare to this object
28
56
  # @return [Boolean] are these types equivalent? (incl. non-null, list)
29
57
  def ==(other)
@@ -5,4 +5,5 @@ GraphQL::BOOLEAN_TYPE = GraphQL::ScalarType.define do
5
5
 
6
6
  coerce_input ->(value) { (value == true || value == false) ? value : nil }
7
7
  coerce_result ->(value) { !!value }
8
+ default_scalar true
8
9
  end
@@ -198,7 +198,7 @@ module GraphQL
198
198
  end
199
199
 
200
200
  def test_it_applies_masking
201
- no_org = ->(member) { member.name == "Organization" }
201
+ no_org = ->(member, ctx) { member.name == "Organization" }
202
202
  query_string = %|
203
203
  {
204
204
  node(id: "2001") {
@@ -49,6 +49,7 @@ module GraphQL
49
49
  end
50
50
 
51
51
  module TestMiddleware
52
+ # TODO: Once deprecated `next_middleware` argument becomes unsupported, add `&` to the argument
52
53
  def self.call(parent_type, parent_object, field_definition, field_args, query_context, next_middleware)
53
54
  query_context[:middleware_log] && query_context[:middleware_log] << field_definition.name
54
55
  next_middleware.call
@@ -8,10 +8,12 @@ module GraphQL
8
8
  #
9
9
  class Directive
10
10
  include GraphQL::Define::InstanceDefinable
11
- accepts_definitions :locations, :name, :description, :arguments, argument: GraphQL::Define::AssignArgument
11
+ accepts_definitions :locations, :name, :description, :arguments, :default_directive, argument: GraphQL::Define::AssignArgument
12
12
 
13
13
  attr_accessor :locations, :arguments, :name, :description
14
- ensure_defined(:locations, :arguments, :name, :description)
14
+ # @api private
15
+ attr_writer :default_directive
16
+ ensure_defined(:locations, :arguments, :name, :description, :default_directive?)
15
17
 
16
18
  LOCATIONS = [
17
19
  QUERY = :QUERY,
@@ -58,6 +60,7 @@ module GraphQL
58
60
 
59
61
  def initialize
60
62
  @arguments = {}
63
+ @default_directive = false
61
64
  end
62
65
 
63
66
  def to_s
@@ -75,6 +78,11 @@ module GraphQL
75
78
  def on_operation?
76
79
  locations.include?(QUERY) && locations.include?(MUTATION) && locations.include?(SUBSCRIPTION)
77
80
  end
81
+
82
+ # @return [Boolean] Is this directive supplied by default? (eg `@skip`)
83
+ def default_directive?
84
+ @default_directive
85
+ end
78
86
  end
79
87
  end
80
88
 
@@ -9,4 +9,5 @@ GraphQL::Directive::DeprecatedDirective = GraphQL::Directive.define do
9
9
  "in [Markdown](https://daringfireball.net/projects/markdown/)."
10
10
 
11
11
  argument :reason, GraphQL::STRING_TYPE, reason_description, default_value: GraphQL::Directive::DEFAULT_DEPRECATION_REASON
12
+ default_directive true
12
13
  end
@@ -4,4 +4,5 @@ GraphQL::Directive::IncludeDirective = GraphQL::Directive.define do
4
4
  description "Directs the executor to include this field or fragment only when the `if` argument is true."
5
5
  locations([GraphQL::Directive::FIELD, GraphQL::Directive::FRAGMENT_SPREAD, GraphQL::Directive::INLINE_FRAGMENT])
6
6
  argument :if, !GraphQL::BOOLEAN_TYPE, 'Included when true.'
7
+ default_directive true
7
8
  end
@@ -5,4 +5,5 @@ GraphQL::Directive::SkipDirective = GraphQL::Directive.define do
5
5
  locations([GraphQL::Directive::FIELD, GraphQL::Directive::FRAGMENT_SPREAD, GraphQL::Directive::INLINE_FRAGMENT])
6
6
 
7
7
  argument :if, !GraphQL::BOOLEAN_TYPE, 'Skipped when true.'
8
+ default_directive true
8
9
  end
@@ -76,6 +76,7 @@ module GraphQL
76
76
  ensure_defined(:values, :validate_non_null_input, :coerce_non_null_input, :coerce_result)
77
77
 
78
78
  def initialize
79
+ super
79
80
  @values_by_name = {}
80
81
  end
81
82
 
@@ -57,20 +57,8 @@ module GraphQL
57
57
  )
58
58
 
59
59
  arguments = query.arguments_for(selection.irep_node, field)
60
- middlewares = query.schema.middleware
61
- resolve_arguments = [parent_type, object, field, arguments, field_ctx]
62
-
63
60
  raw_value = begin
64
- # only run a middleware chain if there are any middleware
65
- if middlewares.any?
66
- chain = GraphQL::Schema::MiddlewareChain.new(
67
- steps: middlewares + [FieldResolveStep],
68
- arguments: resolve_arguments
69
- )
70
- chain.call
71
- else
72
- FieldResolveStep.call(*resolve_arguments)
73
- end
61
+ query_ctx.schema.middleware.invoke([parent_type, object, field, arguments, field_ctx])
74
62
  rescue GraphQL::ExecutionError => err
75
63
  err
76
64
  end
@@ -5,4 +5,5 @@ GraphQL::FLOAT_TYPE = GraphQL::ScalarType.define do
5
5
 
6
6
  coerce_input ->(value) { value.is_a?(Numeric) ? value.to_f : nil }
7
7
  coerce_result ->(value) { value.to_f }
8
+ default_scalar true
8
9
  end
@@ -12,4 +12,5 @@ GraphQL::ID_TYPE = GraphQL::ScalarType.define do
12
12
  nil
13
13
  end
14
14
  }
15
+ default_scalar true
15
16
  end
@@ -42,6 +42,7 @@ module GraphQL
42
42
 
43
43
 
44
44
  def initialize
45
+ super
45
46
  @arguments = {}
46
47
  end
47
48
 
@@ -57,7 +58,16 @@ module GraphQL
57
58
  def validate_non_null_input(input, warden)
58
59
  result = GraphQL::Query::InputValidationResult.new
59
60
 
60
- visible_arguments_map = warden.input_fields(self).reduce({}) { |m, f| m[f.name] = f; m}
61
+ if (input.to_h rescue nil).nil?
62
+ result.add_problem(
63
+ "Expected #{JSON.generate(input, quirks_mode: true)} to be a key, value object " \
64
+ " responding to `to_h`."
65
+ )
66
+ return result
67
+ end
68
+
69
+
70
+ visible_arguments_map = warden.arguments(self).reduce({}) { |m, f| m[f.name] = f; m}
61
71
 
62
72
  # Items in the input that are unexpected
63
73
  input.each do |name, value|
@@ -67,7 +77,7 @@ module GraphQL
67
77
  end
68
78
 
69
79
  # Items in the input that are expected, but have invalid values
70
- invalid_fields = visible_arguments_map.map do |name, field|
80
+ visible_arguments_map.map do |name, field|
71
81
  field_result = field.type.validate_input(input[name], warden)
72
82
  if !field_result.valid?
73
83
  result.merge_result!(name, field_result)
@@ -5,4 +5,5 @@ GraphQL::INT_TYPE = GraphQL::ScalarType.define do
5
5
 
6
6
  coerce_input ->(value) { value.is_a?(Numeric) ? value.to_i : nil }
7
7
  coerce_result ->(value) { value.to_i }
8
+ default_scalar true
8
9
  end
@@ -29,6 +29,7 @@ module GraphQL
29
29
  ensure_defined :fields
30
30
 
31
31
  def initialize
32
+ super
32
33
  @fields = {}
33
34
  end
34
35
 
@@ -7,4 +7,5 @@ GraphQL::Introspection::DirectiveLocationEnum = GraphQL::EnumType.define do
7
7
  GraphQL::Directive::LOCATIONS.each do |location|
8
8
  value(location.to_s, GraphQL::Directive::LOCATION_DESCRIPTIONS[location], value: location)
9
9
  end
10
+ introspection true
10
11
  end
@@ -14,4 +14,5 @@ GraphQL::Introspection::DirectiveType = GraphQL::ObjectType.define do
14
14
  field :onOperation, !types.Boolean, deprecation_reason: "Use `locations`.", property: :on_operation?
15
15
  field :onFragment, !types.Boolean, deprecation_reason: "Use `locations`.", property: :on_fragment?
16
16
  field :onField, !types.Boolean, deprecation_reason: "Use `locations`.", property: :on_field?
17
+ introspection true
17
18
  end
@@ -10,4 +10,5 @@ GraphQL::Introspection::EnumValueType = GraphQL::ObjectType.define do
10
10
  resolve ->(obj, a, c) { !!obj.deprecation_reason }
11
11
  end
12
12
  field :deprecationReason, types.String, property: :deprecation_reason
13
+ introspection true
13
14
  end
@@ -11,4 +11,5 @@ GraphQL::Introspection::FieldType = GraphQL::ObjectType.define do
11
11
  resolve ->(obj, a, c) { !!obj.deprecation_reason }
12
12
  end
13
13
  field :deprecationReason, types.String, property: :deprecation_reason
14
+ introspection true
14
15
  end
@@ -4,7 +4,7 @@ GraphQL::Introspection::InputFieldsField = GraphQL::Field.define do
4
4
  type types[!GraphQL::Introspection::InputValueType]
5
5
  resolve ->(target, a, ctx) {
6
6
  if target.kind.input_object?
7
- ctx.warden.input_fields(target)
7
+ ctx.warden.arguments(target)
8
8
  else
9
9
  nil
10
10
  end
@@ -17,4 +17,5 @@ GraphQL::Introspection::InputValueType = GraphQL::ObjectType.define do
17
17
  end
18
18
  }
19
19
  end
20
+ introspection true
20
21
  end
@@ -24,4 +24,6 @@ GraphQL::Introspection::SchemaType = GraphQL::ObjectType.define do
24
24
  field :directives, !types[!GraphQL::Introspection::DirectiveType], "A list of all directives supported by this server." do
25
25
  resolve ->(obj, arg, ctx) { obj.directives.values }
26
26
  end
27
+
28
+ introspection true
27
29
  end
@@ -5,4 +5,5 @@ GraphQL::Introspection::TypeKindEnum = GraphQL::EnumType.define do
5
5
  GraphQL::TypeKinds::TYPE_KINDS.each do |type_kind|
6
6
  value(type_kind.name, type_kind.description)
7
7
  end
8
+ introspection true
8
9
  end
@@ -22,4 +22,5 @@ GraphQL::Introspection::TypeType = GraphQL::ObjectType.define do
22
22
  field :enumValues, GraphQL::Introspection::EnumValuesField
23
23
  field :inputFields, GraphQL::Introspection::InputFieldsField
24
24
  field :ofType, GraphQL::Introspection::OfTypeField
25
+ introspection true
25
26
  end
@@ -28,6 +28,7 @@ module GraphQL
28
28
  include GraphQL::BaseType::ModifiesAnotherType
29
29
  attr_reader :of_type
30
30
  def initialize(of_type:)
31
+ super()
31
32
  @of_type = of_type
32
33
  end
33
34
 
@@ -33,6 +33,7 @@ module GraphQL
33
33
 
34
34
  attr_reader :of_type
35
35
  def initialize(of_type:)
36
+ super()
36
37
  @of_type = of_type
37
38
  end
38
39
 
@@ -35,6 +35,7 @@ module GraphQL
35
35
 
36
36
 
37
37
  def initialize
38
+ super
38
39
  @fields = {}
39
40
  @dirty_interfaces = []
40
41
  end
@@ -18,14 +18,6 @@ module GraphQL
18
18
  end
19
19
  end
20
20
 
21
- module NullExcept
22
- module_function
23
-
24
- def call(member)
25
- false
26
- end
27
- end
28
-
29
21
  attr_reader :schema, :document, :context, :fragments, :operations, :root_value, :max_depth, :query_string, :warden, :provided_variables
30
22
 
31
23
  # Prepare query `query_string` on `schema`
@@ -38,11 +30,19 @@ module GraphQL
38
30
  # @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
39
31
  # @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
40
32
  # @param except [<#call(schema_member)>] If provided, objects will be hidden from the schema when `.call(schema_member)` returns truthy
41
- def initialize(schema, query_string = nil, document: nil, context: nil, variables: {}, validate: true, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except: NullExcept)
33
+ def initialize(schema, query_string = nil, document: nil, context: nil, variables: {}, validate: true, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil, except: nil, only: nil)
42
34
  fail ArgumentError, "a query string or document is required" unless query_string || document
43
35
 
44
36
  @schema = schema
45
- @warden = GraphQL::Schema::Warden.new(schema, except)
37
+ mask = if except
38
+ wrap_if_legacy_mask(except)
39
+ elsif only
40
+ InvertedMask.new(wrap_if_legacy_mask(only))
41
+ else
42
+ schema.default_mask
43
+ end
44
+ @context = Context.new(query: self, values: context)
45
+ @warden = GraphQL::Schema::Warden.new(mask, schema: @schema, context: @context)
46
46
  @max_depth = max_depth || schema.max_depth
47
47
  @max_complexity = max_complexity || schema.max_complexity
48
48
  @query_analyzers = schema.query_analyzers.dup
@@ -52,7 +52,6 @@ module GraphQL
52
52
  if @max_complexity
53
53
  @query_analyzers << GraphQL::Analysis::MaxQueryComplexity.new(@max_complexity)
54
54
  end
55
- @context = Context.new(query: self, values: context)
56
55
  @root_value = root_value
57
56
  @operation_name = operation_name
58
57
  @fragments = {}
@@ -74,6 +73,8 @@ module GraphQL
74
73
  end
75
74
  end
76
75
 
76
+ @resolved_types_cache = Hash.new { |h, k| h[k] = @schema.resolve_type(k, @context) }
77
+
77
78
  @arguments_cache = Hash.new { |h, k| h[k] = {} }
78
79
  @validation_errors = []
79
80
  @analysis_errors = []
@@ -214,8 +215,11 @@ module GraphQL
214
215
  @warden.possible_types(type)
215
216
  end
216
217
 
217
- def resolve_type(type)
218
- @schema.resolve_type(type, @context)
218
+ # @param value [Object] Any runtime value
219
+ # @return [GraphQL::ObjectType, nil] The runtime type of `value` from {Schema#resolve_type}
220
+ # @see {#possible_types} to apply filtering from `only` / `except`
221
+ def resolve_type(value)
222
+ @resolved_types_cache[value]
219
223
  end
220
224
 
221
225
  def mutation?
@@ -257,5 +261,38 @@ module GraphQL
257
261
  operations[operation_name]
258
262
  end
259
263
  end
264
+
265
+ def wrap_if_legacy_mask(mask)
266
+ if (mask.is_a?(Proc) && mask.arity == 1) || mask.method(:call).arity == 1
267
+ warn("Schema.execute(..., except:) filters now accept two arguments, `(member, ctx)`. One-argument filters are deprecated.")
268
+ LegacyMaskWrap.new(mask)
269
+ else
270
+ mask
271
+ end
272
+ end
273
+
274
+ # @api private
275
+ class InvertedMask
276
+ def initialize(inner_mask)
277
+ @inner_mask = inner_mask
278
+ end
279
+
280
+ # Returns true when the inner mask returned false
281
+ # Returns false when the inner mask returned true
282
+ def call(member, ctx)
283
+ !@inner_mask.call(member, ctx)
284
+ end
285
+ end
286
+
287
+ # @api private
288
+ class LegacyMaskWrap
289
+ def initialize(inner_mask)
290
+ @inner_mask = inner_mask
291
+ end
292
+
293
+ def call(member, ctx)
294
+ @inner_mask.call(member)
295
+ end
296
+ end
260
297
  end
261
298
  end
@@ -32,9 +32,6 @@ module GraphQL
32
32
  # @return [GraphQL::Schema]
33
33
  attr_reader :schema
34
34
 
35
- # @return [GraphQL::Schema::Mask::Warden]
36
- attr_reader :warden
37
-
38
35
  # @return [Array<String, Integer>] The current position in the result
39
36
  attr_reader :path
40
37
 
@@ -46,7 +43,6 @@ module GraphQL
46
43
  @schema = query.schema
47
44
  @values = values || {}
48
45
  @errors = []
49
- @warden = query.warden
50
46
  @path = []
51
47
  end
52
48
 
@@ -55,6 +51,11 @@ module GraphQL
55
51
  @values[key]
56
52
  end
57
53
 
54
+ # @return [GraphQL::Schema::Warden]
55
+ def warden
56
+ @warden ||= @query.warden
57
+ end
58
+
58
59
  # Reassign `key` to the hash passed to {Schema#execute} as `context:`
59
60
  def []=(key, value)
60
61
  @values[key] = value