3
votes

I am used to frameworks like Ruby on Rails or Laravel in PHP where I have models like User and when I want to make a query to the model (for example, to get all the users in the database) I do something like User::all().

I'm new to Play for Scala and Slick, and all the projects and documentation I've already seen use a DAO for accessing the database through a model. I've thought that a Scala object is what I need (or at least I am accustomed to) so I don't need to inject DAO classes everywhere.

With a DAO I do something like this:

class Application @Inject()(adminDAO: AdminDAO) extends Controller {
  def index = Action.async {
    adminDAO.all() map { case admins =>
      Ok(Json.toJson(admins))
    }
  }
}

And with an object (and no idea) I expect to do something like this:

class Application extends Controller {
  def index = Action.async {
    Admin.all() map { case admins =>
      Ok(Json.toJson(admins))
    }
  }
}

Trying to implement the "DAO" object I have found almost impossible to to inject the Play Application context without using Play.current which is deprecated. That kind of deprecation and the absence of a way of injecting the context (or at least I haven't found it) sounds strange to me. I'm starting to think that I'm thinking it the wrong way. Is it really a good idea to use a Scala object as DAO?

1
You can also have a look at Anorm.cchantep

1 Answers

3
votes

It comes down to dependency injection (DI) vs hardcoding dependencies. Your first example makes use of DI, your second one hardcodes the dependency against the Admin DAO. The Play team has decided to go with DI in recent releases in an effort to remove global state (for a discussion why global state is a bad thing see here for example):

Play now, out of the box, uses dependency injection provided by Guice. This is part of a long term strategy to remove global state out of Play, which we hope to complete in the Play 3.0 release.

Source

Hence the right way when it comes to Play is your example 1, using an object and hence a hardcoded dependency is indeed inadvisable purely based on the fact that you work against play (however DI has many advantages too).

I'm not well versed in Ruby, but as far as I know DI with frameworks (e.g. Guice) as it comes in Java/Scala isn't needed because Ruby has certain language features to solve the problem differently, which might be why you are wondering about the whole point of it all. I recommend you read a bit about dependency injection in a Java/Scala context, that should clear up how it works, what problems it solves and what the (dis)advantages are (and since you know Ruby, why it isn't needed in Ruby in the same way).

Trying to implement the "DAO" object I have found almost impossible to to inject the Play Application context without using Play.current which is deprecated. That kind of deprecation and the absence of a way of injecting the context (or at least I haven't found it) sounds strange to me.

You should be able to simply inject the application context into your DAO, e.g. like this:

class AdminDao @Inject()(val application : Application) { 

and then you have the application available. This is the equivalent to the deprecated

val application = Play.current

In both cases you capture the running Application. The depencency injection framework behind it all makes sure that dependencies are resolved recursively, i.e. when you depend on your DAO in a controller it notes that the DAO itself depends on the application. It resolves the application, injects it into a new DAO instance and finally injects that into your controller.

And last but not least many ways lead to rome as usual: Maybe ActiveSlick is something that you find useful (disclaimer: Haven't tried it myself).