Not using head on list inside the method of a controller

Viewed 60

I have the following method of a controller:

  def edit(bookId: Int): Action[AnyContent] = messagesAction {implicit request => {
    val books = Book.getBookId(bookId)
    if(books.nonEmpty) Ok(views.html.book.create(bookForm.fill(books.head)))
    else NotFound("Book is not found.")
  }}

But I'm not satisfied with how I'm doing this.

Actually, I would like to not test the emptiness of the list (the books val).

I tried something like :

  def edit2(bookId: Int): Action[AnyContent] = messagesAction {implicit request => {
    Book.getBookId(bookId).foreach(book => Ok(views.html.book.create(bookForm.fill(book))))
    NotFound("Book is not found.")
  }}

It does compile but I have the NOtFound redirection every time.

How could I do this?

3 Answers

Maybe you're just looking for pattern matching?

Book.getBookId(bookId) match {
   //get head of list and ignore rest
   case book :: _ => Ok(views.html.book.create(bookForm.fill(book)))
   //if list is empty return not found 
   case Nil       => NotFound("Book is not found.")
}

The reason why your second code example doesn't work is because the result of the last expression of the method is used as the return value, so in your case it is always NotFound(...).

If you don't want to test on books.nonEmpty, you could work with headOption like

Book.getBookId(bookId).headOption
  .map(book => Ok(views.html.book.create(bookForm.fill(book)))))
  .getOrElse(NotFound("Book is not found."))

But I'm not sure if that's easier to understand than your original solution.

You could also fold the option like so

Book.getBookId(bookId).headOption.fold(NotFound("Book is not found.")) { book =>
  Ok(views.html.book.create(bookForm.fill(book)))
}
Related