Back
Chapters

Rails routing in depth

Search icon
Search Book
⌘K

Namespaces in Rails

In the previous section, Updating default response format, we have mentioned that usually we use the api/v1 namespace to denote the API routes in our app.

The reason we haven't used this approach in our application is because namespaces is an advanced concept to be introduced at the beginning of the book and would distract the reader from the flow of the book.

Namespaces are used to organize a group of controllers. For example, you may wish to organize a group of controllers that are only accessible by the admin of your app, under the Admin:: namespace. You can do so by placing your controllers in app/controllers/admin directory and editing your routes.rb file like so:

1namespace :admin do
2  resources :articles
3end

You would need to add the namespace to your controllers:

1module Admin
2  class ArticlesController < ApplicationController
3    # Controller action code...
4  end
5end

This will create Admin::ArticlesController which will respond to the RESTful routes under /admin/articles with the prefix admin to the path method used to identify the resources like so:

PrefixVERBURI PatternController#Action
admin_articlesGET/admin/articlesadmin/articles#index
POST/admin/articlesadmin/articles#create
admin_new_articleGET/admin/articles/newadmin/articles#new
admin_edit_articleGET/admin/articles/:idadmin/articles#edit
admin_articleGET/admin/articles/:idadmin/articles#show
PATCH/admin/articles/:idadmin/articles#update
PUT/admin/articles/:idadmin/articles#update
DELETE/admin/articles/:idadmin/articles#destroy

You can also add a namespace to classes using a scope resolution operation or :: like so:

1class Admin::ArticlesController < ApplicationController
2  # Controller action code...
3end

Using the :: operator in the above code means, ArticlesController in the namespace of Admin.

Namespaces are a handy way to organize our routes, but it is not very flexible. If we want a more customizable solution then we can use scopes instead.

Routing with scopes

Scopes are a bit more complex but the advantage they provide is that they give us more options to fine-tune exactly what we want to achieve.

The scope method accepts three options; module, path and as.

The module option

module option lets us define in which module the controller for the embedded resources will reside in.

For example the for the following snippet:

1scope module: 'admin' do
2  resources :articles
3end

Rails will look for the controllers for /articles route inside the Admin:: module. Thus rails will generate the following routes:

PrefixVERBURI PatternController#Action
articlesGET/articlesadmin/articles#index
POST/articlesadmin/articles#create
new_articleGET/articles/newadmin/articles#new
edit_articleGET/articles/:idadmin/articles#edit
articleGET/articles/:idadmin/articles#show
PATCH/articles/:idadmin/articles#update
PUT/articles/:idadmin/articles#update
DELETE/articles/:idadmin/articles#destroy

The path option

path allows us to set the prefix that will appear in the URI, before the resource name.

For example the following snippet would add the prefix /admin to articles route:

1scope  path: 'admin' do
2  resources :articles
3end

The above snippet would generate the following routes:

PrefixVERBURI PatternController#Action
articlesGET/admin/articlesarticles#index
POST/admin/articlesarticles#create
new_articleGET/admin/articles/newarticles#new
edit_articleGET/admin/articles/:idarticles#edit
articleGET/admin/articles/:idarticles#show
PATCH/admin/articles/:idarticles#update
PUT/admin/articles/:idarticles#update
DELETE/admin/articles/:idarticles#destroy

So while the URI pattern has the prefix admin to it, the controller actions and path name prefixes remain unchanged.

The above snippet is similar to using scope without any options specified, like so:

1scope :admin do
2  resources :articles
3end

The as option

The as can be used to change the name of the path method used to identify the resources by adding the supplied value as a prefix.

For example, the following snippet will add admin as a prefix for the path methods for the articles resource:

1scope as: 'admin' do
2  resources :articles
3end

The above snippet would add the prefix admin for the path method and generate the following routes:

PrefixVERBURI PatternController#Action
admin_articlesGET/articlesarticles#index
POST/articlesarticles#create
admin_new_articleGET/articles/newarticles#new
admin_edit_articleGET/articles/:idarticles#edit
admin_articleGET/articles/:idarticles#show
PATCH/articles/:idarticles#update
PUT/articles/:idarticles#update
DELETE/articles/:idarticles#destroy

As we can see, the scope method allows us to define our routes in a more customized way, allowing us to define specific module, path and as options.

Scope vs Namespace

You might be wondering what is the difference between the scope and namespace method, since both methods manipulate how the restful routes for a resource are generated in Rails.

The major difference between the two methods is the value of the module, path and as options.

While in the scope method the options have no default value and have no effect unless specified, in the namespace method block the scope will automatically add the same value for as, module and path options.

In a way, namespace is a shorthand for writing a scope with all three options being set to the same value.

For example, in the following snippet, the namespace will add the admin prefix to the path, module and the path helper method:

1namespace "admin" do
2  resources :articles
3end

The above snippet is the same as:

1scope "/admin", as: "admin", module: "admin" do
2  resources :articles
3end

Both the snippets will generate the routes for the resource articles like so:

PrefixVERBURI PatternController#Action
admin_articlesGET/admin/articlesadmin/articles#index
POST/admin/articlesadmin/articles#create
admin_new_articleGET/admin/articles/newadmin/articles#new
admin_edit_articleGET/admin/articles/:idadmin/articles#edit
admin_articleGET/admin/articles/:idadmin/articles#show
PATCH/admin/articles/:idadmin/articles#update
PUT/admin/articles/:idadmin/articles#update
DELETE/admin/articles/:idadmin/articles#destroy

This is an in-depth chapter and hence you do not need to commit any of these changes.