【初心者向け】RailsでAPI開発 Part.1

# これは何？
Ruby on Railsを活用してスマホアプリのサーバー側開発を行いたい初心者向けの記事です。

| No. | 目次 |
|:-:|:--|
| Part.1  | JSONで表示 |
| Part.2  | 認証 |
| Part.3  | 認可 |
| Part.4  | セキュリティ |
| Part.5  | テスト |

# 対象者
- ProgateのRuby on Railsは理解している。
- Rails Tutorialもだいたい理解している。
- ウェブアプリケーションは簡単なものを作ったことがある。
- でも、スマホアプリのサーバーサイドは開発したことない方

# バージョン
- Ruby
    - 2.4.0
- Rails
    - 5.2.2
- MySQL
    - mysql  Ver 14.14 Distrib 5.7.23, for osx10.13 (x86_64) using  EditLine wrapper

# WebAPIの基礎
下記の記事にざっくりとした概要は記述しています。
https://qiita.com/jiggaman0412/items/d3492fd4f40f901282cc

# 今回の設計
## ▼ 概要図
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180679/e1265017-8000-e031-b7b0-ac9fb530499d.png)

今回は、クライアントは用意せず、コンソールから `curl` コマンドを直接叩いて出力を確認する。

## ▼ 使用するGemなど
- 認証
    - 自前のToken
- 認可
    - Pundit
- 攻撃対策
    - Rack-Attack
- 制限
    - Rack-Cors
- JSON変換
    - Active-Model-Serializers
- サンプルデータ作成
    - faker

バージョニングはV1だけ用意する。

## ▼ DB構成
- User
    - name
    - email
    - token
- Book
    - title
    - user_id

# 手順
## ① APIの下地を整える
```text:Terminal
bundle exec rails new api-sample --api -d mysql
```

```text:Gemfile
gem 'active_model_serializers`
gem 'faker'
```

```text:Terminal
bundle install
```

## ② Userデータの出力準備
```text:Terminal
bundle exec rails g model User name:string email:string token:string
bundle exec rails db:create
bundle exec rails db:migrate
bundle exec rails g controller Users
bundle exec rails g serializer User
```

```ruby:config/routes.rb
resources :users, only: [:show]
```

```ruby:app/controllers/users_controller.rb
before_action :set_user, only: [:show]

def show
 render json: @user, adapter: :json
end

private
def set_user
 @user = User.find(params[:id])
end
```

```ruby:app/serializers/user_serializer.rb
attributes :id, :name, :email, :token
```

## ③ Userデータの出力
```ruby:db/seeds.rb
100.times do
 User.create(
  name: Faker::Name.unique.name,
  email: Faker::Internet.unique.email,
  token: SecureRandom.base64(30)
 )
end
```

```text:curl
curl -X GET http://localhost:3000/users/1
curl -X GET http://localhost:3000/users/100
```

これで結果が出力されてくればとりあえずOK。

## ④ Bookデータの作成と表示
```text:terminal
bundle exec rails g model Book title:string user:references
bundle exec rails db:create
bundle exec rails db:migrate
bundle exec rails g controller Books
bundle exec rails g serializer Book
```

```ruby:db/seed.rb
users = (1..100).map do
 User.create(
  name: Faker::Name.unique.name,
  email: Faker::Internet.unique.email,
  token: SecureRandom.base64(30)
 )
end

100.times do
 Book.create(
  title: Faker::Book.title,
  user: users.sample
 )
end
```

```text:terminal
bundle exec rails g db:seed
```

```ruby:routes.rb
..
resources :books, only: [:index, :show]
```

```ruby:app/controllers/books_controller.rb
before_action :set_book, only: [:show]

def show
 render json: @book, adapter: :json
end

private
def set_book
 @book = Book.find(params[:id])
end
```

```ruby:app/models/user.rb
has_many :books
```

```ruby:app/models/book.rb
belongs_to :user
```

```ruby:app/serializers/user_serializer.rb
attributes :id, :name, :email, :token, :books
```

```ruby:app/serializers/book_serializer.rb
attributes :id, :title, :user
```

```text:curl
curl -X GET http://localhost:3000/books/1
curl -X GET http://localhost:3000/users/20
```

これで、Bookに紐づくUser情報が取得できたり、
Userに紐づくBooks情報がJSON形式で取得できればOK。

## ⑤ バージョニング
```ruby:routes.rb
namespace :v1 do
 resources :users, only: [:index, :show]
 resources :books, only: [:index, :show]
end
```

残りは、controllersとserializersフォルダの中に、
`v1` というフォルダを作成してそれぞれClass名に `V1::HogeController` と付けていけば完成です。

# まとめ
JSON形式で出力するだけであれば非常に簡単で、
ウェブアプリケーションをRailsで開発したことがある人であれば非常にとっつきやすいかと思います。

Part.2ではスマホアプリを作るとなったらほぼ誰でも直面する認証について書いていきます。