1. Single Route Resources
Single route resources are a straightforward way to define routes for a resource with only one route. Let's create a route for a "book" resource using Rails resources method:
# config/routes.rb
resources :books, only: [:show]
In this example, we've defined a single "show" route for the "books" resource, which maps to the "BooksController#show" action.
But if we want all the whole REST routes for books, we use this.
resources :books
2. Nested Routes
Nested routes in Ruby on Rails involve physically nesting one resource
inside a block supplied to another resource
in the routes file. This allows for URLs like '/books/2/chapters/10', where chapters are nested under books.
Nested routes allow you to express hierarchical relationships between resources. For instance, if you have a 'Chapter' resource that belongs to a 'Book,' you can set up nested routes like this:
resources :books do
resources :chapters
end
of course we have defined associations between models
# app/models/book.rb
class Book < ApplicationRecord
has_many :chapters
end
and
# app/models/chapter.rb
class Chapter < ApplicationRecord
belongs_to :book
end
3. Member and Collection Routes
In Ruby on Rails, when defining routes for a resource, you have the flexibility to add custom actions using member and collection routes. These two types of routes serve different purposes and are suitable for distinct scenarios.
Suppose you have a "books" resource and want to add a custom "highlight" action for a specific book. You can define a member route like this:
resources :books do
member do
get 'highlight'
end
end
Now, you can access the "highlight" action for a specific book using a URL like "/books/1/highlight," where "1" represents the book's ID.
Suppose you want to add a custom "search" action that searches for books across the entire collection. You can define a collection route like this:
resources :books do
collection do
get 'search'
end
end
Now, you can perform a search action that applies to all books using a URL like "/books/search."
Note that Member routes typically map to actions that perform operations on a single member or instance of a resource.
Collection routes map to actions that involve the entire collection of a resource.
4. Adding Non-RESTful Routes
Sometimes, you may need routes that don't follow RESTful conventions. For example, let's create a custom route for marking a book as a favorite:
# config/routes.rb
resources :books do
post 'favorite', on: :member
end
Below are other different approaches to implement a non-RESTful route for this scenario:
Using the match Method
This approach allows you to specify the HTTP method (e.g., POST) and the controller action to be invoked. The :as option allows you to create a named route helper method, such as favorite_book_path, for generating URLs to this route.
match '/books/:id/favorite', to: 'books#favorite', via: :post, as: :favorite_book
Using post Method with on: Option
By specifying the on: option within the post method in your routes file. This approach explicitly states that the "favorite" route is a member route, and it maps to the favorite action in the BooksController
resources :books do
post 'favorite', on: :member, to: 'books#favorite'
end
Using Custom Named Routes
With this approach, you have flexibility in naming the route and can use the generated named route helper (e.g., mark_favorite_path or custom_favorite_route_path) to generate URLs for this non-RESTful action.
post '/books/:id/favorite', to: 'books#favorite', as: :mark_favorite
# OR, using a custom helper method name
post '/books/:id/favorite', to: 'books#favorite', as: :custom_favorite_route
Now, you can mark a book as a favorite by making a POST request to "/books/1/favorite."
5. Redirects
In Rails, you can define redirects easily in your routes file. Suppose you want to redirect "/old_path" to "/new_path":
# config/routes.rb
get '/old_path', to: redirect('/new_path')
This code will redirect any request to "/old_path" to "/new_path."
6. Wildcard Routes
Wildcard routes are a powerful tool for handling dynamic URLs. Suppose you want to capture all requests to "/books/*" and route them to a specific controller action:
get '/books/*path', to: 'books#show'
With this wildcard route, you can capture various book-related paths and route them to the "BooksController#show" action.
7. Some Anti-Patterns, or Please Dont
Overuse of Custom Routes
Anti-Pattern: Defining excessive custom routes for every controller action
resources :books do
get 'custom_action_1', on: :member
post 'custom_action_2', on: :collection
put 'custom_action_3', on: :member
# ... more custom actions ...
end
Instead, it's recommended to use RESTful routes whenever possible and resort to custom routes only when necessary.
Verbosity in Named Routes:
Anti-Pattern: Using overly verbose names for named routes.
# BAD
get '/books/:id/edit_book', to: 'books#edit', as: :edit_book_action
# GOOD
get '/books/:id/edit', to: 'books#edit', as: :edit_book
Unused or Dead Routes
Anti-Pattern: Defining routes that are no longer used in the application.
get '/unused_route', to: 'unused#action'
Such routes should be removed to maintain a clean and maintainable route configuration
Complex Route Constraints
Anti-Pattern: Overcomplicating routes with complex constraints.
get '/books/:id', to: 'books#show', constraints: { id: /\d{3}/ }
Keep route constraints simple and understandable, and use them sparingly.
Lack of RESTful Structure with RESTful actions
Anti-Pattern: Creating routes that don't adhere to RESTful principles when these are for RESTful action in the first place.
# BAD because show is a RESTful action
get '/books/show_book/:id', to: 'books#show'
# Better
resources :books, only: [:show]
Inconsistent Route Naming
Anti-Pattern: Using inconsistent naming conventions for routes.
# Wrong
get '/books/show_book/:id', to: 'books#show', as: :display_single_book
# Best
resources :books, only: [:show]
Consistency in naming conventions makes the codebase more understandable
By avoiding these anti-patterns and following Rails' conventions for routing definitions, you can maintain a clean and maintainable routing configuration in your Ruby on Rails application, making it easier for developers to understand and work with the code.
Conclusion:
Mastering routing in Ruby on Rails is essential for building robust web applications. In this concise guide, we've covered single route resources, nested routes, member and collection routes, non-RESTful routes, redirects, and wildcard routes, and anti-patterns, each of these illustrated with code examples. By understanding these routing concepts, you'll be better equipped to handle complex routing scenarios in your Rails applications.
Top comments (0)