Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some hash lookup behaviors #4072

Merged
merged 11 commits into from May 24, 2022
20 changes: 12 additions & 8 deletions lib/graphql/schema/field.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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." }
Expand Down
46 changes: 41 additions & 5 deletions spec/graphql/schema/field_spec.rb
Expand Up @@ -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 #<ArgumentErrorSchema::Query> because the Ruby method params were incompatible with the GraphQL arguments:
assert_equal "Failed to call `:f1` on #<ArgumentErrorSchema::Query> 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
Expand All @@ -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 #<ArgumentErrorSchema::Query> because the Ruby method params were incompatible with the GraphQL arguments:
assert_equal "Failed to call `:field_2` on #<ArgumentErrorSchema::Query> 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
Expand All @@ -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 #<ArgumentErrorSchema::Query> because the Ruby method params were incompatible with the GraphQL arguments:
assert_equal "Failed to call `:f3` on #<ArgumentErrorSchema::Query> 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.
Expand All @@ -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 #<ArgumentErrorSchema::Query> because the Ruby method params were incompatible with the GraphQL arguments:
assert_equal "Failed to call `:f4` on #<ArgumentErrorSchema::Query> 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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down