Below is a piece of code that used to work fine until v0.16.0 and stopped since v0.17.0. Tested with Ruby 3.2.2.
We use similar code to make the objects returned from GraphQL queries work with Rails' route helpers and for that we need to add #to_param to our type definitions.
In a Rails project #to_param is defined on the base Object class and by default returns self.to_s (source).
The objects returned from queries inherit from GraphQL::Client::Schema::ObjectClass which inherits from Object. So when we call #to_param on an object returned from the query it gets dispatched as Object#to_param and doesn't end up in GraphQL::Client::Schema::ObjectClass#method_missing. Thus instead of IDs of records we get strings like "#<#<Module:0x00000001062529f0>::User:0x0000000106316d50>".
It looks that in v0.16.0 all the typed fields were defined as methods on the query objects and since v0.17.0 the library moved to method_missing dispatch. That's why it's no longer possible to use fields that correspond to instance methods of Object, like #to_param.
#!/usr/bin/env ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "graphql", "1.13.2"
# gem "graphql-client", "0.16.0" # <--- this works as expected
gem "graphql-client", "0.21.0"
gem "activesupport", "7.1.3.2"
end
require "graphql"
require "graphql/client"
require "active_support/core_ext/object/to_query"
module MyData
User = Data.define(:id)
end
module MyTypes
class User < GraphQL::Schema::Object
field :id, ID, null: false
field :to_param, String, null: false, resolver_method: :resolve_to_param
def resolve_to_param
"user-#{object.id}"
end
end
class Query < GraphQL::Schema::Object
field :current_user, User, null: false
def current_user
MyData::User.new(id: 1)
end
end
end
class MySchema < GraphQL::Schema
query(MyTypes::Query)
end
client = GraphQL::Client.new(schema: MySchema, execute: MySchema)
TEST_QUERY = client.parse(<<~GRAPHQL)
query {
currentUser {
toParam
}
}
GRAPHQL
current_user = client.query(TEST_QUERY).data.current_user
puts "current_user is #{current_user.inspect}"
puts "Expecting #to_param to return \"user-1\", got: #{current_user.to_param.inspect}"
Below is a piece of code that used to work fine until v0.16.0 and stopped since v0.17.0. Tested with Ruby 3.2.2.
We use similar code to make the objects returned from GraphQL queries work with Rails' route helpers and for that we need to add
#to_param
to our type definitions.In a Rails project
#to_param
is defined on the baseObject
class and by default returnsself.to_s
(source).The objects returned from queries inherit from
GraphQL::Client::Schema::ObjectClass
which inherits fromObject
. So when we call#to_param
on an object returned from the query it gets dispatched asObject#to_param
and doesn't end up inGraphQL::Client::Schema::ObjectClass#method_missing
. Thus instead of IDs of records we get strings like"#<#<Module:0x00000001062529f0>::User:0x0000000106316d50>"
.It looks that in v0.16.0 all the typed fields were defined as methods on the query objects and since v0.17.0 the library moved to
method_missing
dispatch. That's why it's no longer possible to use fields that correspond to instance methods ofObject
, like#to_param
.