Я пытаюсь вернуть запись пользователя из базы данных, используя doob ie, http4s и cats. Я оказался в тупике из-за системы типов, которая выдает следующую ошибку на основе приведенного ниже кода:
маршрутизатор:
val httpRoutes = HttpRoutes.of[IO] {
case GET -> Root / "second" / id =>
val intId : Integer = Integer.parseInt(id)
//if i make thie ConnectionIO[Option[Unit]] it compiles, but returns a cats Free object
val userOption: ConnectionIO[Option[User]] = UserModel.findById(intId, transactor.transactor)
Ok(s"userOption is instance of: ${userOption.getClass} object: ${userOption.toString}")
}.orNotFound
модель:
case class User(
id: Read[Integer],
username: Read[String],
email: Read[String],
passwordHash: Read[String], //PasswordHash[SCrypt],
isActive: Read[Boolean],
dob: Read[Date]
) {
// def verifyPassword(password: String) : VerificationStatus = SCrypt.checkpw[cats.Id](password, passwordHash)
}
object UserModel {
def findById[User: Read](id: Integer, transactor: Transactor[ConnectionIO]): ConnectionIO[Option[User]] = findBy(fr"id = ${id.toString}", transactor)
private def findBy[User: Read](by: Fragment, transactor: Transactor[ConnectionIO]): ConnectionIO[Option[User]] = {
(sql"SELECT id, username, email, password_hash, is_active, dob FROM public.user WHERE " ++ by)
.query[User]
.option
.transact(transactor)
}
}
Ошибка :
Error:(35, 70) Cannot find or construct a Read instance for type:
core.model.User
This can happen for a few reasons, but the most common case is that a data
member somewhere within this type doesn't have a Get instance in scope. Here are
some debugging hints:
- For Option types, ensure that a Read instance is in scope for the non-Option
version.
- For types you expect to map to a single column ensure that a Get instance is
in scope.
- For case classes, HLists, and shapeless records ensure that each element
has a Read instance in scope.
- Lather, rinse, repeat, recursively until you find the problematic bit.
You can check that an instance exists for Read in the REPL or in your code:
scala> Read[Foo]
and similarly with Get:
scala> Get[Foo]
And find the missing instance and construct it as needed. Refer to Chapter 12
of the book of doobie for more information.
val userOption: ConnectionIO[Option[User]] = UserModel.findById(intId, transactor.transactor)
Если я изменю строку на ConnectionIO [Option [User] на ConnectionIO [Option [Unit]], она компилируется и запускается, но возвращает объект Free (...) из библиотеки cats, который Я не смог понять, как разбирать, и не понимаю, почему я не могу вернуть свой класс дела!
См. Также объявления типов в методах findBy и findById. Перед тем, как я добавил их, была ошибка компиляции, в которой говорилось, что обнаружен пользователь, но требуется Read [User]. Я попытался применить объявление того же типа к вызову findById в маршрутизаторе, но он дал ту же ошибку, указанную выше.
Заранее благодарим вас за вашу помощь и, пожалуйста, проявите терпение, учитывая мое невежество. Я никогда не встречал более умной системы типов, чем я!