Ruby on Railsを基本からまとめてみた【APIを構築する方法】

## Rubyでできること(API)

Rubyの中でもRuby on Railsを活用することでAPIの実装ができる。APIは簡単に説明すると『サーバーに保存されているソフトウェアを別のシステムやアプリケーションに利用させること』。特定のルールでサーバーへとアクセスさせ、処理した結果をレスポンスすることを指す。

APIはGoogle社など大手企業が提供しているイメージがあるが、Rubyを活用すれば自分で実装でき、この実装したAPIを社内やスマホアプリなどと連携して利用できる。例えば、経費精算のAPIを作成しておけば、従業員がデータを入力するだけで関係システムに情報登録する仕組みが実装できる。

## API作成

①Railsプロジェクトを作る

```
mkdir <プロジェクト名>

rails new <プロジェクト名> --api
例：rails new secret_menu_api --api

cd <プロジェクト名>
```
②CORS（Cross Origin Resource Sharing）の有効化

CORSは、他の人があなたのAPIにアクセスすることを可能するので、APIへの不要なアクセスを防止するために、Railsは自動的にCORSを無効にします。新しく作成したRails APIのファイルエクスプローラで、次のディレクトリを展開してcors.rbファイルを開く。

```
config>initializers>cors.rb
```
8～16行目をアンコメントする。10行目で、以下のように、(origins 'example.com') を (origins'*') に変更します。

```
# in config>initializers>cors.rb
# lines 8-16

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resources '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
```

explorer' ファイルで、下にスクロールして Gemfile を開く。
gem 'rack-cors'のコメントを解除する。

```
# in Gemfile
gem 'rack-cors'
``` 
ターミナルでインストールする。

```
#in terminal
bundle install
```
③Rails gリソースコマンドでモデル、コントローラ、データベースマイグレーションテーブル、およびルートを作成

```
# in terminal
rails g resource Secret_menu_item
```
④シークレットメニュー項目の属性とデータ型を指定する

※ このAPIはシークレットメニューの項目に関する有用な情報を表示するように設計されているため、以下のように属性を設定することで、そのような情報を表示することができる。

○ シークレットメニューの項目名
○ シークレットメニューを提供しているレストランの名前
○ メニュー説明

```
# in db>migrate>202042720449_create_secret_menu_items.rb

class CreateSecretMenuItems < ActiveRecord::Migration[6.0]
  def change
    create_table :secret_menu_items do |t|
      t.string :menu_name
      t.string :restaurant_name
      t.string :menu_description
    end
  end
end
``` 
テーブルを移行する

```
# in your terminal

rails db:migrate
```
移行に成功すると、ターミナルに以下のように表示される。

```
# Message in your terminal

== 20200427020449 CreateSecretMenuItems: migrating =============================
-- create_table(:secret_menu_items)
   -> 0.0022s
== 20200427020449 CreateSecretMenuItems: migrated (0.0023s) ====================
```

dbディレクトリで、schema.rbを開き、このファイルがデータ構造を示していることを確認する。

```
# in db>schema.rb

ActiveRecord::Schema.define(version: 2020_05_03_161829) do

  create_table "secret_menu_items", force: :cascade do |t|
    t.string "menu_name"
    t.string "restaurant_name"
    t.string "menu_description"
  end
end
```
⑤ インデックス、表示、作成、更新、破棄のアクションを定義する

これで、APIは以下のことができるようになります。

○ Index：データベース内のメニューアイテムのインスタンスを表示する

○ Show: メニュー項目のインスタンスを反映する

○ Create：メニューのインスタンスを作成する

○ Update: 既存のメニュー項目のインスタンスを更新する

○ Delete：シークレットメニュー項目を削除する


secret_menu_intems_controller.rb をコピー＆ペーストする。

```
class SecretMenuItemsController < ApplicationController


    def index
        @secretMenuItems = SecretMenuItem.all
        render json: @secretMenuItems
    end

    def show
        @secretMenuItem = SecretMenuItem.find(params[:id])
        render json: @secretMenuItem
    end

    def create
        @secretMenuItem = SecretMenuItem.create(
            menu_name:params[:menu_name],
            restaurant_name:params[:restaurant_name],
            menu_description: params[:menu_description]
        )
        render json: @secretMenuItem
    end

def update
        @secretMenuItem = SecretMenuItem.find(params[:id])
        @secretMenuItem.update(
            menu_name:params[:menu_name],
            restaurant_name:params[:restaurant_name],
            menu_description: params[:menu_description]
        )
        render json: @secretMenuItem
    end

    def destroy
        @secretMenuItems = SecretMenuItem.all
        @secretMenuItem = SecretMenuItem.find(params[:id])
        @secretMenuItem.destroy
        render json: @secretMenuItems
    end
end
```

⑥index, show, create, update and destroyを作成する

ルートとは、クライアントサイドでHTTPリクエストを受け取り、そのリクエストを適切なアクションに転送するものを指し、これらを設定するには、route.rbにコピー＆ペーストする。

```
# in config>routes.rb

Rails.application.routes.draw do
  resources :secret_menu_items, only: [:index, :show, :create, :update, :destroy]
end
```
⑦データをシードする

データベースにシークレットメニュー項目のインスタンスを作成する。

```
# in db>seed.rb

menu1 = SecretMenuItem.create(menu_name: "Chipotle Nachos", restaurant_name: "Chipotle", menu_description:"Build a plate of nachos with all of your favorite fixings")
menu2 = SecretMenuItem.create(menu_name: "Starbucks butterbeer Frappuccino", restaurant_name: "Starbucks", menu_description:"Combine three pumps of toffee nut syrup and three pumps of caramel with a Crème Frappuccino base")
menu3 = SecretMenuItem.create(menu_name: "Skittles", restaurant_name: "Jamba Juice", menu_description:"A mixture of lemonade, lime sherbet, frozen yogurt, and strawberries")
 
Seed the date

# in your terminal
rails db:seed


Check if it was done correctly:

# in your terminal
rails c

# It will pull up a console
2.6.1 :002 >
```
SecretMenuItem.allと入力すると、シードされたシークレットメニューアイテムのすべてのインスタンスが抽出される。

```
# in your terminal

2.6.1 :002 > SecretMenuItem.all
   (0.5ms) SELECT sqlite_version(*)
  SecretMenuItem Load (0.2ms) SELECT "secret_menu_items".* FROM "secret_menu_items" LIMIT ? [["LIMIT", 11]]
 => #<ActiveRecord::Relation [#<SecretMenuItem id: 1, menu_name: "Chipotle Nachos", restaurant_name: "Chipotle", menu_description: "Build a plate of nachos with all of your favorite ...">, #< SecretMenuItem id: 2, menu_name: "Starbucks butterbeer Frappuccino", restaurant_name: "Starbucks", menu_description: "Combine three pumps of toffee nut syrup and three ...">, #<SecretMenuItem id: 3, menu_name: "Skittles", restaurant_name: "Jamba Juice", menu_description: "A mixture of lemonade, lime sherbet, frozen yogurt...">]>
```

すべてのインスタンスが表示されば、すべてのデータが正常にシードされたことになる。

## 参考サイト
[【2022最新】Rubyでできること7選！トレンドは？](https://www.anken-navi.jp/news/programming-language/ruby/ruby-possible-7/)
[How to create an API using Ruby on Rails](https://rootstack.com/en/blog/ruby-on-rails-api)