Clean up your routes with Sinatra::Namespace

Wed Jul 20 15:09:54 2016 Zachary Scott mail@zzak.io

After fighting with Sinatra::Namespace for a few weeks, the build is finally green!

Since then, I've added some documentation for writing your Sinatra routes in a modular fashion and wanted to share that here too.

Thanks goes out to @dkobia for the inspiration and everyone who helped get the Sinatra::Namespace specs green, including:

It was a herculean effort, and wouldn't be possible without these fine folks :)

A quick digression

So the reason we ran into all of this trouble initially, because Sinatra's router changed to use Mustermann.

As you may know, this change will take place in Sinatra 2.0.

However, the router changes broke mostly all of the previous router's private API which we were using for the Sinatra::Namespace extension.

Shame on us ;)

In any case, everything is fixed and green now and YAYY!!!

So you want modular routes

When I think of "modularizing" an application, it usually means splitting things up into actual modules.

You can do this too with your Sinatra routes!

In order to do this, we can use Sinatra's extension API to create an extension to put our namespaces!

First, let's create an extension.

Let's call the module Routes since it has all of our... routes. ;)

This module must define the registered(app) method in order to be used later.

Basically, when you "register" an extension, Sinatra will pass the app context and evaluate this block including anything you put in it.

In our case we're just going to define routes. Single responsibility principle.. or something.

require 'sinatra/base' # For creating Sinatra extensions
require 'sinatra/namespace' # To create namespaces

module Zomg # Keep everything under the same namespace for sanity

  module Routes # Define our "Routes" module

    # Don't forget to define this method!
    def self.registered(app)

      # First, register the Namespace extension
      app.register Sinatra::Namespace

      # This defines an `/api` namespace on the application
      app.namespace '/api' do
        get '/users' do
          # do something with `GET "/api/users"`
        end
      end

    end
  end

  # Lastly, register the extension to use in our app
  Sinatra.register Routes

end # Close the Zomg module definition

Usage

We can now use our Routes extension just like any other Sinatra extension:

module Zomg
  # Define our app class, we use modular app for this example
  class App < Sinatra::Base
    # this gives us all the namespaces we defined earlier
    register Routes

    get '/' do
      "Welcome to my application!"
    end
  end
end

Zomg::App.run! # Don't forget to start your app ;)

Phew! That was a mouthful.

I hope that helps you use Sinatra::Namespace in every way imaginable!

Including, but not limited to cleaning up and organizing your code into nicely housed namespaces ;)