Reputation: 12091
I have a simple Play application in which I need to check url being called and use different database accordingly. I know that it's easy to access current url in the controller, but for this to work I need to access it in the model.
Passing the url from controller to each call of a model method would be too big of an inconvenience. Is there any other way to solve this problem?
Play Framework 2.2.1 / Scala 2.10.3
UPDATE: This is my basic example
Controller (Application.scala
):
package controllers
import play.api._
import play.api.mvc._
import models.Data
object Application extends Controller {
def index = Action {
//Call to model method - model should somehow get the URL without it being passed as a param
val smth: String = Data.getSmth()
Ok(smth);
}
}
Model (Data.scala
):
package models
object Data {
def getSmth: Option[String] = DB.withSession {
val db = //this is where I need the url to decide which database to use
sql"""SELECT #$db.smth FROM smthTable""".as[String].firstOption
}
}
Upvotes: 0
Views: 1004
Reputation: 11479
So, this is by design in the Play Scala API - there is no magic context, if you want data you will have to pass it along to whatever piece of your code that needs it.
You will have to take the url as a parameter of some kind, you could do it like this:
case class MyModel(someData: String, requestUrl: String)
object MyModel {
def apply(someData: String, request: Request) =
new MyModel(someData, request.url)
}
This would clearly express the dependency, but in your particular app you might call this from every request and want to avoid having to repeat providing that parameter, in that case you can use Scala implicits which makes the compiler look for a matching implicit instance that is of the same type in the current scope (you can read more about this here: http://www.scala-lang.org/old/node/114).
object MyModel {
def apply(someData: String)(implicit request: Request) =
new MyModel(someData, request.url)
}
which could then be called from a controller action like this
def myAction = Action { implicit request =>
val model = MyModel("blablabla")
...
}
Of course it may be a bad idea to tightly couple your model to the play Request API and you should probably introduce your own class to represent this 'context', you could then implicitly convert from Request
to YourContext
in you controllers and have the model implicitly use YourContext
instead.
If all this sounds like gibberish to you, you should probably start with actually learning Scala before trying to build a web app in Scala. There are lots of good books nowadays ('Scala for the impatient' for example) as well as a multitude of good online resources (the neophytes guide to scala is a good one).
Good luck!
Upvotes: 1