Skip to content

Commit 627fd3d

Browse files
committed
Allow field null: to override resolver config
1 parent 3de803b commit 627fd3d

File tree

2 files changed

+27
-13
lines changed

2 files changed

+27
-13
lines changed

lib/graphql/schema/field.rb

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def method_conflict_warning?
187187
# @param name [Symbol] The underscore-cased version of this field name (will be camelized for the GraphQL API)
188188
# @param type [Class, GraphQL::BaseType, Array] The return type of this field
189189
# @param owner [Class] The type that this field belongs to
190-
# @param null [Boolean] `true` if this field may return `null`, `false` if it is never `null`
190+
# @param null [Boolean] (defaults to `true`) `true` if this field may return `null`, `false` if it is never `null`
191191
# @param description [String] Field description
192192
# @param deprecation_reason [String] If present, the field is marked "deprecated" with this message
193193
# @param method [Symbol] The method to call on the underlying object to resolve this field (defaults to `name`)
@@ -211,7 +211,7 @@ def method_conflict_warning?
211211
# @param ast_node [Language::Nodes::FieldDefinition, nil] If this schema was parsed from definition, this AST node defined the field
212212
# @param method_conflict_warning [Boolean] If false, skip the warning if this field's method conflicts with a built-in method
213213
# @param validates [Array<Hash>] Configurations for validating this field
214-
def initialize(type: nil, name: nil, owner: nil, null: true, description: :not_given, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, &definition_block)
214+
def initialize(type: nil, name: nil, owner: nil, null: nil, description: :not_given, deprecation_reason: nil, method: nil, hash_key: nil, dig: nil, resolver_method: nil, connection: nil, max_page_size: :not_given, scope: nil, introspection: false, camelize: true, trace: nil, complexity: nil, ast_node: nil, extras: EMPTY_ARRAY, extensions: EMPTY_ARRAY, connection_extension: self.class.connection_extension, resolver_class: nil, subscription_scope: nil, relay_node_field: false, relay_nodes_field: false, method_conflict_warning: true, broadcastable: nil, arguments: EMPTY_HASH, directives: EMPTY_HASH, validates: EMPTY_ARRAY, &definition_block)
215215
if name.nil?
216216
raise ArgumentError, "missing first `name` argument or keyword `name:`"
217217
end
@@ -253,7 +253,13 @@ def initialize(type: nil, name: nil, owner: nil, null: true, description: :not_g
253253
@resolver_method = resolver_method
254254
@complexity = complexity
255255
@return_type_expr = type
256-
@return_type_null = null
256+
@return_type_null = if !null.nil?
257+
null
258+
elsif resolver_class
259+
nil
260+
else
261+
true
262+
end
257263
@connection = connection
258264
@has_max_page_size = max_page_size != :not_given
259265
@max_page_size = max_page_size == :not_given ? nil : max_page_size
@@ -530,17 +536,13 @@ class MissingReturnTypeError < GraphQL::Error; end
530536
attr_writer :type
531537

532538
def type
533-
if @return_type_expr.nil?
534-
if @resolver_class && (t = @resolver_class.type)
535-
t
536-
else
537-
# Not enough info to determine type
538-
message = "Can't determine the return type for #{self.path}"
539-
if @resolver_class
540-
message += " (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
541-
end
542-
raise MissingReturnTypeError, message
539+
if @resolver_class
540+
return_type = @return_type_expr || @resolver_class.type_expr
541+
if return_type.nil?
542+
raise MissingReturnTypeError, "Can't determine the return type for #{self.path} (it has `resolver: #{@resolver_class}`, perhaps that class is missing a `type ...` declaration, or perhaps its type causes a cyclical loading issue)"
543543
end
544+
nullable = @return_type_null.nil? ? @resolver_class.null : @return_type_null
545+
Member::BuildType.parse_type(return_type, null: nullable)
544546
else
545547
@type ||= Member::BuildType.parse_type(@return_type_expr, null: @return_type_null)
546548
end

spec/graphql/schema/field_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,4 +694,16 @@ def search_results
694694
assert_equal [:b, :c, :a], field.all_argument_definitions.map(&:keyword)
695695
assert_equal false, field.scoped?
696696
end
697+
698+
it "accepts partial overrides for type an nullability" do
699+
nonnull_float_resolver = Class.new(GraphQL::Schema::Resolver) do
700+
type GraphQL::Types::Float, null: false
701+
end
702+
703+
nullable_field = GraphQL::Schema::Field.new(name: "blah", owner: nil, resolver_class: nonnull_float_resolver, null: true)
704+
assert_equal "Float", nullable_field.type.to_type_signature
705+
706+
int_field = GraphQL::Schema::Field.new(name: "blah", owner: nil, resolver_class: nonnull_float_resolver, type: GraphQL::Types::Int)
707+
assert_equal "Int!", int_field.type.to_type_signature
708+
end
697709
end

0 commit comments

Comments
 (0)