Want to discuss a project?

Replacing Rails: Part 1 "Lets Go!"

Alex Barlow ·
23 April 2015

Rails has been, whether I like it or not, a pretty big chunk of my life. When I first started charging for my work, Rails was new and it seemed like a community of really active developers. Github and RubyGems seem to have changed the way we all write and use code. (Remember when Github used to be the best RubyGem host?!)

Here at Made by Many, Ruby along with Rails is often our back end of choice for building applications that require a quick turnaround, particularly when there is lots of CRUD involved. It's often an easy option with a fairly good toolset (we’ll talk more about that later) and lots of RubyGems around it cover everything from pagination to authentication.

Simply “not using Rails” anymore however is, well, not that simple! Rails does certain things very well and that’s a part of why it’s still around. In particular, Forms, Database mapping (ORM), Convention, Emails, Rake Tasks and Migrations to name a few, so what’s around that has a chance of replacing Rails? Go!

I’m not going to try and teach you Go from scratch, but look at the getting start guide and Go by Example for some great help there. Also this video is a great talk about some ideas behind the concurrency in Go.

I’m hoping to make this into a series of posts, but I’m not going to make a step by step guide. If that’s something that could interest you, perhaps a screencast is in order.

In the last week I’ve been building an app that includes Dropbox authentication, a job queue and RESTful controllers — so let’s have a look at some of those parts extracted and compare them to Rails-land! In this example I’m using a simple router/toolkit called Martini.

Here’s my model for Reels (a Reel is a collection of Photos); not so different really! The JSON notation you see is called ‘tags’ in Go, it’s essentially metadata added to the field and here it specifies the field names Go will use to parse or encode JSON. “-” means don’t print anything and “omitempty” means only output the field if it isn’t null.

For database access we’re using Gorm, which automagically maps database results back into structs and can do the same back when saving to the database.

I was sceptical of Gorm at first, it promises an ORM (which is a scary thought) and a lot more but so far we’ve had good experiences with it. We decided not to use its automatic database migrations in favour of hand written SQL migrations using Goose, our migration for the reel model looks as simple as this..

Let’s have a look at the controller which uses our reel model, we’ll have a look at how we handle the authentication and database access after that.

Two things to note in this controller are the ReelsControllerRouter function which we’ll use in a moment to add the routes to our application and the helper methods at the bottom, which find a reel in the database scoped by the given user and parse an incoming JSON response (as it’s an API) into a ReelForm object.

The ReelForm object is a separate object to the Reel object to avoid mass assignment issues and at a later date validations.

To glue these together, lets have a look at our app.go file, this is the main file in our application and is responsible for router and general setup.

Here’s where we leverage Martini and Martini Router, add some default security options, initialise a cookie store (for storing a users login) and importantly, setup a DB connection using Gorm and use Martini’s Map function to attach it to any request that needs it. Our users authenticate using Dropbox (more of that in part 2) but here’s a peak at how we perform our authentication check from a cookie.

What’s next?

In part 2 I’m going to dive deeper into Go, our testing framework, our tools and talk about creating packages you can use throughout your app (like a Dropbox client or a Worker).