The below code works fine, but as you can see the 2nd clause in the for comprehension
has a call that is unsafe.
case class ProductView(product: Product, stores: List[Store], warehosue: Option[Warehosue])
def loadView(...): ConnectionIO[Option[ProductView]] =
for {
product <- getProductById(id) // ConnectionIO[Option[Product]]
warehouse <- getWarehouse(product.get.warehouseId.get.id) // ConnectionIO[Option[Warehouse]]
stores <- loadStores(...) // ConnectionIO[List[Store]]
} yield product map { p =>
ProductView(p, stores, warehouse)
}
I tried to make that a safe call, but my types don't seem to line up.
warehouse <- getWarehouse(product.get.warehouseId.get.id)
How can I improve this, if any of the options is a None
, I just want to return a None
.
This is suppose to return a Option[Warehouse]
I tried this:
warehouse <- product.map(p => p.warehouseId.map(id => getWarehouse(id)))
Hoping someone can help with this part of my for comprehension.
CodePudding user response:
The easiest way is using OptionT
and flatTraverse
def loadView(id: Int):
ConnectionIO[Option[ProductView]] =
(for {
product <- OptionT(getProductById(id))
warehouse <- OptionT.liftF(product.warehouseId.flatTraverse(getWarehouse))
stores <- OptionT.liftF(loadStores(...))
} yield ProductView(product, stores, warehouse)).value
Also alternative variant without OptionT
def loadView(id: Int): ConnectionIO[Option[ProductView]] = {
getProductById(id).flatMap {
_.traverse { product =>
for {
warehouse <- product. warehouseId.flatTraverse(getWarehouse)
stores <- loadStores(...)
} yield ProductView(product, stores, warehouse)
}
}
}