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

Field type no longer supports Proc for lazy type resolution? #2874

Closed
jondruse opened this issue Apr 12, 2020 · 5 comments
Closed

Field type no longer supports Proc for lazy type resolution? #2874

jondruse opened this issue Apr 12, 2020 · 5 comments

Comments

@jondruse
Copy link

Describe the bug

until tag v1.10.0.pre3 the docs for fields included this:

  # @example Lazy type resolution
  #   # If the field's type isn't defined yet, you can pass a proc
  #   field :city, -> { TypeForModelName.find("City") }
  #

I've looked through the changelog and don't see an explicit mention that this has been removed so I'm just wondering if it's intentionally removed or if it's a bug.

If it's intentionally removed, is there a different way of achieving this? Thanks!

Versions

graphql version: 1.10.6
ruby version: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin18]

require 'rubygems'
require 'graphql'

class QueryType < GraphQL::Schema::Object

  # --- this one works
  #field :time_zones, [String], camelize: false, description: 'Timezones', null: false

  # --- this one throws error
  field :time_zones, -> { [String] }, camelize: false, description: 'Timezones', null: false
  
  def time_zones
    [
      "Pacific",
      "Mountain",
      "Central",
      "Eastern"
    ]
  end


end

class MyAppSchema < GraphQL::Schema
  query QueryType
end


variables = {}
query = " { time_zones }"
operation_name = nil
context = { }
result = MyAppSchema.execute(query, variables: variables, context: context, operation_name: operation_name)

puts result.inspect

Steps to reproduce

Run the code above
Actual behavior

Press ENTER or type command to continue
Traceback (most recent call last):
        9: from run_test.rb:7:in `<main>'
        8: from run_test.rb:12:in `<class:QueryType>'
        7: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/member/has_fields.rb:12:in `field'
        6: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/field.rb:109:in `from_options'
        5: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/field.rb:109:in `new'
        4: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/member/accepts_definition.rb:142:in `initialize'
        3: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/field.rb:275:in `initialize'
        2: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/field.rb:137:in `scoped?'
        1: from /Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/field.rb:120:in `connection?'
/Users/jondruse/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/graphql-1.10.6/lib/graphql/schema/member/build_type.rb:118:in `to_type_name': Unhandled to_type_name input: #<Proc:0x00007fcfbb1bcc80@run_test.rb:12 (lambda)> (Proc) (RuntimeError)
@jondruse
Copy link
Author

Update:

If I add a case for Proc in that file it works but I'm not sure of the ramifications:

        def to_type_name(something)
          case something
          when GraphQL::BaseType, GraphQL::Schema::LateBoundType
            something.unwrap.name
          when Array
            to_type_name(something.first)
          when Module
            if something.respond_to?(:graphql_name)
              something.graphql_name
            else
              to_type_name(something.name)
            end
          when String
            something.gsub(/\]\[\!/, "").split("::").last
          when GraphQL::Schema::NonNull, GraphQL::Schema::List
            to_type_name(something.unwrap)
          when Proc
            to_type_name(something.call)
          else
            raise "Unhandled to_type_name input: #{something} (#{something.class})"
          end
        end 

@rmosolgo
Copy link
Owner

That's right, proc isn't supported in class-based schemas.

Previously, procs were called lazily to work around circular loading. Since switching to classes, that should work a bit better, at least with Rails autoloader.

If eagerly calling the proc works (as shown in your workaround above), why not just remove the proc?

@jondruse
Copy link
Author

Yeah that all makes sense.

So is there any way of including a field of a type that hasn't been defined yet? Most of our schema is created dynamically using ActiveRecord introspection. Any help would be much appreciated! Thanks again for all your work on this, it's a life saver!

@rmosolgo
Copy link
Owner

Are your types assigned to constants? If so, you can use the string constant name for the type, and it will be constantized as late as possible. For example:

field(:post, "Types::Post", null: true)

will eventually find

# app/graphql/types/post.rb
Types::Post = build_type(::Post)

@jondruse
Copy link
Author

That's easier! Thanks so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants