Skip to content

Footgun: Using method: kwarg w/ defined resolver method #5475

@cocoahero

Description

@cocoahero

When a field definition uses the method: keyword argument, it is ignored if the owning object definition has a method named the same as the field.

class MyRootObject
  def foo
    "hello"
  end
end

class QueryRoot < GraphQL::Schema::Object
  field :my_field, String, null: false, method: :foo

  def my_field
    "footgun"
  end
end

class Schema < GraphQL::Schema
  query(QueryRoot)
end

result = Schema.execute("{ myField }", root_value: MyRootObject.new)

puts result.to_h.dig("data", "myField") # => footgun

Looking at the default resolver resolution logic, this is due to the fact that the object definition is checked before the method: kwarg. The docs state:

By default, fields return values by:

- Trying to call a method on the underlying object; OR
- If the underlying object is a Hash, lookup a key in that hash.
- An optional :fallback_value can be supplied that will be used if the above fail.

As seen above, this is not entirely true.

Internally we have developed a rubocop rule to detect this (happy to share), but its unable to highlight occurrences where the method is defined in an ancestor.

"Fixing" this behavior is likely considered a breaking change, so not sure if its something to address in 3.x?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions