I am trying to learn scala. I know how to write a function. This is how I write a function.
def test_function: Unit = {
println("This is just a test")
}
But then I started learning playframework. This is how they write a function in controller in play.
def test_function: Unit = Action{
println("This is just a test")
}
My question is what is this Action doing before the curly braces? What is it called? How can I write my own? I hope I have made my question clear. Thanks in advance.
You can get this kind of behavior by defining an apply method on an object called Action:
object Action {
def apply(block: => Unit): Unit = {
println("before")
block // do the action in the block
println("after")
}
}
Then both of these:
Action { println("hi") }
Action(println("hi"))
Produce this:
before
hi
after
The thing in braces after Action is just the argument to the apply method. Scala allows either parentheses or braces, but using braces allows you to put multiple statements in:
Action {
println("a")
println("b")
}
yields:
before
a
b
after
Action is a trait (play.api.mvc.Action). Essentially it represents this type: play.api.mvc.Request => play.api.mvc.Result (doc1, doc2).
In your case you are using Action {...} which is equivalent to Action(...) and converted by compiler to Action.apply(...) call. If you check source code you'll see the apply method signatures defined not only on the Action trait and it's companion object, but also in here:
/**
* Provides helpers for creating `Action` values.
*/
trait ActionBuilder[+R[_]] extends ActionFunction[Request, R]
In your case you are not taking any request and not producing any response, so essentially your Action is a function call of a form apply(block: => Result) where Result is thrown away since you define return type of your function as Unit.
Action supports many ways you can handle its body (including Futures) so pick the right apply method to cover your needs.
You can extend Action if you need to since it's not a final implementation. Here is an example:
case class Logging[A](action: Action[A]) extends Action[A]
Action is basically a function alias of the shape play.api.mvc.Request => play.api.mvc.Result. When you see Action { }, you are actually seeing apply function of the companion object of that type and are passing a body that should provide that Request => Result function.
The companion object has roughly the shape of:
object Action {
def apply(f: Request => Response): Action = ...
}
so that when you call Action { ... }, the { ... } is that function that will be executed when the action is invoked.
In your example, println("This is just a test") serves as the provider of the Result.
Related
I've been using Play! Framework with Java and would like to try it out with Scala.
I've started on a Scala book but the most basic Play! sample has me completely puzzled:
def index(): Action[AnyContent] = Action { implicit request =>
Ok(views.html.index())
}
What Scala construct is Play! using here? I understand that we are defining a function that returns an Action with a generic parameter AnyContent. But the next part has me puzzled. What does the assignment mean in this context?
If I go to definition of Action[AnyContent] it's defined as trait Action[A] extends EssentialAction { ... }
If I go to the definition of Action after equals it's defined as:
trait BaseController extends BaseControllerHelpers {
/**
* The default ActionBuilder. Used to construct an action, for example:
*
* {{{
* def foo(query: String) = Action {
* Ok
* }
* }}}
*
* This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way.
*/
def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
}
Note: I'm interested in the Scala construct that's used I don't care what Play! is actually doing here which I kind of understand.
You are essentially calling Action.apply(), which is defined here in ActionBuilder. The first and only parameter of the apply() function being the function request => Ok(...).
Imagine I have a service:
class ServiceA(serviceB: ServiceB) {
import Extractor._
def send(typeA: A) = serviceB.send(typeA.extract)
}
object Extractor {
implicit class Extractor(type: A) {
def extract = ???
}
}
I want the extract method to be an implicitly defined because it doesn't directly relate to A type/domain and is a solution specific adhoc extension.
Now I would like to write a very simple unit test that confirms that serviceB.send is called.
For that, I mock service and pass a mocked A to send. Then I could just assert that serviceB.send was called with the mocked A.
As seen in the example, the send method also does some transformation on typeA parameter so I would need to mock extract method to return my specified value. However, A doesn't have extract method - it comes from the implicit class.
So the question is - how do I mock out the implicit class as in the example above as imports are not first class citizens.
If you want to specify a bunch of customised extract methods, you can do something like this:
sealed trait Extractor[T] {
// or whatever signature you want
def extract(obj: T): String
}
object Extractor {
implicit case object IntExtractor extends Extractor[Int] {
def extract(obj: Int): String = s"I am an int and my value is $obj"
}
implicit case object StringExtractor extends Extractor[String] {
def extract(obj: String): String = s"I am "
}
def apply[A : Extractor](obj: A): String = {
implicitly[Extractor[A]].extract(obj)
}
}
So you have basically a sealed type family that's pre-materialised through case objects, which are arguably only useful in a match. But that would let you decouple everything.
If you don't want to mix this with Extractor, call them something else and follow the same approach, you can then mix it all in with a context bound.
Then you can use this with:
println(Extractor(5))
For testing, simply override the available implicits if you need to. A bit of work, but not impossible, you can simply control the scope and you can spy on whatever method calls you want.
e.g instead of import Extractor._ have some other object with test only logic where you can use mocks or an alternative implementation.
Consider the following Akka actor. Implemententations of this actor should need to override and implement handleMessage(message: T). This implementation should call executeQueryLookup on its last line
abstract class BaseQueryLookupActor[T, U] extends Actor {
def receive = {
case message: T => handleMessage(message)
case message => unhandled(message)
}
def handleMessage(message: T) // Abstract method
def executeQueryLookup(cacheName: String, queryName: String, params: Map[String, String]) {
// Concrete method that contains query logic
}
}
I realize there are multiple ways to achieve this without using any Scala functional concepts, but I'm thinking that it is also possible to achieve this somehow using a partial function or currying.
If so, how would I achieve this?
i'm not sure i follow, but would it work to define
def handleMessage(message: T): (String, String, Map[String, String])
and call executeQueryLookup yourself in the base class, like
def receive = {
case message: T =>
val (cacheName, queryName, params) = handleMessage(message)
executeQueryLookup(cacheName, queryName, params)
case message => unhandled(message)
}
If you leave it to the subclass to implement a method, and you call that method, then there is nothing the superclass can do to enforce that the implementation in the subclass does some specific action. This has nothing to do with currying or partial functions.
You will have another problem with your actor, since the generic type T is erased on the JVM: at runtime T = java.lang.Object. The match will therefore always be successful and the second case will never be invoked. You will have to pass along type tags both when creating the actor and with every message. A crude approximation would be to use classTag instead, since every JVM object has a .getClass method, but that will only match the outermost type and it will not help if you want to distinguish a List[Int] from a List[String].
Our Play application uses Slick as a data access layer. This means that in almost every action in our app we need to have both the current Request and Slick's database Session implicitly available on the scope.
I want to write a custom Action to do this so we only need one line to do this. What I want to do is write it in such a way that I can write something like this:
def someAction = DBAction { implicit request, session =>
// body with implicit request and session on scope
But this is not valid syntax. Using a tuple does not work because it cannot implicitly unpack the tuple in action body. Is it possible to create a custom action that passes multiple implicit arguments to the body? How do I do this?
You cannot implicit 2 variables like that.
But your Custom action can return a WrappedRequest (an object which encapsulates the request and your session), and you can define an implicit conversion between this wrapped request and your Session.
Try this example, derived from this class.
sealed case class DBRequest(session: Session, private val request: Request[AnyContent])
extends WrappedRequest(request)
trait DBController extends Controller {
// Implicit conversion from DBRequest to Session
implicit def session(implicit request: DBRequest) = request.session
def DBAction(action: DBRequest => Result) = Action { request =>
database.withSession { session =>
action(DBRequest(session, request))
}
}
}
object MyController extends Controller with DBController {
def myAction = DBAction { implicit request =>
println(session)
}
}
#senia was right, currying needs to be used to do this. This is actually addressed in the Play docs but it's a recent addition I missed.
For future reference for people looking for this, my custom action now looks like this:
def DBAction(action: Request[AnyContent] => Session => Result) = {
Action { request =>
database.withSession { session =>
action(request)(session)
}
}
}
Which I can then use in the following way:
def someAction = DBAction { implicit request => implicit session => /* body */ }
I never liked the new operator in Scala, particularly for DSLs. The workarounds for constructing objects without new are usually quite ugly. For instance, if you import scala.actors.Actor._, you have actor { ... }, but inside the body you are not having access to this: Actor, so there is all sorts of pseudo instance methods in that object, too, like receive, react, self, etc.
With Scala 2.10 macros, I wonder if there is a chance to get the following working?
object Button {
def apply(body: ? ): Button = macro applyImpl(body)
def applyImpl(c: Context)(body: c.Expr[ ? ]): c.Expr[Button] = ?
}
trait Button {
def text: String
def text_=(s: String): Unit
def doSomething(): Unit
}
Button {
text = "test"
doSomething()
}
As an additional challenge, what happens if doSomething is protected?
I don't think this will work, since
{
text = "test"
doSomething()
}
won't compile, as there is no text and no doSomething() method outside of the Button trait. Macros can currently only work on expressions that have already been typechecked.