-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Defer calling field do ... end blocks until needed #5054
Conversation
I was able to confirm this has the desired effect in Rails by making a new app and adding fields like this to field :things, fallback_value: [{name: "Abacus"}] do
type [Types::Thing]
end
field :other_things, fallback_value: [{name: "Abacus"}] do
type [Types::OtherThing]
end I also added Then, from GraphiQL, I made two different queries to the backend: # first
query {
things { __typename }
}
# second
query {
otherThings { __typename }
} In the Rails server log, I saw the desired load messages. The first query loaded
The second query loaded
🎉 |
We have a few places where we override def field(*args, **kwargs, some_custom_option: true, &block)
super(*T.unsafe(args), **options).tap do |field_defn|
field_defn.extension(SomeExtension)
end
end This PR no longer yields the field instance of course. Two questions:
|
Hey, sorry it wasn't working the same right out of the box. I'm sure there's something that will work for this... What goes wrong in the example above? (I see One thing that comes to mind is passing a new block to field(*args, **kwargs, &block)
super(*args, **kwargs) do |field_inst|
block.call(field_inst)
field_inst.extension(SomeExtension)
end
end IIUC that new block would be passed to I'd love to keep |
😓 my example was a bad one. We have a few patterns and it's actually the other one that has the issue: def field(*args, **kwargs, some_custom_option: true)
field_defn = super(*T.unsafe(args), **options)
field_defn.extension(SomeExtension) if some_custom_option
field_defn
end
So I think it all makes sense and should work to support the same use cases. |
Ok, thanks for those details. I'm surprised graphql-ruby/lib/graphql/schema/member/has_fields.rb Lines 11 to 15 in 5dcdb59
I'd be happy to debug further if you don't mind sharing the full error message and backtrace. Maybe it would have another clue as to where that |
rmosolgo#5054 introduced a regression where an extension registered eagerly can no longer register another extension in its `apply` method. I fix the bug here by restoring the previous `@call_after_define` logic.
rmosolgo#5054 introduced a regression where an extension registered eagerly can no longer register another extension in its `apply` method. I fix the bug here by restoring the previous `@call_after_define` logic.
This way, in theory, loading
my_object.rb
doesn't necessary load the field return types of these fields. (Rails won't try to load files until the constants are actually referenced, and in this case, it can be deferred until execution.)cc @gmcgibbon -- would this approach work in your type-checking setup? Like this:
I think that would give you plain Ruby constants in the source.
The downside is the need to call
ensure_loaded
everywhere. It's too bad and reminds me of how GraphQL-Ruby used to be full ofensure_defined
, yuck 😩 . But, I think it's the right thing, and thanks to caching by the schema / Warden / Subset, calls to that method were surprisingly manageable.ensure_loaded
could even be helpful. For example, lots offield.rb
checks to see if@resolver
has a return type, arguments, etc, and uses those if they're given. But those checks could be done eagerly inensure_loaded
, and maybe even afreeze
call to avoid surprises if the field is modified afterensure_loaded
has run.Part of #5014
TODO:
Field#type(t)
to updatedconnection?
as neededDocument support for thisI'm going to wait and document the whole thing when it's ready