You can list all the routes in your Rails application by running the
Imagine you're building a course platform, where each course has multiple lessons.
- Each lesson is associated with a particular course.
- Whenever you perform an operation on a lesson (create, read, update, delete), you're working in the context of an existing course.
- When working with a lesson, you're really working with a course-lesson pair.
Basically, the lesson resource is nested under the course resource. In a Rails routing file, you can represent the relationship between a course and its lessons as follows:
# config/routes.rb
resources :courses do
resources :lessons
end
This instructs the Rails router to generate regular resourceful routes for the course resource, and generate nested, resourceful routes for the lesson resource. Let's check the routes generated for the lesson resource.
$ 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
As you can see, all lesson route URLs are prefixed with /courses/:course_id
, meaning each lesson is nested under a particular course whose ID can be accessed by params[:course_id]
.
In addition, all lesson route names are prefixed with "course", providing clear and obvious named route helpers, such as: course_lessons_path
and new_course_lesson_path
. When using a named route helper, you must provide a valid instance of the Course
resource class under which this lesson is nested. For example,
link_to "Add New Lesson", new_course_lesson_path(course)
link_to "Edit Lesson", edit_course_lesson_path(course, lesson)
Given a course with ID 5 and a lesson with ID 10, the URL for that particular lesson will look like: /courses/5/lessons/10
, following the structure: /courses/{course_id}/lessons/{id}
. The controller can access the course id and lesson id using params[:course_id]
and params[:id]
.
Namespacing a Nested Route
In the above example, the lessons resource will use the LessonsController
class (located under the app/controllers
directory). If you want to have the LessonsController
class nested under the app/controllers/courses
directory instead, pass the :module
option as follows:
# config/routes.rb
resources :courses do
resources :lessons, module: "courses"
end
Let's inspect the routes generated by the above configuration.
bin/rails routes -g lesson
Prefix Verb URI Pattern Controller#Action
course_lessons GET /courses/:course_id/lessons(.:format) courses/lessons#index
POST /courses/:course_id/lessons(.:format) courses/lessons#create
new_course_lesson GET /courses/:course_id/lessons/new(.:format) courses/lessons#new
edit_course_lesson GET /courses/:course_id/lessons/:id/edit(.:format) courses/lessons#edit
course_lesson GET /courses/:course_id/lessons/:id(.:format) courses/lessons#show
PATCH /courses/:course_id/lessons/:id(.:format) courses/lessons#update
PUT /courses/:course_id/lessons/:id(.:format) courses/lessons#update
DELETE /courses/:course_id/lessons/:id(.:format) courses/lessons#destroy
Notice the only column that changed was the Controller#Action
column. It's now using the Courses::LessonsController
class nested under the app/controllers/courses/lessons_controller.rb
file.
A word of caution: resources should never be nested more than 1 level deep. Why? Check out this excellent post from Jamis Buck.