I see many project get nested routes wrong. Developers do not use Ruby modules to reflect the relationship between the parent and children nesting of controllers. Here is an example of the wrong way (IMHO). Let’s say we have a customer and the customer has_many orders
and has_one profile
. Some developers will represent it like this.
/customers
path in the file app/controllers/customers_controller.rb
class CustomersController < ApplicationController
def index
...
end
end
/customer/:id/orders
path in the file app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def index
...
end
end
/customer/:id/profile
path in the file app/controllers/profile_controller.rb
class ProfileController < ApplicationController
def show
...
end
end
With a config/routes.rb
resources :customer do
resources :orders
resource :profile, only: [:edit, :update]
end
While this gives us the correct url structure, a better approach is to use Ruby’s modules to represent the relationship.
Here is an example of what I consider the correct approach:
/customers
path in the file app/controllers/customers_controller.rb
class CustomersController < ApplicationController
def index
...
end
end
/customer/:id/orders
path in the file app/controllers/customers/orders_controller.rb
module Customers
class OrdersController < ApplicationController
def index
# ...
end
end
end
/customer/:id/profile
path in the file app/controllers/customers/profile_controller.rb
module Customers
class ProfileController < ApplicationController
def show
# ...
end
end
end
One way to set up the routes file is as follows:
resources :customer do
resources :orders, controller: 'customers/orders'
resource :profile, controller: 'customers/profile'
end
However, the controller
options looks a little repetitive. A more elegant way is to use the scope
command:
resources :customer do
scope module: 'customers' do
resources :orders
resource :profile
end
end
Now our files and the Ruby class names reflect their true relationships. Instead of:
app/controllers/customers_controller.rb
app/controllers/orders_controller.rb
app/controllers/profile_controller.rb
We have:
app/controllers/customers_controller.rb
app/controllers/customers/orders_controller.rb
app/controllers/customers/profile_controller.rb