0

I was trying this in playframework. When I came through this part, at first it seemed pretty straightforward but while trying to trace it I'm not able to understand how this works. I know what kind of parameter is accepted by apply method of Action but I couldn't get how request is available and how it can be passed to Ok. Can anyone show analogous example with simple definition in scala.

@Singleton
class HomeController @Inject()(configuration: Configuration, cc: ControllerComponents)(implicit assetsFinder: AssetsFinder)
  extends AbstractController(cc) {
  def tweets = Action { implicit request =>
    Ok(s"request is $request")
  }
}

Thanks in advance

pramesh
  • 1,914
  • 1
  • 19
  • 30

2 Answers2

1

Object Action extends trait DefaultActionBuilder extending trait ActionBuilder. The latter has method

apply(block: R[B] => Result): Action[B]

In your case request is of type Request[AnyContent] i.e. R is Request and B is AnyContent, Ok(s"request is $request") is of type Result,

Action { implicit request =>
  Ok(s"request is $request")
}

is of type Action[B] i.e. Action[AnyContent]. So the syntax is just apply method of an object and a lambda as an argument of the method.

What is the apply function in Scala?

foo(implicit x => ???) is the same as foo(x => { implicit val x_ = x; ??? }).

Implicit keyword before a parameter in anonymous function in Scala

Ok is just new Status(OK) i.e. new Status(200) and class Status has method

def apply[C](content: C)(implicit writeable: Writeable[C]): Result

i.e. C is now String and content is s"request is $request" (i.e. string "request is " + request.toString).

If you use IDE you can investigate similar inheritance hierarchies and types yourself.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Thank you for the answer. The real thing I need to know is according to which scala construct are we able to pass request to Ok? – pramesh Apr 09 '18 at 15:52
  • `Ok(s"request is $request")` is the same as `Ok.apply("request is" + request.toString)`. It's just function syntax in Scala (`f(x)` is the same as `f.apply(x)`) and string interpolation. – Dmytro Mitin Apr 09 '18 at 15:55
1

I'll try and simplify a bit:

trait A extends (String => String) { self => def apply() = this }

A effectively extends a function from String to String.

object A { def apply(f: String => String): A = new A { def apply(x: String) = f(x) } }

A's companion object actually implements A.

So you can now do this:

val f: String => String = _.toLowerCase
A(f)

This is valid Scala code.

You define f (toLowerCase on strings) and you pass it to the apply method of A.

This can also be written like this:

A { s => s.toLowerCase } // this way of putting it should remind you of Action { request => ... }

This is exactly how Play Action and EssentialAction works.

The other thing you ask is about Ok.

Ok is defined as a short version of Status with a set status code (200) and the given body (so something like Ok("Hello world!") will work.

On top of this there's the usual string interpolation you should know about.

mfirry
  • 3,634
  • 1
  • 26
  • 36