Namespacing controllers in a Ruby on Rails application is a great way to isolate different features: invoicing, authentication, etc. It's also pretty simple to implement, so there are no reasons not to do it if you need it.
The initial state
Let's start with a sample controller named ProposalsController:
# app/controllers/proposals_controller.rb
class ProposalsController < ApplicationController
def index
# something cool is probably happening here
end
end
This file currently lives in app/controllers/proposals_controller.rb, and the routes are:
# routes.rb
resources :proposals, only: [:index]
Moving things up
Now let's say we want to move this controller into a module named Invoice. Here are the steps to follow to add a namespace.
1. Create the folder `app/controllers/invoice`
The first thing to do is create a new folder under app/controllers, named invoice.
2. Move the `proposals_controller.rb` file in the `invoice` folder
3. Add the namespace to the `ProposalsController`
This is done with the module keyword from Ruby that will encapsulate the ProposalsController class.
# app/controllers/invoice/proposals_controller.rb
module Invoice
class ProposalsController < ApplicationController
def index
# something cool is probably happening here
end
end
end
4. Add a scope or a namespace in the routes
For the change to routes.rb, we have two options, depending on how we want the URI path to be affected.
With this first solution, the generated path in the browser will be /invoice/proposals, and it will use the controller located at app/controllers/invoice/proposals_controller.rb.
# routes.rb
namespace :invoice do
resources :proposals, only: [:index]
end
This second solution will not add anything to the path. The proposals will be available at /proposals, and use the controller located at app/controllers/invoice/proposals_controller.rb.
# routes.rb
scope module: :invoice do
resources :proposals, only: [:index]
end
The End
That's it, let me know if you have any comments!

