Reputation: 1009
I am working on a basic job-board app for practice and when trying to compile my Scala code I am getting the following error.
[warn] insecure HTTP request is deprecated 'http://repo.typesafe.com/typesafe/releases/'; switch to HTTPS or opt-in as ("Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/").withAllowInsecureProtocol(true)
[info] Compiling 8 Scala sources to /Users/ryanmcavoy/Code/job-board/target/scala-2.11/classes ...
[error] /Users/ryanmcavoy/Code/job-board/src/main/scala/io/github/jobboard/database/JobQueries.scala:26:5: Could not find or construct Param[shapeless.::[String,shapeless.::[io.github.jobboard.model.JobPostDetails,shapeless.HNil]]].
[error] Ensure that this type is an atomic type with an Meta instance in scope, or is an HList whose members
[error] have Meta instances in scope. You can usually diagnose this problem by trying to summon the Meta
[error] instance for each element in the REPL. See the FAQ in the Book of Doobie for more hints.
[error] sql"""
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
It seems to be complaining about the below method
def insert(jobPost: JobPost): doobie.Update0 = {
sql"""
|INSERT INTO jobs (
| id,
| details
|)
|VALUES (
| ${jobPost.id},
| ${jobPost.details}
|)
""".stripMargin
.update
}
I have had a look at the docs here: https://tpolecat.github.io/doobie-0.2.3/15-FAQ.html but haven't been able to figure it out.
For additional info I'll include the below:
case class JobPost(id: String, details: JobPostDetails)
case class JobPostDetails(title: String, description: String, salary: Double, employmentType: String, employer: String)
def createTable: doobie.Update0 = {
sql"""
|CREATE TABLE IF NOT EXISTS jobs (
| id UUID PRIMARY KEY,
| details JSON NOT NULL
|)
""".stripMargin
.update
}
Upvotes: 1
Views: 238
Reputation: 22595
In your case, Doobie doesn't know how to serialize JobPostDetails
into JSON column on your Postgres database.
By default, Doobie doesn't know how to change case class into JSON. Arguably the most popular library for serializing JSON in scala is circe. You'd have to add additional dependencies in your build.sbt
for circe and circe-Postgres-doobie integration.
"org.tpolecat" %% "doobie-postgres" % "0.8.8"
"org.tpolecat" %% "doobie-postgres-circe" % "0.8.8"
"io.circe" %% "circe-core" % "0.13.0"
Then you should create instances of Encoder
, Decoder
, Put
and Get
typeclasses in companion object of JobPostDetails
:
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import doobie.postgres.circe.json.implicits._
import doobie._
import io.circe.syntax._
case class JobPostDetails(title: String, description: String, salary: Double, employmentType: String, employer: String)
object JobPostDetails {
//for decoding json into JobPostDetails
implicit val circeDecoder: Decoder[JobPostDetails] =
deriveDecoder[JobPostDetails]
//for encoding JobPostDetails into json
implicit val circeEncoder: Encoder[JobPostDetails] =
deriveEncoder[JobPostDetails]
//tells doobie to put JobPostDetails as json to details column
implicit val put: Put[JobPostDetails] =
Put[Json].contramap(_.asJson)
//tells doobie how to read JobPostDetails from json column
implicit val get: Get[JobPostDetails] =
Get[Json].temap(_.as[JobPostDetails].leftMap(_.show))
}
After that, you should be able to save JobPost
.
Upvotes: 1