Interfaces

At this point you should know the basics, so it’s a perfect time for some hands-on training. The following paragraph will give you hints on what needs to be done. Try implementing it yourself. At the end I will add an example solution in case you are stuck. Later in this chapter we will learn about interfaces and how they relate to the work you’ve done.

Your DIY kit

Before you go further, try to implement the changes yourself. I think, at this point, you have the necessary knowledge to add the User and Vote models. I’ll show what to do later in this chapter, but try to implement it yourself first.

What you have to do:

  1. Add User class with fields: id, name, email, password and createdAt
  2. Add Vote class with fields: id, createdAt, userId, linkId(you don’t have to to define any relations for now)
  3. Create database tables for both,
  4. Add object types for both,
  5. Add fetchers for both,
  6. Implement HasId type class,
  7. Add fields in main ObjectType which allows for fetching a list of entities like users and votes

Please, go ahead with your implementation … I will wait here

User entity

Let’s start from the user entity:

Database setup.

Sample entities:

Add a function responsible for user retrieval:

Dont’ forget about import com.howtographql.scala.sangria.models.User

GraphQL part:

Add fetcher to resolvers.

Add fields to main ObjectType:

We’re ready… you can now execute a query like this:

query {
    users(ids: [1, 2]){
      id
      name
      email
      createdAt
    }
}

Vote entity

If you want, you can make similar changes for Vote entity. And then follow the instructions and check everything works.

Database setup.

The next step is creating relations.

Add votes retrieval function.

GraphQL part:

Add fetcher to resolvers.

Add fields to main ObjectType:

The following query should now execute successfully:

query {
  votes(ids: [1, 2]){
    id
    createdAt
  }
}  

Finding common parts

As you can see some code is very similar. Like HasId for all three types:

implicit val linkHasId = HasId[Link, Int](_.id)
implicit val userHasId = HasId[User, Int](_.id)
implicit val voteHasId = HasId[Vote, Int](_.id)

What if you want to add more entities? You will have to duplicate this code.

The solution for this is an interface. We can provide an interface that will be extended by any of the entities. This way, for example, you will need just one HasId

And then extend this trait by all of those classes like:

case class Link(...) extends Identifiable
case class User(...) extends Identifiable
case class Vote(...) extends Identifiable

Now we can replace all above HasId type classes with the single one. But now we will move it into companion object so it will be accessible whenever we import the trait.

The next step is providing GraphQL’s interface type for that trait.

Make similar changes to UserType and VoteType.

Now if you look into the schema definition in graphiql console you will see that all three models implement the Identifiable interface.

So far so good. We made many changes in this chapter, so if you like you can compare current state o files with the following snippets.

GraphQLSchema.scala
models/package.scala
DAO.scala
DBSchema.scala


Ok, that’s all for this chapter. In the next one you will learn about relations.

Unlock the next chapter
Do interfaces are part of GraphQL specification?
No
No, but it's recommended to use it
No it's forced to implement by Scala and its traits
Yes