UPDATE: This isn't a full tutorial. I plan on doing this in pieces. The code shown here is one example of one piece of the app. I'll delve more into the code later, but I thought that the issues I encountered while getting up and going were more important to write about initially. I hope that's not too confusing.
It's been a while, but I finally have something interesting to write about.
I've been dabbling with the Play framework again after some time. Work uses Java for a whole lot of stuff so I figured it'd behoove me to ease myself into the JVM again. I don't know Scala very well, but after a foray into Go and C#, looking at it now makes a lot more sense than when I first looked at it.
I decided that I wanted to write a workout progress tracker. I'm getting married in August and I made it a goal a while back to put on some muscle weight, and put on some weight on the bar. I'd been struggling and struggling to get more weight up on the bar, and just couldn't be consistent. Long story short, it turns out a lot of it was my diet, probably almost all of it (but that's another story). My lifts started improving, I gained about 10-12 pounds, and I decided I wanted to see how far I've come since I started officially lifting again a few years ago.
A few things have changed since I last looked at Play. For one, it uses the activator system to scaffold apps, run tests, install scala, etc. It's a little confusing, but really it's not so bad. I also had intended on using squeryl for my database object stuff, but it looks like it hasn't been updated in a while and I remembered the agonizing pain I went through just to get it to work at all the last time I did this. So, I went with slick, play's endorsed ORM thingy. Specifically, I went with play-slick, which integrates slick directly into play itself.
This was a little bit of a nightmare at first, because the tutorial for play initially sets you up with play 2.3.8 by default, and I wanted to be using the latest play-slick, as those docs seemed the most robust and up to date, which requires:
- Play version 2.4.x
- Slick version 3.0.x
- Scala version 2.10.x/2.11.x
The issue I ran into, that frustrated me to no end, was the fact that the tutorials don't specify which specific versions of each you need. I just looked through my commit history to try to find specifics, and I started convulsing, so long story short: if you're getting a lot of errors trying to find dependencies, make sure your build.sbt has at least a couple resolvers for the typesafe repository, and google the latest version for your dependency and try using that. Here are my plugin.sbt and build.sbt for reference (I went ahead and made a gist so that they remain tied to this post's version, here's the repo in case you are from the future and want to see something that may be more up to date: https://github.com/dhoss/steel): https://gist.github.com/dhoss/1a824ee5397f22eec0ac.
ANOTHER NOTE BEFORE I GO FURTHER: I felt like a complete idiot for this, but adding a resolver in plugins.sbt doesn't necessarily mean it's going to be available in build.sbt. I'm sure this is incredibly naive and dumb, but I spent a lot of time yelling at my screen trying to figure out why nothing was being pulled down from the repo I had just added. I ended up just adding the resolvers to both build.sbt and plugins.sbt. Like they say, "shoot 'em all and let God sort 'em out."
The last thing I really needed to get sorted was this nagging issue where my app couldn't connect to postgres. Postgres was running, I could connect to it using the same username and password, but the app couldn't do it. Again, this was something minor that turned out to be in front of my face the whole time, but because I wasn't able to find a lot of documentation on slick driver connection configuration. This one line was all that was standing between me and glory:
This needs to go before a line that looks like this:
This really confused me for a while, so I can help keep others from this same frustration.
Moving on to some code.
Make sure you read through this and get everything set up first: https://www.playframework.com/documentation/2.4.x/Home
I decided to go with a DAO set up for my database access, because the initial code I was following is set up as such and it seemed reasonably simple and flexible. You do have to write your CRUD methods, but I found it nice to be able to control exactly what you want those doing.
For starters, let's define our model. In this case, we basically define our table structure in relatively broad strokes.
Simple enough. Remember, you still need to write the actual SQL to create these tables with play evolutions.
Next, let's take a look at one of our DAOs.
We define our column methods, and a * projection that acts how would expect it would with SQL. Next, we create a class that sets up the dbConfig, our query object (exerciseTypes), a method to map ids to names for option dropdowns, and our insert and list methods. Fairly simple.
Per TDD, here is a small test that makes sure we can insert and retrieve things:
Nothing out of the ordinary here either.
So, this concludes things for now. I've got a ways to go on my scala skills, and this app certainly has a bit to go as well. I'm hoping to document the app's progress and post any "gotchas" I run into from here on out as well.
Next time, I'll try to demonstrate how to add a datatable for quick CRUD and sorting.