Skip to content

Instantly share code, notes, and snippets.

@marioosh
Created June 26, 2018 10:08
Show Gist options
  • Save marioosh/6f75f24bb5e5fd6fc3d46472147c4551 to your computer and use it in GitHub Desktop.
Save marioosh/6f75f24bb5e5fd6fc3d46472147c4551 to your computer and use it in GitHub Desktop.
HowToGraphql - Sangria tutorial - Interfaces
package com.howtographql.scala.sangria\
import DBSchema._
import com.howtographql.scala.sangria.models.{Link, User, Vote}
import slick.jdbc.H2Profile.api._
import scala.concurrent.Future
class DAO(db: Database) {
def allLinks = db.run(Links.result)
def getLinks(ids: Seq[Int]): Future[Seq[Link]] = db.run(
Links.filter(_.id inSet ids).result
)
def getUsers(ids: Seq[Int]): Future[Seq[User]] = db.run(
Users.filter(_.id inSet ids).result
)
def getVotes(ids: Seq[Int]): Future[Seq[Vote]] = {
db.run(
Votes.filter(_.id inSet ids).result
)
}
}
package com.howtographql.scala.sangria
import java.sql.Timestamp
import akka.http.scaladsl.model.DateTime
import com.howtographql.scala.sangria.models._
import slick.jdbc.H2Profile.api._
import scala.concurrent.duration._
import scala.concurrent.Await
import scala.language.postfixOps
object DBSchema {
implicit val dateTimeColumnType = MappedColumnType.base[DateTime, Timestamp](
dt => new Timestamp(dt.clicks),
ts => DateTime(ts.getTime)
)
class LinksTable(tag: Tag) extends Table[Link](tag, "LINKS"){
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def url = column[String]("URL")
def description = column[String]("DESCRIPTION")
def createdAt = column[DateTime]("CREATED_AT")
def * = (id, url, description, createdAt).mapTo[Link]
}
val Links = TableQuery[LinksTable]
class UsersTable(tag: Tag) extends Table[User](tag, "USERS"){
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def name = column[String]("NAME")
def email = column[String]("EMAIL")
def password = column[String]("PASSWORD")
def createdAt = column[DateTime]("CREATED_AT")
def * = (id, name, email, password, createdAt).mapTo[User]
}
val Users = TableQuery[UsersTable]
class VotesTable(tag: Tag) extends Table[Vote](tag, "VOTES"){
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def userId = column[Int]("USER_ID")
def linkId = column[Int]("LINK_ID")
def createdAt = column[DateTime]("CREATED_AT")
def * = (id, userId, linkId, createdAt).mapTo[Vote]
}
val Votes = TableQuery[VotesTable]
/**
* Load schema and populate sample data withing this Sequence od DBActions
*/
val databaseSetup = DBIO.seq(
Links.schema.create,
Users.schema.create,
Votes.schema.create,
Links forceInsertAll Seq(
Link(1, "http://howtographql.com", "Awesome community driven GraphQL tutorial", DateTime(2017,9,12)),
Link(2, "http://graphql.org", "Official GraphQL web page",DateTime(2017,10,1)),
Link(3, "https://facebook.github.io/graphql/", "GraphQL specification",DateTime(2017,10,2))
),
Users forceInsertAll Seq(
User(1, "mario", "[email protected]", "s3cr3t"),
User(2, "Fred", "[email protected]", "wilmalove")
),
Votes forceInsertAll Seq(
Vote(id = 1, userId = 1, linkId = 1),
Vote(id = 2, userId = 1, linkId = 2),
Vote(id = 3, userId = 1, linkId = 3),
Vote(id = 4, userId = 2, linkId = 2),
)
)
def createDatabase: DAO = {
val db = Database.forConfig("h2mem")
Await.result(db.run(databaseSetup), 10 seconds)
new DAO(db)
}
}
package com.howtographql.scala.sangria
import akka.http.scaladsl.model.DateTime
import sangria.schema.{ListType, ObjectType}
import models._
import sangria.ast.StringValue
import sangria.execution.deferred.{DeferredResolver, Fetcher, HasId}
import sangria.schema._
import sangria.macros.derive._
object GraphQLSchema {
implicit val GraphQLDateTime = ScalarType[DateTime](//1
"DateTime",//2
coerceOutput = (dt, _) => dt.toString, //3
coerceInput = { //4
case StringValue(dt, _, _ ) => DateTime.fromIsoDateTimeString(dt).toRight(DateTimeCoerceViolation)
case _ => Left(DateTimeCoerceViolation)
},
coerceUserInput = { //5
case s: String => DateTime.fromIsoDateTimeString(s).toRight(DateTimeCoerceViolation)
case _ => Left(DateTimeCoerceViolation)
}
)
val IdentifiableType = InterfaceType(
"Identifiable",
fields[Unit, Identifiable](
Field("id", IntType, resolve = _.value.id)
)
)
val LinkType = deriveObjectType[Unit, Link](
Interfaces(IdentifiableType),
ReplaceField("createdAt", Field("createdAt", GraphQLDateTime, resolve = _.value.createdAt))
)
val UserType = deriveObjectType[Unit, User](
Interfaces(IdentifiableType)
)
val VoteType = deriveObjectType[Unit, Vote](
Interfaces(IdentifiableType)
)
val linksFetcher = Fetcher(
(ctx: MyContext, ids: Seq[Int]) => ctx.dao.getLinks(ids)
)
val usersFetcher = Fetcher(
(ctx: MyContext, ids: Seq[Int]) => ctx.dao.getUsers(ids)
)
val votesFetcher = Fetcher(
(ctx: MyContext, ids: Seq[Int]) => ctx.dao.getVotes(ids)
)
val Resolver = DeferredResolver.fetchers(linksFetcher, usersFetcher, votesFetcher)
val Id = Argument("id", IntType)
val Ids = Argument("ids", ListInputType(IntType))
val QueryType = ObjectType(
"Query",
fields[MyContext, Unit](
Field("allLinks", ListType(LinkType), resolve = c => c.ctx.dao.allLinks),
Field("link",
OptionType(LinkType),
arguments = Id :: Nil,
resolve = c => linksFetcher.deferOpt(c.arg(Id))
),
Field("links",
ListType(LinkType),
arguments = Ids :: Nil,
resolve = c => linksFetcher.deferSeq(c.arg(Ids))
),
Field("users",
ListType(UserType),
arguments = List(Ids),
resolve = c => usersFetcher.deferSeq(c.arg(Ids))
),
Field("votes",
ListType(VoteType),
arguments = List(Ids),
resolve = c => votesFetcher.deferSeq(c.arg(Ids))
)
)
)
val SchemaDefinition = Schema(QueryType)
}
package com.howtographql.scala.sangria
import akka.http.scaladsl.model.DateTime
import sangria.execution.deferred.HasId
import sangria.validation.Violation
package object models {
trait Identifiable {
val id: Int
}
object Identifiable {
implicit def hasId[T <: Identifiable]: HasId[T, Int] = HasId(_.id)
}
case class Link(id: Int, url: String, description: String, createdAt: DateTime) extends Identifiable
case object DateTimeCoerceViolation extends Violation {
override def errorMessage: String = "Error during parsing DateTime"
}
case class User(id: Int, name: String, email: String, password: String, createdAt: DateTime = DateTime.now) extends Identifiable
case class Vote(id: Int, userId: Int, linkId: Int, createdAt: DateTime = DateTime.now) extends Identifiable
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment