diff --git a/lib/graphql/schema/field.rb b/lib/graphql/schema/field.rb index 227f56456a..eca1979084 100644 --- a/lib/graphql/schema/field.rb +++ b/lib/graphql/schema/field.rb @@ -246,7 +246,7 @@ def initialize(type: nil, name: nil, owner: nil, null: nil, description: :not_gi end end - method_name = method || name_s + method_name = method || hash_key || name_s @dig_keys = dig if hash_key @hash_key = hash_key @@ -643,11 +643,7 @@ def resolve(object, args, query_ctx) inner_object = obj.object if defined?(@hash_key) - inner_object.fetch(@hash_key) { - inner_object[@hash_key_str] - } - elsif @dig_keys - inner_object.dig(*@dig_keys) + inner_object[@hash_key] || inner_object[@hash_key_str] elsif obj.respond_to?(resolver_method) method_to_call = resolver_method method_receiver = obj @@ -658,7 +654,15 @@ def resolve(object, args, query_ctx) obj.public_send(resolver_method) end elsif inner_object.is_a?(Hash) - if inner_object.key?(@method_sym) + if @dig_keys + inner_object.dig(*@dig_keys) + elsif defined?(@hash_key) + if inner_object.key?(@hash_key) + inner_object[@hash_key] + else + inner_object[@hash_key_str] + end + elsif inner_object.key?(@method_sym) inner_object[@method_sym] else inner_object[@method_str] @@ -751,7 +755,7 @@ def assert_satisfactory_implementation(receiver, method_name, ruby_kwargs) if unsatisfied_ruby_kwargs.any? || unsatisfied_method_params.any? raise FieldImplementationFailed.new, <<-ERR -Failed to call #{method_name} on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments: +Failed to call `#{method_name.inspect}` on #{receiver.inspect} because the Ruby method params were incompatible with the GraphQL arguments: #{ unsatisfied_ruby_kwargs .map { |key, value| "- `#{key}: #{value}` was given by GraphQL but not defined in the Ruby method. Add `#{key}:` to the method parameters." } diff --git a/spec/graphql/schema/field_spec.rb b/spec/graphql/schema/field_spec.rb index dd3bed2cee..461a0249e1 100644 --- a/spec/graphql/schema/field_spec.rb +++ b/spec/graphql/schema/field_spec.rb @@ -208,7 +208,7 @@ def f5(**ok_keyrest) err = assert_raises GraphQL::Schema::Field::FieldImplementationFailed do ArgumentErrorSchema.execute("{ f1(something: 12) }") end - assert_equal "Failed to call f1 on # because the Ruby method params were incompatible with the GraphQL arguments: + assert_equal "Failed to call `:f1` on # because the Ruby method params were incompatible with the GraphQL arguments: - `something: 12` was given by GraphQL but not defined in the Ruby method. Add `something:` to the method parameters. ", err.message @@ -218,7 +218,7 @@ def f5(**ok_keyrest) err = assert_raises GraphQL::Schema::Field::FieldImplementationFailed do ArgumentErrorSchema.execute("{ f2(something: 12) }") end - assert_equal "Failed to call field_2 on # because the Ruby method params were incompatible with the GraphQL arguments: + assert_equal "Failed to call `:field_2` on # because the Ruby method params were incompatible with the GraphQL arguments: - `something: 12` was given by GraphQL but not defined in the Ruby method. Add `something:` to the method parameters. ", err.message @@ -227,7 +227,7 @@ def f5(**ok_keyrest) err = assert_raises GraphQL::Schema::Field::FieldImplementationFailed do ArgumentErrorSchema.execute("{ f3(something: 1) }") end - assert_equal "Failed to call f3 on # because the Ruby method params were incompatible with the GraphQL arguments: + assert_equal "Failed to call `:f3` on # because the Ruby method params were incompatible with the GraphQL arguments: - `something: 1` was given by GraphQL but not defined in the Ruby method. Add `something:` to the method parameters. - `always_missing:` is required by Ruby, but not by GraphQL. Consider `always_missing: nil` instead, or making this argument required in GraphQL. @@ -236,7 +236,7 @@ def f5(**ok_keyrest) err = assert_raises GraphQL::Schema::Field::FieldImplementationFailed do ArgumentErrorSchema.execute("{ f4 }") end - assert_equal "Failed to call f4 on # because the Ruby method params were incompatible with the GraphQL arguments: + assert_equal "Failed to call `:f4` on # because the Ruby method params were incompatible with the GraphQL arguments: - `never_positional` is required by Ruby, but GraphQL doesn't pass positional arguments. If it's meant to be a GraphQL argument, use `never_positional:` instead. Otherwise, remove it. ", err.message @@ -611,9 +611,14 @@ def search_results "OtherCapital" => "explicit-hash-key-works", "some_random_key" => "hash-key-works-when-underlying-object-responds-to-field-name", "stringified_hash_key" => "hash-key-is-tried-as-string", - } end + + field :ostruct_results, ResultType, null: false + + def ostruct_results + OpenStruct.new(search_results) + end end query(QueryType) @@ -644,6 +649,37 @@ def search_results } assert_equal expected_result, search_results end + + it "works with non-hash instances" do + res = HashKeySchema.execute <<-GRAPHQL + { + ostructResults { + method + lowercase + Capital + Other + OtherCapital + stringifiedHashKey + } + } + GRAPHQL + + search_results = res["data"]["ostructResults"] + expected_result = { + "lowercase" => "lowercase-works", + "Capital" => "capital-camelize-false-works", + "Other" => "capital-camelize-true-works", + "OtherCapital" => "explicit-hash-key-works", + "method" => "hash-key-works-when-underlying-object-responds-to-field-name", + "stringifiedHashKey" => "hash-key-is-tried-as-string" + } + assert_equal expected_result, search_results + end + + it "populates `method_str`" do + hash_key_field = HashKeySchema.get_field("Result", "method") + assert_equal "some_random_key", hash_key_field.method_str + end end describe "when the owner is nil" do