I am trying to use Graphcool to design a backend for our product. We already have the domain model for the product.
The problem I am facing is with non scalar attributes where I am forced to use @relation (that too two way relation).
Help me design the following case
# projectId: cj4dsyc7ur8cc0142s3hesy1r
# version: 2
type File implements Node {
contentType: String!
createdAt: DateTime!
id: ID! @isUnique
name: String!
secret: String! @isUnique
size: Int!
updatedAt: DateTime!
url: String! @isUnique
}
type User implements Node {
createdAt: DateTime!
email: String @isUnique
id: ID! @isUnique
password: String
updatedAt: DateTime!
}
type Record implements Node {
createdAt: DateTime!
id: ID! @isUnique
name: String!
description: String!
createdBy: User!
modifiedBy: User!
}
For this I get the error
Errors
createdBy: The relation field `createdBy` must specify a `@relation` directive: `@relation(name: "MyRelation")`
modifiedBy: The relation field `modifiedBy` must specify a `@relation` directive: `@relation(name: "MyRelation")`
Then when I try to add the relation I am forced to do the following
# projectId: cj4dsyc7ur8cc0142s3hesy1r
# version: 2
type File implements Node {
contentType: String!
createdAt: DateTime!
id: ID! @isUnique
name: String!
secret: String! @isUnique
size: Int!
updatedAt: DateTime!
url: String! @isUnique
}
type User implements Node {
createdAt: DateTime!
email: String @isUnique
id: ID! @isUnique
password: String
updatedAt: DateTime!
}
type Record implements Node {
createdAt: DateTime!
id: ID! @isUnique
name: String!
description: String!
createdBy: User! @relation(name: "createdBy")
modifiedBy: User! @relation(name: "modifiedBy")
}
Which leads to following error
Errors
createdBy: A relation directive with a name must appear exactly 2 times.
modifiedBy: A relation directive with a name must appear exactly 2 times.
I understand for every non scalar outgoing graphcool expects to put up a 2 way relationship. But consider a use case for modifiedBy and createdBy (User), I can not put a relationship on User object for every entity I add.
What is a better way of doing this on GraphCool?
Also, why is this restriction put up by GraphCool, GraphQL doesn't dictate this restriction?
Cheers Rohit
thanks for using Graphcool!
First things first. As you point out Graphcool enforces two-way relations when you want to connect types. In some cases you know up front that you only want to query the data in one direction, so it might seem unintuitive that you have to create a two-way relation.
The reason for this is that the Graphcool Permission System allows you to succinctly specify permission rules based on the structure of your data. In your case you might want to specify that only the creator of a post is allowed to delete a record.
In practice it turns out that very often you end up needing the reverse relation when you implement your permission rules. Enforcing two-way relations makes the entire programming model simpler to understand and sets you up to easily implement permission rules.
For your schema a solution would be to extend the User type as follows:
type User implements Node {
createdAt: DateTime!
email: String @isUnique
id: ID! @isUnique
password: String
updatedAt: DateTime!
createdRecords: [Record!]! @relation(name: "CreatedBy")
modifiedRecords: [Record!]! @relation(name: "UpdatedBy")
}
(please note that relation names must begin with a uppercase letter)
Hope that helps :-)