I'm trying to get the hang of working "the Scala way" so I was wondering if the following code is how things should be done in this case.
So I have the entities User and Company (mapped with LiftWeb mapper). User has currentUser which contains an Option[User] and Company has currentCompany which is an Option[Company]. In order to compare if the current user is the owner of the current company I'm doing something like:
Company.currentCompany.map{_.owner.get == User.currentUser.map{_.id.get}.openOr(-1) }.openOr(false)
It works but somehow it feels kinda verbose. Is it good? Is it not? Any better ideas? Thanks!
Using for-comprehension is definitively the solution, actually... or flatMap
but less readable
To recall every generators are bound using flatMap
function of the Monadic Option
, except the last which is mapped (like any for
and yield
). Here is a good slideshow on the underneath concepts Monad
So the for comprehension is used to pass through all steps while they aren't encoded in the fail state (None
for Option
).
Here is a full example with four tests (the four basic cases) for each options (for and flatMap)
case class User(id: String) {
}
object User {
def currentUser(implicit me: Option[User]): Option[User] = me
}
case class Company(owner: Option[User]) {
}
object Company {
def currentCompany(implicit myCompany: Option[Company]): Option[Company] = myCompany
}
object Test extends App {
test1()
test2()
test3()
test4()
test5()
test6()
test7()
test8()
def test1() {
implicit val me: Option[User] = None
implicit val myCompany: Option[Company] = None
val v: Boolean = (for {
c <- Company.currentCompany
u <- User.currentUser
o <- c.owner if o.id == u.id
} yield true) getOrElse false
println(v)
}
def test2() {
implicit val me: Option[User] = Some(User("me"))
implicit val myCompany: Option[Company] = None
val v: Boolean = (for {
c <- Company.currentCompany
u <- User.currentUser
o <- c.owner if o.id == u.id
} yield true) getOrElse false
println(v)
}
def test3() {
implicit val me: Option[User] = None
implicit val myCompany = Some(Company(me))
val v: Boolean = (for {
c <- Company.currentCompany
u <- User.currentUser
o <- c.owner if o.id == u.id
} yield true) getOrElse false
println(v)
}
def test4() {
implicit val me: Option[User] = Some(User("me"))
implicit val myCompany = Some(Company(me))
val v: Boolean = (for {
c <- Company.currentCompany
u <- User.currentUser
o <- c.owner if o.id == u.id
} yield true) getOrElse false
println(v)
}
def test5() {
implicit val me: Option[User] = None
implicit val myCompany: Option[Company] = None
val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false
println(v)
}
def test6() {
implicit val me: Option[User] = Some(User("me"))
implicit val myCompany: Option[Company] = None
val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false
println(v)
}
def test7() {
implicit val me: Option[User] = None
implicit val myCompany = Some(Company(me))
val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false
println(v)
}
def test8() {
implicit val me: Option[User] = Some(User("me"))
implicit val myCompany = Some(Company(me))
val v:Boolean = Company.currentCompany.flatMap(c => User.currentUser.flatMap( u => c.owner.map(o => if (u.id == o.id) true else false))) getOrElse false
println(v)
}
}