Shallow Nested Routes
In the previous post, we learned how nested resources work. Consider the following route configuration:
# config/routes.rb
resources :courses do
resources :lessons
end
It generates the following routes:
$ bin/rails routes -g lesson
Prefix Verb URI Pattern Controller#Action
course_lessons GET /courses/:course_id/lessons(.:format) lessons#index
POST /courses/:course_id/lessons(.:format) lessons#create
new_course_lesson GET /courses/:course_id/lessons/new(.:format) lessons#new
edit_course_lesson GET /courses/:course_id/lessons/:id/edit(.:format) lessons#edit
course_lesson GET /courses/:course_id/lessons/:id(.:format) lessons#show
PATCH /courses/:course_id/lessons/:id(.:format) lessons#update
PUT /courses/:course_id/lessons/:id(.:format) lessons#update
DELETE /courses/:course_id/lessons/:id(.:format) lessons#destroy
You must have noticed that the show
, edit
, update
, and destroy
routes for a lesson don't really need the course. They can exist on their own.
show
: Given a lesson id, show this lessonedit
: Given a lesson id, show the form to edit this lessonupdate
: Given a lesson id, update this lessondestroy
: Given a lesson id, delete this lesson
In contrast, the index
, create
, and new
routes for a lesson will always need a course, otherwise Rails won't know which course we're talking about.
index
: For which course we should show all the lessons?create
: Which course we should add this lesson to?new
: For which course we should add new lesson?
To address this, we could define our nested routes like this:
resources :courses do
resources :lessons, only: [:index, :new, :create]
end
resources :lessons, only: [:show, :edit, :update, :destroy]
However, Rails provides the shallow
option as a shortcut.
resources :courses do
resources :lessons, shallow: true
end
Shallow nesting strikes a balance between descriptive routes and deep nesting.
Let's review the generated routes.
$ bin/rails routes -g lesson
Prefix Verb URI Pattern Controller#Action
## Need a Course
course_lessons GET /courses/:course_id/lessons(.:format) lessons#index
POST /courses/:course_id/lessons(.:format) lessons#create
new_course_lesson GET /courses/:course_id/lessons/new(.:format) lessons#new
## Doesn't Need a Course
edit_lesson GET /lessons/:id/edit(.:format) lessons#edit
lesson GET /lessons/:id(.:format) lessons#show
PATCH /lessons/:id(.:format) lessons#update
PUT /lessons/:id(.:format) lessons#update
DELETE /lessons/:id(.:format) lessons#destroy
If you have multiple resources nested under a single parent resource, you can pass the shallow option to the parent.
resources :courses, shallow: true do
resources :lessons
resources :students
end
If you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. You can also subscribe to my blog to receive future posts via email.