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.

Connection between technologies according to the the StackOverflow Developer
Survey

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]
"""