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 =>
    //get all users

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

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

  def view(id: String) = Action {
    implicit request =>

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

      userOption match {
        case Some(user) => {
        case None => InternalServerError("Could not find user")

  def follow(id: String) = SecuredAction(true) {
    implicit request =>

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

      currentUserIdentityOption match {
        case Some(currentUser) => {

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

          userToFollowOption match {
            case Some(userToFollow) => {
              GraphDbService.addEdge(null, currentUser.id.id, id, "follows")
              val message = ResponseMessage("ok", "following user: " + id.toString).toJsonString
            case None => Ok(ResponseMessage("error", "cannot find user: " + id.toString).toJsonString)
        case None => 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 <- users) yield
        "userId" -> Json.toJson(user.getUserId),
        "graphId" -> Json.toJson(user.asVertex().getId.toString),
        "firstName" -> Json.toJson(user.getFirstName),
        "lastName" -> Json.toJson(user.getLastName),
        "fullName" -> Json.toJson(user.getFullName),
        "providerId" -> Json.toJson(user.getProviderId),
        "firstName" -> 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)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.