Scala Play Controller - Refactoring out Duplication for Restful Web Services I'm new to scala and I'm noticing I have some repeating code in my controllers.

I'm wondering if anyone can give some hints for traits and parameterization for eliminating duplicate code for basic crud operations on the web services - I'm still a little confused about how to use scala 'generics'/parameters.

Don't mind the json - I've fixed this horrible scrappy code now using the objects to render themselves as json.

Code piece

package controllers

import play.api.mvc._
import securesocial.core._
import play.Logger
import models.{ResponseMessage, GraphedUser}
import com.tinkerpop.blueprints.Vertex
import service.{BaseFramedEntity, SecureSocialUserService, FramedGraphService, GraphDbService}
import play.api.libs.json._
import scala.util.parsing.json
import json.JSONArray
import play.api.libs.concurrent.{Akka, Promise}
import play.api.Play.current
import securesocial.core.UserId
import Predef._
import play.mvc.With

/**
 * Controller for user api
 */
object UsersController extends BaseController with securesocial.core.SecureSocial {


  val collectionName = "users"


  def index = Action {
    implicit request =&gt;
    //get all users

      val pageOption = request.queryString.get("page")

      pageOption match {
        case Some(page) =&gt; {
          val resultsPerPageOption = request.queryString.get("numResults")
          resultsPerPageOption match {
            case Some(size) =&gt; Ok(renderUserJson(getUserList(page.head.toInt, size.head.toInt))) //Both page and size exists
            case None =&gt; Ok(renderUserJson(getUserList(page.head.toInt, defaultPageSize))) //only page exists
          }
        }
        case None =&gt; Ok(renderUserJson(getUserList(defaultPage, defaultPageSize))) //page doesn't exist. Ignore size.
      }
  }

  def view(id: String) = Action {
    implicit request =&gt;

      val userOption = FramedGraphService.getFramedVertexByProperty("userId", id, classOf[GraphedUser])

      userOption match {
        case Some(user) =&gt; {
          Ok(user.toString)
        }
        case None =&gt; InternalServerError("Could not find user")
      }
  }

  def follow(id: String) = SecuredAction(true) {
    implicit request =&gt;

    //Must validate user...
      val currentUserIdentityOption = SecureSocial.currentUser

      currentUserIdentityOption match {
        case Some(currentUser) =&gt; {

          val userToFollowOption = FramedGraphService.getFramedVertexByProperty("userId", id, classOf[GraphedUser])

          userToFollowOption match {
            case Some(userToFollow) =&gt; {
              GraphDbService.addEdge(null, currentUser.id.id, id, "follows")
              val message = ResponseMessage("ok", "following user: " + id.toString).toJsonString
              Ok(message)
            }
            case None =&gt; Ok(ResponseMessage("error", "cannot find user: " + id.toString).toJsonString)
          }
        }
        case None =&gt; InternalServerError(ResponseMessage("error", "unknown error").toJsonString)
      }
  }

  private def getUserList(page: Int, size: Int): Iterable[GraphedUser] = {
    val fullUsersList = FramedGraphService.getFramedVerticesByProperty(BaseFramedEntity.TYPE_KEY, GraphedUser.USER_TYPE, classOf[GraphedUser])
    fullUsersList.slice((page - 1) * size, (page - 1) * size + size)
  }

  private def renderUserJson(users: Iterable[GraphedUser]): String = {

    val listToConvert = for (user &lt;- users) yield
      Json.toJson(Map(
        "userId" -&gt; Json.toJson(user.getUserId),
        "graphId" -&gt; Json.toJson(user.asVertex().getId.toString),
        "firstName" -&gt; Json.toJson(user.getFirstName),
        "lastName" -&gt; Json.toJson(user.getLastName),
        "fullName" -&gt; Json.toJson(user.getFullName),
        "providerId" -&gt; Json.toJson(user.getProviderId),
        "firstName" -&gt; Json.toJson(user.getAvatarUrl)))

    val concatenated = listToConvert.foldLeft("")(_ + _)
    surroundJsonWithObject(concatenated, collectionName)
  }
}
for all the option matchers you could use getOrElse
And remember: Option is also a list with all given features

here an example

val resultsPerPageOption = request.queryString.get("numResults")
val size= resultsPerPageOption.map(_.head.toInt).getOrElse(defaultPageSize)
Ok(renderUserJson(getUserList(page.head.toInt, size)))