Cristian Boariu
Cristian Boariu

Reputation: 9621

Scala trait for Rest class in Play

In a Play Framework project, I have controllers for handling REST request, an example would be:

 object AddressBean extends Controller with RestTrait{

  def list = Action {
    val list = Addresses.findAll()
    Ok(Json.toJson(list.map(s => Json.toJson(s)(AddressJson.addressWrites))))
  }

  def create = Action {
    Ok("")
  }
}

(please note that I just put OK("") to compile, I have to implement them, like I implemented list method).

I want to define a trait for all these REST classes to implement the same methods and I started like:

    /**
 * Define an interface for all of our REST classes.
 */
trait RestTrait extends Controller{
  /**
   * List entities.
   */
  def list
  /**
   * Create entity. Get entity from request.body
   */
  def create

  //and so on
}

The issue is that I receive a warning saying Unit does not take parameters so I understand that my methods from trait should have an Action return type so I end up defining them like:

    /**
 * Define an interface for all of our REST classes.
 */
trait RestTrait extends Controller{
  /**
   * List entities.
   */
  def list = Action{
      Ok("")
  }
  /**
   * Create entity. Get entity from request.body
   */
  def create = Action{
      Ok("")
  }

  //and so on
}

Isn't there any way to avoid defining methods in trait like this? Because then I have to use override in my classes. I mainly want to implement not override those methods...

Upvotes: 2

Views: 491

Answers (1)

Blake Pettersson
Blake Pettersson

Reputation: 9067

Abstract methods without a return type will return Unit, so all you have to do is to add return type of Action[AnyContent] to your methods.

trait RestTrait extends Controller{
  /**
   * List entities.
   */
  def list:play.api.mvc.Action[play.api.mvc.AnyContent]

  /**
   * Create entity. Get entity from request.body
   */
  def create:play.api.mvc.Action[play.api.mvc.AnyContent]

  //and so on
}

Action is in fact a singleton object that accepts a function which returns a Result.

object Action extends java.lang.Object with scala.ScalaObject {
...
  def apply(block : scala.Function1[play.api.mvc.Request[play.api.mvc.AnyContent], play.api.mvc.Result]) : play.api.mvc.Action[play.api.mvc.AnyContent]
  def apply(block : => play.api.mvc.Result) : play.api.mvc.Action[play.api.mvc.AnyContent]
}

Upvotes: 5

Related Questions