-
Notifications
You must be signed in to change notification settings - Fork 493
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
Use Struct Field Resolver instead of Method #282
Conversation
I have implemented your PR review suggestions. Please take a look Your suggestion to use hybrid approach is implemented. |
@pavelnikolov are you OK with merging this? |
I think this is a really useful feature and can't wait to use it. What't the plan for merging? |
I'll review the PR shortly. I'm sorry for the delay on this. |
Can't wait to throw away half of my resolver code after this is merged! :) |
Any update for this PR be merged? |
@pavelnikolov I have addressed your review comment. Please merge this PR, thank you! |
Thank the gods, and @Salman-Ahmad I was just looking for this functionality. ❤️ It looks great on my end. I appreciate that if a field does not exist, but a method does then the method will be used, especially for backward compatibility. I would suggest that {
get(limit: 3) {
name
color
}
} package gql
import (
"context"
"github.com/gorilla/mux"
graphql "github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/relay"
)
type Record struct {
Name string
}
func (r *Record) Color(ctx context.Context) string {
return "blue"
}
type query struct{}
type Options struct {
Limit int32
}
func (q *query) Get(ctx context.Context, options Options) (*Record, error) {
return &Record{
Name: "salman",
}, nil
}
func AddEndpoint(r *mux.Router) {
s := `
schema {
query: Query
}
interface Record {
color: String!
name: String!
}
type Query {
get(limit: Int! = 5): Record
}
`
schema := graphql.MustParseSchema(s, &query{}, graphql.UseFieldResolvers())
r.Handle("/query", &relay.Handler{Schema: schema})
} |
@itsleeowen , your suggestion would introduce a breaking change which I would really like to avoid. Instead, this feature will be opt-in. |
@pavelnikolov Cool, I'm curious what that breaking change is? On the surface it looks backward compatible, if you're using struct methods, those continue to work. |
@itsleeowen oh, my bad 🤦♂️ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this is ready to go in after a few minor changes...
Thank you for your contribution! |
🎉 just at the right time! Thank you so much! |
Question about the social example: What is the use of the FriendsResolver method? When is it called? I put some debug logging in it, but that never shows, also the pagination doesn't seem to be doing anything currently? |
@marcelvanwaaijen I haven't looked into it in details but my wild guess is that it was an existing example and when this feature was implemented we ended up adding |
This fixes #28. Essentially, it reduces lot of boilerplate code by making use of struct field as resolvers instead of creating methods for each struct field.
Now, methods are required only when
first: Int, last: Int
etc.union
typeBy using struct fields as resolvers, one could also benefit from DRY codebase by not having a pair of a struct which look the same (one for GraphQL and one for DB)
Does this break existing API?
No. This change is completely transparent and you can continue using your existing codebase.
Can I still continue using methods as resolvers?
Yes, by default, it uses method resolvers. Even when
UseFieldResolvers()
is turned on, the method is given higher priority than the field. When there is no method, the field will be used if there is any.How can I use struct fields as resolvers?
When invoking
graphql.ParseSchema()
orgraphql.MustParseSchema()
to parse the schema, you pass ingraphql.UseFieldResolvers()
as an argument. For an example, take a look at./example/social/server/server.go
Additional Notes
./example/social/social.go
&./example/social/server/server.go