Thank you Rails for the carry
Tags: api, rails, ruby, noob
Published: 2023-03-02 17:42:18

Hello all,


I've picked up Ruby recently in my bootcamp program. We initially started with the vanilla Ruby to build our backend. Much like vanilla JavaScript that I had learned previously, everything had to be code manually. 

Anyways, we had to utilize Sinatra (Domain Specific Language) to make use of ActiveRecord in Ruby to establish Object Relational Mapping (ORM) to use in our backend (API). It was such a tedious bits of work. It was a lot of typing the same thing over and over. 

And then we were introduced Rails.

From having to type these migration files out manually.

```Ruby
class CreateProducts < ActiveRecord::Migration[6.1]
  def change
    create_table :Products do |t|
      t.integer :farm_id
      t.string :name
      t.string :category
      t.string :description
      t.string :picture_link
      t.integer :price
      t.integer :stock
    end
  end
end
```

Into, typing these inside the terminal

```terminal
rails g migration product name category description picture_link price:integer stock:integer farm:belongs_to --no-test-framework
```

As an efficient (lazy) wannabe web app programmer that I am- this changes everything.

'Rails g' calls upon the generator method (you'll come to love this) pre-built into the rails to generation a migration file. The convention is as followed 'rails g migration' + 'name of the table' + 'columns (in which, if not specified data type, will all be considered by strings): data_type' and the '--no-test-framework' is to not interrupt any rspec (tests) files that were created (if you were in a class setting which provided you tests to guide you). 
**Also the 'belongs_to' is used to establish many-to-many relationship with another table. 

You can already see how much heavy lifting (typing) these generator methods will save you from. Oh yeah, did I mention there are more methods than just for creating migration?

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9jx346e1jdrwv4a1tiy.jpg)

> "YES, YOU CAN CREATE A WHOLE NEW API WITH COUPLE KEYSTROKES.
> THIS THING IS A MVC FRAMEWORK ON RUBY. BASICALLY RUBY ON STEROIDS. SO EASY TO USE IT'S SCARY." -me

First of all, I would make sure that you have ruby and rails installed properly. I would follow this tutorial (https://www.youtube.com/watch?v=fmyvWz5TUWg&t=1792s) since I won't pretend that I know how to fix your problem if something goes wrong with initial set up. 

Once everything is all set up. I would go into your terminal and direct to where you want this file/project to live in. (Yes, we are going to walkthrough how to make your own customizable API)

Start with,

```terminal
rails new my_api --api
```

Please Please Please don't use 'my_api' as your API name. Pick some other interesting name. Also don't forget '--api' at the end so rails doesn't generate all the other stuff you don't need. Even if you do it's nbd. Start over or play with the new stuff that comes with it.

Depending on how fast your computer is this step will take a (short) while. It also lists all the required gem into gemfiles. Might as well run in your terminal 'bundle install' when it's done generating everything.

```terminal
bundle install
```

Then you'll want to create some sort of seed data to fill your migration table. (pro tip: use Faker gem with loops)

Here's where the magic happens. Type, 

```terminal
rails g resource some_table name number:integer date:date 
```

WALLA

You have now generated migration file, model, controller, and routes in config/routes.rb!

Now you have basically a skeleton file that was generated by rails. But we're not done yet!

Always Always Always, make sure your migration file looks right and that there are no typos. This will snowball into a headache you do not want when you cannot access your API. 

Rails is especially picky with generator command with/without pluralization at the end. 

-rails g scaffold* (no pluralized name)
-rails g resource (no pluralized name)
-rails g migration (no pluralized name)
-rails g model (no pluralized name)
-rails g controller (**pluralized name**)

If I make a mistake here and you fail your test please let your instructor know that you tried to follow this noob guide and he was wrong.

Then go into your model and establish some validation to filter data that goes into your database. It can be as simple as

```Ruby
class Product < ApplicationRecord
  validates :name, :number, :date, presence: true
end
```
Just to make sure there are no empty data in any of the column going into your database.

Then go into your controller to set up how your API would receive the request from frontend and package what information to send back.

```Ruby
class ProductsController < ApplicationController
    before_action :find_product, only: [:show, :update, :destroy]

    def index
        products = Product.all
        render json: products, status: :ok
    end

    def show
        render json: @product, status: :ok
    end

    def create
        new_product = Product.create!(new_product_params)
        render json: new_product, status: :created
    end

    def update
        @product.update!(edit_product_params)
        render json: @product, status: :accepted
    end

    def destroy
        @product.destroy
        head :no_content
    end

    def fruits
        fruits = Product.all.where(category: "fruit")
        render json: fruits, status: :ok
    end

    def vegetables
        vegetables = Product.all.where(category: "vegetable")
        render json: vegetables, status: :ok
    end

    private

    def find_product
        @product = Product.find(params[:id])
    end

    def edit_product_params
        params.permit(:stock, :price, :description)
    end

    def new_product_params
        params.permit(:name, :category, :picture_link, :description, :price, :stock)
    end

end
```

This controller has full CRUD (create, read, update, destroy) and it is ready to listen to requests from frontend. 

Go ahead and fire up your rails server
```
rails s
```

Now go into one of your Chrome/Firefox (I recommend installing JSON reader on Chrome, Firefox can read JSON format by default) and type

```
localhost:3000/
```
You should see something like this.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmk6fp8jmklv3lfzovoh.PNG)

You can probably tell that this is not the right address..

Try in your web browser,

```
localhost:3000/products
```
or
```
localhost:3000/products/1
```

Right now we can't really test the other actions (create, update, or destroy) unless you have POSTMAN (**cough** my other posts **cough**).

But wait... did we ever establish the routes?

AHA, Rails is back at it again with heavy lifting. With the 'resource' generator method it also generates the default 6 methods (with --api) according to the RESTful routes.

Try in your terminal
```
rails routes
```
These are all default routes that comes with 'rails g resource'
```
     Prefix Verb   URI Pattern                                                                                       Controller#Action
                                products GET    /products(.:format)                                                                               products#index
                                         POST   /products(.:format)                                                                               products#create
                                 product GET    /products/:id(.:format)                                                                           products#show
                                         PATCH  /products/:id(.:format)                                                                           products#update
                                         PUT    /products/:id(.:format)                                                                           products#update
                                         DELETE /products/:id(.:format)                                                                           products#destroy
```
And if you go into your config/routes.rb

```Ruby
Rails.application.routes.draw do
  resources :products # this generates all the default routes
end
```
This is one of the ways Rails makes it easier for you to make your custom API.

*If you do 'rails g scaffold' it also create all the controller actions for you

Thanks for reading!