Reputation: 4068
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!
Upvotes: 1
Views: 5944
Reputation: 5293
Have you looked at using for-comprehensions? You could do something like the following:
for(
company <- Company.currentCompany.map{_.owner};
user <- User.currentUser.map{_.id}
) yield (company == user).getOrElse(false)
This will return true if Company.currentCompany is Some[value], and User.currentCompany is Some[value], and company.owner == user.id.
I feel there should be some way of getting rid of that getOrElse on the end, and returning the unwrapped boolean directly, hopefully someone else might be able to shed some light on this!
Upvotes: 10
Reputation: 1918
Given:
Case class user(name:String)
Case class company(owner:Option[User])
Val currentcompany=company(Some("Karl"))
Val currentuser=Some(user("Karl"))
Possible solution:
currentcompany.foldLeft(false) {
case (a,b) => currentuser.isDefined && b.owner == currentUser.get
}
Upvotes: 0
Reputation: 4345
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)
}
}
Upvotes: 6