Routing in Rails
Tags: ruby, rails, api, beginners
Published: 2023-07-10 21:36:43

## Introduction
Routing is the means of navigating one or more networks. In full-stack Rails applications one routing system handles the full request/response cycle. In Rails API applications, separate routing systems handle the client and server. Routing is simplified when using RESTful conventions, and Rails provides a `resources` macro to further streamline the process. Custom routes fill the gaps conventions leave. 

## Rails Route Components
A Rails route has four components: verb, path, controller, and action. The syntax is as follows and written in the config/routes.rb file of a Rails application.
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  verb '/path' to: 'controller#action'

end
```
### Verb
The first component of a route is an HTTP verb: GET, POST, PUT, PATCH, DELETE. Verbs communicate the type of request a client is sending to the server. 

### Path
The second route component is the path. A path communicates the resource endpoint the client request is accessing. In RESTful routes the path always include a plural endpoint: `/users`, `/students`, `/goals`. RESTful endpoints can also be followed with an id: `/users/:id`.

### Controller
The third component is the controller. It follows the `to:` key and directs the request to the appropriate controller. In RESTful routes the endpoint and the controller are typically the same: `'/students' to: 'students#action'`. Just as RESTful endpoints are plural, controller names are plural as well.

### Action
The fourth and final route component is the action. Actions are basically methods for controllers. This final element of the route sends the request to the appropriate action within the controller. In RESTful routes the action is associated with the HTTP verb.
```rb
# app/controllers/model_controller.rb
class ModelController < ApplicationController

  def action
    # response logic
  end 

end
```

## RESTful Routes
REST is short for **RE**presational **S**tate **T**ransfer. Developed by Roy Fielding in 2000, REST is the standard for API communication. Using RESTful conventions simplifies the routing process and reduces the number of decisions that need to be made. It also makes the API accessible to any other developers.

### CRUD
CRUD stands for **C**reate, **R**ead, **U**pdate, **D**elete. These are the four ways data is manipulated on the web. Each of these actions has an HTTP verb associated with it: GET, POST, PUT, PATCH, DELETE. Rails also has corresponding RESTful actions: index, create, show, update and destroy.
```
CRUD         HTTP           RAILS
-----------------------------------------
Create       POST           #create 
Read         GET            #index, #show
Update       PUT, PATCH     #update
Delete       DELETE         #destroy
```

#### Index
The `index` action is associated with the GET verb and used to return all instances of a class. 
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  get '/books' to: 'books#index'

end

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  
  def index
    books = Book.all
    render json: books
  end

end
```
#### Create
The `create` action is associated with the POST verb and used to create a new instance of a class.
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  post '/books' to: 'books#create'

end

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  
  def create
    book = Book.create(params)
    render json: book, status: :created
  end

end
```
#### Show
The `show` action is associated with the GET verb and used to return a specific instance of a class. The route must include an `:id` after the endpoint.
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  get '/books/:id' to: 'books#show'

end

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  
  def show
    book = Book.find(params[:id])
    render json: book
  end

end
```
#### Update
The `update` action is associated with PATCH and PUT verbs and used to update a specific instance of a class. The route must include an `:id` after the endpoint.
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  patch '/books/:id' to: 'books#update'
  put '/books/:id' to: 'books#update'

end

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  
  def update
    book = Book.find(params[:id])
    book.update(params)
    render json: book, status: :accepted
  end

end
```
#### Destroy
The `destroy` action is associated with the DELETE verb and used to destroy a specific instance of a class. The route must include an `:id` after the endpoint.
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  delete '/books/:id' to: 'books#destroy'

end

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  
  def destroy
    book = Book.find(params[:id])
    book.destroy
    render :no_content
  end

end
```
### Resources
Let's combine all the previous examples to see the routes and controller files when all RESTful routes are in use.
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  get '/books' to: 'books#index'
  post '/books' to: 'books#create'
  get '/books/:id' to: 'books#show'
  patch '/books/:id' to: 'books#update'
  put '/books/:id' to: 'books#update'
  delete '/books/:id' to: 'books#destroy'

end

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  def index
    books = Book.all
    render json: books
  end

  def create
    book = Book.create(params)
    render json: book, status: :created
  end

  def show
    book = Book.find(params[:id])
    render json: book
  end

  def update
    book = Book.find(params[:id])
    book.update(params)
    render json: book, status: :accepted
  end

  def destroy
    book = Book.find(params[:id])
    book.destroy
    render :no_content
  end
end
```
That routes file is starting to look pretty lengthy and it only has routes for one resource. Imagine managing an app with 7 or 8 resources. Rails to the rescue! Rails has a `resources` macro which creates RESTful routes for all CRUD actions. 
```rb
# app/config/routes.rb
Rails.application.routes.draw do

  resources :books

end
```
So much better. Using `resources` not only cleans up and simplifies the code, it also prevents typos and syntax errors.

By default, `resources` creates seven routes for each resource. What happens when the controller only has one or two actions? The routes for the other actions have been created but will lead to routing error messages. To keep those routes from being created use the `only:` key.
```rb
resources :books, only: [:index, :show]
```

#### Nested Routes
The `resources` macro can be used in nested routes as well. Nested routes reflect the relationships between models. If an Author model `has_many :books`, routes to the books through the authors can be established as such:
```rb
resources :authors do
  resources :books, only: [:index, :show]
end
```
This declaration creates these nested routes:
```rb
get '/authors/:author_id/books' to: 'books#index'
get '/authors/:author_id/books/:id' to: 'books#show'
```
Nested routes should only be one level deep.

## Custom Routes
Custom routes follow the same format as RESTful routes. The only difference is there are no limitations of RESTful conventions. A good use-case for a custom route would be `/login` and `/logout`. These paths communicate useful information but they are not a resource in and of themselves. Since a sessions controller typically handles login and logout functionality, the routes could be setup as:
```rb
resources :sessions, only: [:create, :destroy]
```
or as custom routes:
```rb
post '/login' to: 'sessions#create'
delete '/logout' to: 'sessions#destroy'
```
Both routes work the same. The difference is on the client side. Fetching `/login` or `/logout` is really clear. While fetching `/sessions` is less clear.

## Conclusion
Routing in Rails is pretty straightforward whether RESTful, nested or custom. All routes have four components: verb, path, controller, and action. For a deeper dive check out the [docs](https://guides.rubyonrails.org/routing.html).
###
####
#####
######Credit
Photo by <a href="https://unsplash.com/@yogidan2012?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Daniele Levis Pelusi</a> on <a href="https://unsplash.com/photos/QSRXNv9kmus?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>