Rails API Versioning

May 18, 2017


Versioning? Sounds like something I made up but it's a real thing and you need to care about it say's I! But really, it's something you don't wanna forget about if you want to update your API in the future and not upset your users. Just like applications on your phone and computer, it's common for APIs to receive updates and changes. The problem is that people using your API expect certain results to stay constant and that's not always possible with updates. So to keep your customers happy and their customers happy we need to discuss versioning!

To begin, if you didn't go through Creating a Rails API or didn't keep the code you can clone it from Github here.

Creating our API Routes

To start out we're going to begin in the routes.rb file which can be found in the config folder. This file is used to recognize URLs and dispatch them to the controller action they correspond to. For instance, when we type into the URL localhost:3000/dog_parks our application looks into this file for a matching route. It's sorta odd our application finds a route since nothing in the routes.rb files even remotely resemble that URL huh?

The magic is in line 2 resources :dog_parks. This single line creates all the common routes we'd need for the CRUD controller we have. If you don't believe me then dive into the terminal, open your project, and type in bin/rails routes. You should see this.

Crazy huh? We get all of that with one line. If we didn't add that single line we would need to add all of this to get the same functionality.

If you look at the routes again you'll see the same routes are available but with a lot more code required.

With that established we can work on our API's versioning. First, we'll add an API namespace to our routes. When you do this look at the routes and see how it has changed.

Next, we can specify more finely the version we'd like to make available to people by adding another namespace called "v1".

If you run the routes you'll see v1 has been added but if you try and run them you'll get an error. Our routes.rb file thinks the controller will be placed inside of app > controllers > api > v1 but we haven't set up that folder structure yet. We'll do that next.

Adding the Folder Structure

To make sure our controllers are in the right place we'll be adding a few folders and then copying the existing dog_parks_controller.rb into them. You can create the folders with the terminal like me or manually add them via your text editor.

Then add a new file called dog_parks_controller.rb and copy the stuff from the original file to this new one. Lastly, it's important you surround your class with these module statements.

When you've done that your class should look like this.

Using the New Versioned API

Easier than you thought right? Now to check out what we've done just go to your browser and type in localhost:3000/api/v1/dog_parks and you'll see the dog parks returned in JSON format.

If that didn't work. Take a look at my folder structure and make sure it's the same as yours. If it's not exactly the same you might be getting an error. Alternatively, if you didn't put the proper namespace in routes.rb or name the modules correctly in the dog_parks_controller.rb file you could be getting other errors.

To add more versions all you'd need to do is create the routes in routes.rb and then repeat what we did in the api folder for other versions.

Other Versioning Methods

Like most things in web development, this isn't the only way to achieve versioning in an API. This just happened to be the simplest and easiest way to implement it. This way isn't what you'd call the preferred method but does work. I'll do a more advanced version of this post later and flesh out a more scalable option. The way we've done it in this post has a few shortcomings such as future maintenance issues because we include the version in the URL. In the more advanced post, we'll place the version in the HTTP Accept header.

I hope you enjoyed this post and found it helpful. Next, I'll be walking you through adding authentication to your API and finally creating an iOS application to consume it.

Thanks again! Auf Wiedersehen!