How do I use arguments that are passed to a Graphql ruby field to transform the result?

3.4k views Asked by At

I am looking to do something similar to what is done in the graphql tutorial: https://graphql.org/learn/queries/#arguments

I want to pass feet/meters to a scaler field to transform the result that is returned.

{
  human(id: "1000") {
    name
    height(unit: FOOT)
  }
}

I can't figure out how to do that in ruby using graphql-ruby.

I currently have a type that looks like:

class Types::Human < Types::BaseObject

  field :id, ID, null: false
  field :height, Int, null: true do
     argument :unit, String, required: false
  end

  def height(unit: nil)

  #what do I do here to access the current value of height so I can use unit to transform the result?

  end
end

I have found that the resolver method (height) is called for every instance that is returned... but I don't know how to access the current value.

Thanks

2

There are 2 answers

1
wintheday On BEST ANSWER

When you define a resolving method inside of your type definition Graphql Ruby assumes that that method will resolve the value. So at the time your current method def height(unit: nil) is ran it doesn't know what the current height value is because it is expecting you to define it.

Instead what you would want to do is move the resolving method to the model / object returned for the Human type. For example, in rails you might do this:

# app/graphql/types/human_type.rb
class Types::Human < Types::BaseObject

  field :id, ID, null: false
  field :height, Int, null: true do
    argument :unit, String, required: false
  end

end
# app/models/human.rb
class Human < ApplicationRecord

  def height(unit: nil)
    # access to height with self[:height]. 
    # You must use self[:height] so as to access the height property
    # and not call the method you defined.  Note: This overrides the
    # getter for height.
  end
end

GraphQL Ruby will then call .height on the instance of human that is passed to it.

0
RMK On

I found that the object being queried is available in resolve method itself

def height(unit: nil)
  # do some conversion here and return the value you want.
  self.object.height
end