はじめてのRails API 

※ 当方、はじめてのQiita投稿になりますので、どうかお手柔らかにお願いいたします。

# そもそもAPIってなあに？

APIは、アプリケーションプログラミングインターフェースの略です。
「[WebAPIについての説明](https://qiita.com/busyoumono99/items/9b5ffd35dd521bafce47)」という記事の「[WebAPIの一旦のまとめ](https://qiita.com/busyoumono99/items/9b5ffd35dd521bafce47#webapi%E3%81%AE%E4%B8%80%E6%97%A6%E3%81%AE%E3%81%BE%E3%81%A8%E3%82%81)」に、簡潔でとてもいい説明がありました。

- *サーバーで用意している関数(機能)をhttpで通信して利用する事。*
- *利用するには決め事を守ってリクエストを出す。*
- *決まり事とはURLとか渡すデータの名前とかデータの形式とか。*
- *レスポンスは大体何かしらのデータ。時々画像も。*
- *データの形式は最近はJSON。一昔前はXMLが主流だった。*
- *ajax形式で利用される事が多い*

上記の記事を最初から全部読むのは大変だと思うので、概念から知りたい、という場合は以下の記事が参考になります。

- [APIって結局何なの？初心者向けに徹底解説します！](https://blog.codecamp.jp/api)

もっとコンピューターサイエンス的な観点で知りたい、という場合は、最初の記事をつまみ食いしながら読むと良さそうです。

そういうことで、APIはどうやら**JSON形式のデータ**だということが分かりました。
JSONについて知りたい方は、以下の記事を読んでみて下さい。

- [非エンジニアに贈る「具体例でさらっと学ぶJSON」](https://dev.classmethod.jp/etc/concrete-example-of-json/)

JSON形式のデータは、こんな感じの見た目をしています。

```json
{ "hoge": 1, "fuga": { "hoge": "hello" }}
```
このようなデータが返ってくるようなAPIを、これからRailsで作ってみたいと思います。

# Rails API を作成しよう


## 1. Railsプロジェクトの作成

まずは**APIモード**でRailsプロジェクトを作成しましょう。
APIモードでRailsプロジェクトを作成すると、APIには不要なView・UI関連のライブラリがインストールされません（Rails4までは`rails-api`というgemを入れる必要がありました）。
APIモードでRailsプロジェクトを作成するには、`rails new`するときに、`--api`オプションを付けます。

```bash
$ rails new api-project --api
```

## 2. Model、Controllerの作成

今回はscaffoldで作ってしまいましょう。

```bash
$ rails g scaffold users
```

できたModelは以下のようになります。

```ruby
class User < ApplicationRecord
end
```

また、Controllerは以下です。
`render json:`がいっぱいありますね。これでjson形式のAPIが出来ています。

```ruby
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]

  # GET /users
  def index
    @users = User.all

    render json: @users
  end

  # GET /users/1
  def show
    render json: @user
  end

  # POST /users
  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, status: :created, location: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /users/1
  def update
    if @user.update(user_params)
      render json: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  # DELETE /users/1
  def destroy
    @user.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def user_params
      params.fetch(:user, {})
    end
end

```

## 3. jsonを確認してみよう

実際にjsonを見てみましょう。
先ほど`User`モデルを作成したため、一度マイグレーションを行ってから、ローカルのRailsサーバーを立ち上げます。

```bash
$ rails db:migrate
== 20171216035325 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0015s
== 20171216035325 CreateUsers: migrated (0.0015s) =============================


$ rails s
```

以下のURLにアクセスすると、
http://localhost:3000/users
真っ白な画面に`[]`と表示されています。
この画面は`User#index`のアクションで、`User`一覧のjsonが出力されるのですが、まだ`User`のデータがひとつも入っていないため、空の配列が表示されています。
ですので、正常に表示されているということになります。

これだけだとさみしいので、データが入った状態のjsonを確認するために、`name`カラムを追加します。
[マイグレーションファイルを作成](https://github.com/c5meg1012/api-project/commit/e86b6b334eed36ddb77ba4c276a5d7857e30ac7a)して、[その内容を更新](https://github.com/c5meg1012/api-project/commit/c1d470fc2f795568eeedc65b22db1159fc2fc6cd)し、[再度マイグレーションを行い](https://github.com/c5meg1012/api-project/commit/b66801c72c0894d6d25180b6c0aea2efd86bf0b8)ます。
これで`name`カラムが追加されました。
これから`User`のデータを入れるためにpostを行うので、[Controllerのストロングパラメータを更新](https://github.com/c5meg1012/api-project/commit/edd979573e60214136ace57b754317269ef377de)します。

以上の準備ができたところで、以下のコマンドで**新しいUserを作るAPI**を叩いてみましょう。

```bash
$ curl -X POST http://localhost:3000/users -d 'user[name]=meru'
{"id":1,"created_at":"2017-12-16T04:30:04.202Z","updated_at":"2017-12-16T04:30:04.202Z","name":"meru"}
```
このようなレスポンスが返ってくれば、成功です。
それでは、先ほどのURLに再度アクセスしてみましょう。
http://localhost:3000/users
以下のように表示されていれば、成功です。

```
[{"id":1,"created_at":"2017-12-16T04:30:04.202Z","updated_at":"2017-12-16T04:30:04.202Z","name":"meru"}]
```

# テストの作成

APIのテストは、エラーハンドリング（各種エラーをどのように処理するか）の検証で重要になります。
APIではない通常のRailsアプリケーションでもテストは欠かせませんが、APIを目視や動作確認で検証するなんてますます面倒ですので、APIを作る際には必ずテストを書くようにしましょう。

今回は`rspec`で作成したいので、これまで作成してきたRailsプロジェクトに、`rspec`をインストールします。
方法については、以下の記事を参考にして下さい。

- [Railsでrspecを使うように設定する](https://qiita.com/akiko-pusu/items/0f15130509a88cf59a7d)

APIのテストは、`spec/requests`ディレクトリ以下に作成します。

```
$ bundle exec rails generate rspec:integration User
```

これで、テストファイルが自動生成されます。

今回は`User#index`だけテストを行います。
[テストの内容を更新](https://github.com/c5meg1012/api-project/commit/45f40dede3f87494f8c94e20ad6db3a9340861c4)し、テストを実行してみましょう。

```
$ bundle exec rspec
.

Finished in 0.17578 seconds (files took 1.87 seconds to load)
1 example, 0 failures
```

これで、APIのテストが出来ました。


# API ドキュメント も忘れずに

APIからレスポンスを受けるには、**渡すデータの名前やデータの形式などの決め事を守ってリクエストを出す**こと、という説明が前半でありました。
API ドキュメントは、その決め事を何らかの形で見える化するものです。
リクエストを出す側の気持ちを考えると、APIを作るなら必ず残しておきたいですね。

ちなみに、QiitaのAPIドキュメントはこんな感じで、

- [Qiita API v2ドキュメント - Qiita:Developer](https://qiita.com/api/v2/docs)

esaのAPIドキュメントはこんな感じです。

- [dev/esa/api/v1 - docs.esa.io](https://docs.esa.io/posts/102)

[rails guide](https://railsguides.jp/api_documentation_guidelines.html)のように`$ bundle exec rake rdoc`で生成して、マークダウンで書いていく方法もありますが、
[autodoc](https://github.com/r7kamura/autodoc)というツールを使えば、`rspec`のテストから自動生成できます。
先ほど作成したテストをもとに、APIドキュメントを生成してみましょう。

Gemfileに`gem 'autodoc, group: :test'`を追加し、`$ bundle install`をします。
その後は、以下の記事を参考にしながら進めましょう。

- [Rails でつくる API のドキュメントを自動生成してくれる autodoc がすごい](http://blog.inouetakuya.info/entry/2013/10/20/132928)

これで、APIドキュメントが作成できました。

# まとめ

後半駆け足になってしまいましたが、「RailsでAPIっていうものを作ってみたいけどやり方がわからない...」という方向けに、APIの作成からテスト、ドキュメントの作成方法までご紹介しました。

APIの書き方やドキュメントの作成方法には、ほかにもいくつか種類がありますので、興味のある方は調べてみて下さい。