What’s in a name?

Namespacing and Versioning your Rails API

Photo by Jon Tyson on Unsplash

When we learn to code, many of us tend to adopt practices that were taught to us without immediately understanding the details of the “why”. I mean, we get a general idea of what’s going on, of course, but a lot of times we’re focused on getting a handle on how to use some bit of code and making sure that bit of code interacts with other bits of code. We want to move on to learn something new in order to put together a deliverable, something that we can include in a portfolio, something that we can “show”.

One of the things that I didn’t question too deeply has to do with a Rails API (I know, I’m writing about something that’s NOT Javascript or React…SHOCKING).

What is namespacing?

The more features you start adding to your Rails application, the more numerous and complex your app directory will become. This no doubt leads to problems navigating and even understanding the app. An effective approach to handle this is to namespace your app (and in particular we’re talking about controllers here), which essentially creates subfolders; while you don’t cut down on your actual number of files, namespacing leads to a much more efficient organization of your files and an easier time understanding what’s going on.

One common example is needing to limit a number of controllers to a select administrative route. You would place these controllers in the app/controllers/admin directory, with a hypothetical invoices_controller.rb file looking like this:

class Admin::InvoicesController < ApplicationController   def index
// some code here to do stuff

Notice the Admin::, which is the syntax for creating the namespaced class. Your routes.rb folder would look something like this:

namespace :admin do
resources :articles

For the Admin::ArticlesController, these routes would be created:

From https://guides.rubyonrails.org/routing.html

Besides creating dedicated admin routes, another common reason to use namespacing is to separate out any routes you are using as api endpoints. Many of us use a Rails backend as an API and it is important to separate out API routes from regular routes in your app, just from an organizational perspective. If you think about it, different rules apply to API endpoints; you can’t just make major changes, as you could break external applications (if someone is using your API endpoints) or you could break your own front end if it is making calls to those endpoints.

Yet another reason to use namespacing is to be able to your Rails API.

What is versioning?

Essentially, versioning is actually what it sounds like…you’re creating different of your API. Or, better, you’re creating the of having different versions of your API.

As I mentioned above, whenever you are working with API endpoints, any major changes that you make have the potential to break an app (either your own or any using your endpoints). You want to avoid making breaking changes, obviously. However, sometimes these are inevitable, as when you are growing your app or need to add some important functionality.

So what do you do? When you do have to make a change, the version system helps you do that. No matter how small your app is initially, it’s always a good idea to start with versioning. By convention the first version of an API is denoted with v1. And this is a nested namespace within the api namespace.

Here is an example of controller that is api namespaced with versioning:

Doubly namespaced users_controller file for a version 1 api endpoint.

The users_controller.rb file is nested in the api/v1 directory.

If we take a look at the routes.rb folder, we see this:

So we would hit this endpoint via api/v1/trips.

Ok, so now that we have a version 1, we build that out, test some functionality and great, things are working! But let’s say a client requests some functionality that we haven’t built in, or as we’re testing out our app we see we don’t like something and need to change it. Because we’ve set up versioning, we can create a version 2 of our API, called v2 (surprise), and make our change without affecting the functionality of our v1.

We (and anyone else using our API) can still hit the api/v1/trips endpoint without any interruption in service. Once we’ve completed our v2, we can mark the v1 endpoint as deprecated in our v1 API docs and then get users moved over to v2. The new endpoint will then simply be api/v2/trips.

Using namespacing and versioning does not add much more work at the start of your project at all…but could save a BIG headache down the line. So I think it’s a good idea to go ahead and create your Rails app with these options from the beginning.

Happy coding!