CRUD in Ruby
Published: 2022-11-28 19:49:07

  This post goes over how to create routes in Ruby-Sinatra that respond to fetch requests, post requests, patch requests, and delete requests. In order for Ruby to act as the backend server and respond to requests from the frontend, one must have installed the needed dependencies, created necessary migrations, created seed data, set up models accurately, and created CRUD routes. 

## Install Necessary Dependencies 

  In order to install necessary depending for ActiveRecord and Sinatra to work, run `bundle install` in the terminal. 

## Create Migrations

  In order to create a migration, run `bundle exec rake db:create_migration NAME=create_<Name of migration>`. 
For example, In order to create a migration for a model named Review run `bundle exec rake db:create_migration NAME=create_reviews`. To create a migration for a model named Restaurant, run `bundle exec rake db:create_migration NAME=create_restaurants`

  This will create a migration file in the db folder. In the newly create migration file, one can create a table with specific attributes. 

  For example, we can create the following table in db/migrate/20221114231536_create_reviews.rb:

```
class CreateReviews < ActiveRecord::Migration[6.1]
  def change
    create_table :reviews do |t|
      t.string :username
      t.string :date
      t.integer :rating 
      t.string :review
      t.belongs_to :restaurant
    end
  end
end
```

  This table contains a username which takes a string, a date which takes a string, a rating which takes an integer, a review which takes a string, and a foreign key for model Restaurant.

we can create the following table in db/migrate/20221114231542_create_restaurants.rb:

```
class CreateRestaurants < ActiveRecord::Migration[6.1]
  def change
    create_table :restaurants do |t|
      t.string :name
      t.string :location
     end
  end
end
```
This table contains attributes name and location both of which take a string.


## Create Seed Data

  After creating all necessary migrations, the next step is to create seed data in db/seeds.rb. Following is an example of some seed data.

```
//create seed data for 
Snooze = Restaurant.create(name: "Snooze, an A.M. Eatery", location: "3940 5th Ave San Diego, CA 92103")
 
Din_Tai = Restaurant.create(name: "Din Tai Fung",location: "4301 La Jolla Village Dr Bldg P Unit 2000 San Diego, CA 92122")

//Review belongs to Snooze as shown under restaurant attribute
Review.create(username: "Camille Jones", date: "10/5/2021", rating: 5, review: "Very good breakfast items. We got the French toast and the shrimp and grits and the eggs benedict. I highly recommend this place and the staff was very attentive.", restaurant: Snooze)

//Review belongs to Din_Tai as shown under restaurant attribute
Review.create(username: "Camille Jones", date: "07/25/2022", rating: 5, review: "Created this account just to write this review because the service was EXCEPTIONAL :)We are very excited to go back again !", restaurant: Din_Tai)


```

  In the example above, we create seed data for Restaurant first. We then use the Restaurant data in the Review data for the restaurant attribute to specify the relationship between a Review and a Restaurant (in other words, we specify which Review belongs to which restaurant).

## Creating Models

  For the purposes of this post, A restaurant has many reviews and a review belongs to a restaurant. We can specify this relationship in app/restaurant.rb and app/review.rb.

```
// app/restaurant.rb

class Restaurant < ActiveRecord::Base
    has_many :reviews
end
```

```
// app/review.rb
class Review < ActiveRecord::Base
    belongs_to :restaurant
end
```

## Set up CRUD responses (JSON format)

After installing dependencies, creating migrations, creating seed data, and setting up models, we can finally define our CRUD routes in app/controllers/application_controller.rb responsible for responding to CRUD requests.

- Creating a Get (Read) route for all Restaurant data and its associate Reviews

The following code will do all of the following:

- respond with all Restaurant instances in json format 

```
get "/restaurants" do
  restaurants = Restaurant.all
  restaurants.to_json
end
```

- respond with all Restaurant instances in json format including its associate reviews

```
get "/restaurants" do
  restaurants = Restaurant.all
  restaurants.to_json(include: :reviews)
end
```

- Creating a Post (Create) route

- In order to create a new Review, the post route will look like the following:

```
post '/review' do
  review = Review.create(
    username: params[:username],
    date: params[:date],
    review: params[:review],
    rating: params[:rating],
    restaurant_id: params[:restaurant_id]
  )
end
```

- Creating a Delete route

- In order to delete a review, create a delete route. Add the /:id in the path and use .find() method to find a review by its id so that specific review can be deleted. 
```
delete '/review/:id' do
  review = Review.find(params[:id])
  review.destroy
  review.to_json
end
```

- Creating a Patch (Update) route
 
In order to respond to a Patch request, create a patch route. Add "/:id" to the path and use .find() method to find a review by its id so it can be updated.
```
patch '/review/:id' do
  review = Review.find(params[:id])
  review.update(
    date: params[:date],
    username: params[:username],
    rating: params[:rating],
    review: params[:review]
  )
  review.to_json
end
```