Michael Anhari

Using namespaces to organize your Rails code base

A wall of shipping containers stacked in a grid.

Sometimes you want to group areas of your application under one roof. For example, let's say you're building a multisided marketplace or building a CMS as part of your application. Let's pretend we're doing the latter.

Without namespacing, all of your resources would live in app/models whether a part of the CMS or not. If we wanted to group the resources managed by the CMS portion of the application we could namespace them in a module.

Creating models under a namespace

The Rails generators support namespacing code using the namespace/resource pattern.

bin/rails generate model cms/article title:string body:text

This generates a Cms module at app/models/cms.rb that defines the table prefix for the namespace:

module Cms
  def self.table_name_prefix
    'cms_'
  end

The underlying table in PostgreSQL would be named cms_articles, and the model in app/models/cms/article.rb would look like the following:

module Cms
  class Article < ApplicationRecord
  end
end

Namespacing controllers and views

Let's say the resources for our CMS should be managed under the http://localhost:3000/cms path in the URI. The Rails router makes this easy.

# frozen_string_literal: true

Rails.application.routes.draw do
  namespace :cms do
    resources :articles
  end
end

and our controller would look something like this app/controllers/cms/articles.rb:

module Cms
  class ArticlesController < ApplicationController
    def index
      # code for /cms/articles here
    end
  end
end

and our corresponding views would live in app/views/cms/articles/index.html.erb

Conclusion

Namespacing our models has made a code base with several hundred models easier to navigate and reason about, and I think it is a pattern worth considering. Tomorrow we'll talk about setting up Rails to handle the acronyms in your codebase so that we can reference our CMS module as CMS instead of Cms.

Newsletter

I'm working on sending out a weekly newsletter. I'll make it as easy as possible to unsubscribe at any time.