
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