RESTful Conventions in Rails
Tags: rails, ruby, crud, beginners
Published: 2022-04-15 00:40:23

RESTful routes fall into four general categories: Create, Read, Update, and Delete. They are commonly referred to as 'CRUD' actions. Almost all major websites use full CRUD so that users can interact with their databases.

To implement these four CRUD actions to a database, we combine each one of them with an HTTP verb like shown below.

- CREATE with POST
- READ with GET
- UPDATE with PATCH or PUT
- DELETE with DESTROY

For example, if we wanted to do full CRUD for birds.rb model, here is what it would look like in a Rails framework.

![Full CRUD with 5 RESTful Routes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/epwn27ezzo48nqriygcw.png)


## Creating RESTful Routes with Resources

To set up full CRUD actions in Rails, we first need to create some routes in routes.rb. We can do this by using Resources as shown below. 

```ruby
# config/routes.rb

Rails.application.routes.draw do
  resources :birds
end
```
If our application does not use all four CRUD actions, we can customize our routes to have only the actions that we need. For example, if our website is read only and we only need to make a GET request with index and show controller actions, then routes.rb will look like this.

```ruby
# config/routes.rb

Rails.application.routes.draw do
  resources :birds, only: [:index, :show]
end
```
It is considered good practice not to have routes that are not being used by out application. Therefore, using the above syntax to pick only the routes we need is important. There is also an option to list only the routes we don't use by replacing `only:` with `except:`.


## Quick set up of CRUD in Rails using Scaffold

Rails scaffolding is a quick way to generate some of the major pieces of a Rails application. If you want to create the models, views, controllers for a new resource in a single operation, you can use scaffolding as shown in the example below.

```
$ rails g scaffold Bird name:string species:string
```
Running the above code in the terminal will create multiple files for the Bird model including a controller that has built in full CRUD. However, it will set-up the file as if we are using Views for the front-end of or app. This could create some unnecessary files if we are using a front-end that is, for example, built using React.js.

## Set up of CRUD in Rails using Resource

To avoid the above issue of having unnecessary files for an app that is using a React.js as a front-end library, we can instead run the following code in the terminal.
 
```
$ rails g resource Bird name:string species:string
```

This will create multiple files that we need for the Bird model; however, the controller will not have the CRUD actions already built. So we will have to manually write the code needed for full CRUD as shown below. 

```ruby
# app/controllers/bird_controller.rb

class BirdsController < ApplicationController

#Error Handling
  rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_response

  # GET /birds (show all birds)
  def index
    birds = Bird.all
    render json: birds # renders data in JSON format
  end

  # POST /birds (create a new bird)
  def create
    bird = Bird.create(bird_params)
    render json: bird, status: :created
  end

  # GET /birds/:id (show a specific bird)
  def show
    bird = find_bird
    render json: bird
  end

  # PATCH /birds/:id (update a specific bird)
  def update
    bird = find_bird
    bird.update(bird_params)
    render json: bird
  end

  # DELETE /birds/:id (delete a specific bird)
  def destroy
    bird = find_bird
    bird.destroy
    head :no_content
  end

  private # code below this line is private (secure)

  def find_bird
    Bird.find(params[:id])
  end

  def bird_params
    params.permit(:name, :species, :likes)
  end

# Error handling
  def render_not_found_response
    render json: { error: "Bird not found" }, status: :not_found
  end

end
```

## Good Practices

- Use strong params by using the private method
- Have code that will handle errors
- Don't have unused routes in routes.rb
- Leave comments explaining what the code is doing

## Resources
[Rails Guides](https://guides.rubyonrails.org/v3.2/getting_started.html)