From c15a70ffbb19d8875504f8fde90bb3ff4c5ddd7c Mon Sep 17 00:00:00 2001 From: Cody Ley-Han Date: Tue, 11 Sep 2018 14:50:17 -0700 Subject: [PATCH 1/2] Adds docs for how resolvers are bound --- docs/content/reference/resolvers.md | 203 ++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 docs/content/reference/resolvers.md diff --git a/docs/content/reference/resolvers.md b/docs/content/reference/resolvers.md new file mode 100644 index 00000000000..0ef1e2da365 --- /dev/null +++ b/docs/content/reference/resolvers.md @@ -0,0 +1,203 @@ +--- +linkTitle: Resolvers +title: Resolving grapqhQL requests +description: Different ways of binding graphQL requests to resolvers +menu: { main: { parent: 'reference' } } +--- + +There are multiple ways that a graphQL type can be bound to a Go struct that allows for many usecases. + + +## Bind directly to struct field names +This is the most common use case where the names of the fields on the Go struct match the names of the +fields in the graphQL type. If a Go struct field is unexported, it will not be bound to the graphQL type. + +```go +type Car struct { + Make string + Model string + Color string + OdometerReading int +} +``` + +And then in your graphQL schema: +```graphql +type Car { + make: String! + model: String! + color: String! + odometerReading: Int! +} +``` + +And in the gqlgen config file: +```yaml +models: + Car: + model: github.com/my/app/models.Car +``` + +In this case, each filed in the graphQL type will be bound to the respective field on the go struct +ignoring the case of the fields + + +## Bind to a method name + +This is also very common use case that comes up where we want to bind a graphQL field to a Go struct method + +```go +type Person { + Name string +} + +type Car struct { + Make string + Model string + Color string + OwnerID *string + OdometerReading int +} + +func (c *Car) Owner() (*Person) { + // get the car owner + //.... + return owner +} +``` + +And then in your graphQL schema: +```graphql +type Car { + make: String! + model: String! + color: String! + odometerReading: Int! + owner: Person +} +``` + +And in the gqlgen config file: +```yaml +models: + Car: + model: github.com/my/app/models.Car + Person: + model: github.com/my/app/models.Person +``` + +Here, we see that there is a method on car with the name ```Owner```, thus the ```Owner``` function will be called if +a graphQL request includes that field to be resolved + +## Bind when the field names do not match + +There are two ways you can bind to fields when the the Go struct and the graphQL type do not match. + + +The first way is you can bind resolvers to a struct based off of struct tags like the following: + +```go +type Car struct { + Make string + ShortState string + LongState string `gqlgen:"state"` + Model string + Color string + OdometerReading int +} +``` + +And then in your graphQL schema: +```graphql +type Car { + make: String! + model: String! + state: String! + color: String! + odometerReading: Int! +} +``` + +And in the gqlgen config file add the line: +```yaml +struct_tag: gqlgen + +models: + Car: + model: github.com/my/app/models.Car +``` + +Here even though the graphQL type and Go struct have different field names, there is a Go struct tag field on ```longState``` +That matches and thus ```state``` will be bound to ```LongState``` + + +The second way you can bind fields is by adding a line into the config file such as: +```go +type Car struct { + Make string + ShortState string + LongState string + Model string + Color string + OdometerReading int +} +``` + +And then in your graphQL schema: +```graphql +type Car { + make: String! + model: String! + state: String! + color: String! + odometerReading: Int! +} +``` + +And in the gqlgen config file add the line: +```yaml +models: + Car: + model: github.com/my/app/models.Car + fields: + state: + fieldName: LongState +``` + +## Binding to Anonymous or Embedded Structs +All of the rules from above apply to a struct that has an embedded struct. + +```go +type Truck { + car + + is4x4 bool +} + +type Car struct { + Make string + ShortState string + LongState string + Model string + Color string + OdometerReading int +} +``` + +And then in your graphQL schema: +```graphql +type Truck { + make: String! + model: String! + state: String! + color: String! + odometerReading: Int! + is4x4: Bool! +} +``` + +Here all the fields from the Go struct Car will still be bound to the respective fields in the graphQL schema that match + +## Binding Priority +If a ```struct_tags``` config exists, then struct tag binding has the highest priority over all other types of binding. +In all other cases, the first Go struct field found that matches the graphQL type field will be the field that is bound. \ No newline at end of file From baa99fc58711afed393a3952296a4a9bc754494c Mon Sep 17 00:00:00 2001 From: Cody Ley-Han Date: Tue, 11 Sep 2018 20:55:12 -0700 Subject: [PATCH 2/2] cleaned up resolver doc --- docs/content/reference/resolvers.md | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/content/reference/resolvers.md b/docs/content/reference/resolvers.md index 0ef1e2da365..0887f234805 100644 --- a/docs/content/reference/resolvers.md +++ b/docs/content/reference/resolvers.md @@ -128,14 +128,14 @@ models: ``` Here even though the graphQL type and Go struct have different field names, there is a Go struct tag field on ```longState``` -That matches and thus ```state``` will be bound to ```LongState``` +that matches and thus ```state``` will be bound to ```LongState```. The second way you can bind fields is by adding a line into the config file such as: ```go type Car struct { Make string - ShortState string + ShortState string LongState string Model string Color string @@ -166,12 +166,12 @@ models: ## Binding to Anonymous or Embedded Structs All of the rules from above apply to a struct that has an embedded struct. - +Here is an example ```go type Truck { - car + Car - is4x4 bool + Is4x4 bool } type Car struct { @@ -198,6 +198,27 @@ type Truck { Here all the fields from the Go struct Car will still be bound to the respective fields in the graphQL schema that match +Embedded structs are a good way to create thin wrappers around data access types an example would be: + +```go +type Cat struct { + db.Cat + //... +} + +func (c *Cat) ID() string { + // return a custom id based on the db shard and the cat's id + return fmt.Sprintf("%d:%d", c.Shard, c.Id) +} +``` + +Which would correlate with a gqlgen config file of: +```yaml +models: + Cat: + model: github.com/my/app/models.Cat +``` + ## Binding Priority If a ```struct_tags``` config exists, then struct tag binding has the highest priority over all other types of binding. In all other cases, the first Go struct field found that matches the graphQL type field will be the field that is bound. \ No newline at end of file