Reputation: 1153
I've got problem with implicit conversion from DB model to APP model:
override implicit def dbBook2AppBook(book: Book): BookApp = {
val author = Await.result(authRep.getById(book.authID),1 seconds)
BookApp(book.id.get, book.title,
AuthorApp(author.get.id,author.get.name,author.get.surname), book.available)
}
Basically i want to convert Book to BookApp:
case class BookApp(id: Int,
title: String,
author: AuthorApp,
var available: Boolean)
case class Book(id: Option[Int] = None, title: String, authID: Int, available: Boolean)
And as you can see my Book class have Author ID, and i want my BookApp to have AuthorApp object inside. What i need to do is to obtain from database Author, while doing conversion from Book. From database through authRep: AuthorReposiotory
i'm obtaining Future[Author]
.
My question is, if there is better way to obtain BookApp from convertion without need to use wait for Author object? Any suggestions?
For the answer from "Jon Anderson", I can't make conversion from Future[Book]
to Future[BookApp]
, because when i'm obtaining more than one row from Database i'm receiving Future[Seq[Book]]
, then the conversion won't work. Additional information, i still preserve Future in whole application, because when i do conversion i do something like this:
def findBooks(title: Option[String], authorName: Option[String],
authorSurname: Option[String], available: Option[Boolean])
: Future[Seq[BookApp]] = {
bookRep.findBooks(title,authorName,authorSurname,available)
.map(x => x.map( y => y: BookApp))
}
So convertion is done on object by map, but still returned converted unwrapped object. Main problem is wait in convertion, so main question is, how can i get rid of that?
Upvotes: 1
Views: 496
Reputation: 7768
As you discovered thought the types: you can't.
First of all, forget about using implicits in your design until you are more familiar with the languages, they won't help you here. (And forget about implicit conversion forever...)
One possible approach here would be stay work inside the Future
context suing a dbBook2FutureAppBook(book: Book): Future[BookApp]
.
Converting from a Future[Seq[Book]]
to Future[Seq[Bookapp]]
can be done using Future#flatMap
and Future.sequence
:
val fsb: Future[Seq[Book]] = ...
val fsa: Future[Seq[Bookapp]] =
fsb.flatMap { books =>
Future.sequence(books.map(dbBook2FutureAppBook))
}
This answers your question about Future
, but be aware that this will emit one database query per book in your Future[Seq[Book]]
, which is a terrible idea. You probably want to write a Seq[Book] => Seq[Bookapp]
query by hand.
Upvotes: 1
Reputation: 696
You should preserve the future all the way into the app layer. In this case, a for-comprehension
works nicely...
override implicit def dbBook2AppBook(bookFuture: Future[Book]): Future[BookApp] = {
for {
book <- bookFuture
author <- authRep.getById(book.authID)
//any other futures needed to create APP model here...
} yield {
BookApp(book.id.get, book.title, AuthorApp(author.get.id,author.get.name,author.get.surname), book.available)
}
}
Upvotes: 0