Try, the new monad in Scala 2.10

Today I tried for the first time Scala’s Try monad. I used it twice already and I’m sure I’ll use a lot more times!

Here is how I used it the first time. I wanted to parse some CSV data into a sequence of case classes. And of course, with input data you never know what can go wrong. I didn’t really want to handle the error, I just wanted to know if it was parsed correctly or not. Therefore I used an Option to return either Some(result) or None.

Here is the code for the attempt with Option:

def parseCSV(csv : String) = {
  try {
    Some {
      csv.split("\n").map { line =>
        val tokens = line.split(";")
        ActivityData(tokens(0).toLong, tokens(1).toInt, tokens(2).toInt, tokens(3).toLong)
      }
    }
  } catch {
    case _ : Throwable => None
  }
}

A bit complicated isn’t it? Using this function is cool (just as with every other Option) but actually reading it is painful. It’s just too messy with that try catch. Is there a better way of doing this?

Well, there comes the Try monad from scala.util package to save the situation!

def parseCSV(csv : String) = Try {
  csv.split("\n").map { line =>
    val tokens = line.split(";")
    ActivityData(tokens(0).toLong, tokens(1).toInt, tokens(2).toInt, tokens(3).toLong)
  }
}

Look at this! Wow! This is neat! Just surround your code with Try and that’s it!

And the best part, you can use it exactly the same way as you would use the Option monad (dah .. that’s what are monads all about).

parseCSV(csvdata).map { entries =>
  //do something with the data
}.getOrElse {
  BadRequest("Invalid CSV Data")  //this is Play Framework specific (returns a 400 HTTP response with a message)
}

Note: For those who are wondering how does this work, the Try monad returns Success(something) if everything was calculated without any exceptions and Failure(error) if an error was thrown while executing the argument of Try().

Note (deep): Try takes its argument by-name (not by-value), therefore it can execute it within a try, catch the exception and return either Success or Failure. Isn’t Scala a super powerful awesome language? Yes it is!

Advertisements

How to simplify your action’s validation code in Play Framework 2 (with Scala of course)

In web development you very often want to do some checks if the data passed through parameters are valid. I’m not talking about having valid format but if for example the corresponding entry exists or if the user has the right to access that information or not. I’ll be a bit more specific by using an example and you’ll get my point. Ok, let’s consider that we want to make a web app which manages devices andΒ users. A device has a unique id and a name. A user has a unique id, a name and a set of devices attached to him. Let’s assume we wrote all the necessary code and we want to provide an action that attaches a device to a user. How would we do that? My first approach would be something like this:

object Users extends Controllers {

  def attachDevice(user_id : Long, device_id : Long) = Action {
    models.User.getById(user_id).map { user_id =>
      models.Device.getById(device_id).map { device_id =>
        if (models.User.attach(user_id, device_id))
          Ok("succeeded")
        else
          InternalServerError
      }.getOrElse { BadRequest("Invalid device id") }
    }.getOrElse { BadRequest("Invalid user id") }
  }

}

That’s fine! It’s not a bad approach. We do all the necessary tests. Code is more or less readable. It’s clear what we return in each case. But what happens when we want to have another action that needs to check if the user_id or device_id is valid? Would we rewrite them?

Not really! We would refactor them!

Great! Let’s create a trait Security and put our validations there.

trait Security {
  import play.api.mvc.Results._

  def withValidDevice(device_id : Long)(result : Result) = {
    if (models.Device.getById(device_id).nonEmpty)
      result
    else
      BadRequest( "Invalid device id" )
  }

  def withValidUser(user_id : Long)(result : Result) = {
    if (models.User.getById(user_id).nonEmpty)
      result
    else
      BadRequest( "Invalid user id" )
  }

  def IsValidUserAndDevice(user_id : Long, device_id : Long)(f: Request[AnyContent] => Result) = Action { req =>
    withValidUser(user_id) {
      withValidDevice(device_id) {
        f(req)
      }
    }
}

That’s it! Let’s use it now in our controller to simplify the code. Can you guess what it would be?

object Users extends Controllers with Security {

  def attachDevice(user_id : Long, device_id : Long) = IsValidUserAndDevice(user_id, device_id) {
    if (models.User.attach(user_id, device_id))
      Ok("succeeded")
    else
      InternalServerError
  }
}

This is a lot cleaner isn’t it? But what if we want to process a POST request with form data? How would we use our validations? It turns out that it’s not so hard to do (see code below).

object Users extends Controllers {

  import play.api.data.Forms._
  import play.api.data._

  case class AttachData(user_id : Long, device_id : Long)

  val attachForm = Form(
    mapping(
      "user_id" -> longNumber,
      "device_id" -> longNumber
    )(AttachData.apply)(AttachData.unapply)
  )

  def attachDevice(user_id : Long, device_id : Long) = Action {
    shareForm.bindFromRequest.fold(
      formWithErrors => BadRequest( formWithErrors.errorsAsJson ),
      data => {
        withValidUser(data.user_id) {
          withValidDevice(data.device_id) {
            if (models.User.attach(user_id, device_id))
              Ok("succeeded")
            else
              InternalServerError
          }
        }
      }
    )
  }
}

We could for improvement define a method withValidUserAndDevice in our Security trait and then simplify the POST request code as well.

Conclusion

There is no very special conclusion telling the truth but I just wanted to point out this pattern with defining two validation methods:

  1. A method that returns an Action and can simplify the code of the GET requests
  2. A method that returns a Result which can simplify the POST requests and is flexible enough to be used in every action you want

As always, I hope you’ll find this blog entry useful and will help you simplify your validation code with Play Framework 2 and Scala πŸ™‚

Change brightness of my laptop screen through command line

Unfortunately the Fn buttons for brightness don’t work with Lubuntu and my Acer laptop. Luckily, there is a command line solution for that:

xrandr --output LVDS1 --brightness 0.8

I’m pretty sure you can figure out that 0.8 means 80% right? Rest is simple πŸ˜€

I know that this is not a remarkable blog post but next time I’ll be sitting in the darkness blinded by my screen’s too strong brightness I’ll know exactly where to look for the command that changes it πŸ™‚

Have a nice weekend!