According to the StackOverflow Developer Survey
2020,
the Scala programming language is mainly used in connection with Hadoop and
Spark. In
contrast to the survey, the Play Framework
provides a modern web framework that is inspired by Django or Ruby on Rails.
Coming from a Django background, I think the learning curve for the PlayFramework
is much steeper, and some things that come naturally in Django are much harder to
get in Play. This article shows how to get an interactive shell to work with
your models in Play, similar to Django’s python manage.py shell
.
In my experience, Django takes the term convention-over-configuration much more literally. Active Record-like models come basically for free. In Play, one has to work a bit on the model and the repository (a.k.a. manager in Django parlance) to get a similar implementation. The structure of the model in Play resembles much more what Eric Evans describes in his book Domain-Driven Design.
When I started working with Play, I wanted to have an interactive shell with access to the model and a local instance of a database. I know and love such a shell from Django. It would slow down the development if such a console was not possible in Play.
Play provides an interactive shell with the console
command in sbt
. The
ubiquitous dependency injection requires a bit of boilerplate code in order to
access our repositories to retrieve model entities. Assume we have a repository
called PollsRepository
, much like the example of the Django tutorial. You can get
interactive access to the repository with the default
database by running the following boilerplate in sbt’s console.
import play.api._
val env = Environment(new java.io.File("."), this.getClass.getClassLoader, Mode.Dev)
val context = ApplicationLoader.Context.create(env)
val loader = ApplicationLoader(context)
val app = loader.load(context)
val dbApi = app.injector.instanceOf[db.DBApi]
// Apply database evolution
db.evolutions.Evolutions.applyEvolutions(dbApi.database("default"))
val pollsRepo = app.injector.instanceOf(Class.forName("models.PollsRepository")).asInstanceOf[models.PollsRepository]
To make this a bit more practical, add the following code to your built.sbt
file. This will create the repository instance every time you fire up the console.
console / initialCommands := """import play.api._
val env = Environment(new java.io.File("."), this.getClass.getClassLoader, Mode.Dev)
val context = ApplicationLoader.Context.create(env)
val loader = ApplicationLoader(context)
val app = loader.load(context)
val dbApi = app.injector.instanceOf[db.DBApi]
db.evolutions.Evolutions.applyEvolutions(dbApi.database("default"))
val pollsRepo = app.injector.instanceOf(Class.forName("models.PollsRepository")).asInstanceOf[models.PollsRepository]
"""
This might also interest you