Rails5でGrapeを使って簡単にAPIを実装する

RailsでAPIの実装を依頼され、その時にGrapeを使用しましたので、使用方法を忘れないように書き残しておきたいと思います。

Grapeを使用すると、Restful な WEB-APIが簡単に実装できます。

# Grapeの導入
### 前提
- OS：Centos7
- Rubyのバージョン：2.4.1
- Railsのバージョン：5.1.6
- Railsプロジェクトは作成済

### Gemfile
```ruby:Gemfile
gem 'grape'
```
上記を追記して、bundle installする。

# フォルダ構成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279050/57fce26a-a8fd-61d3-d4ca-936d0f438440.png)
APIのソースはapp/apis/配下に配置することにしました。
ディレクトリ構成およびファイル名は、クラスの名前空間およびクラス名と一致させる必要がありです。（大文字、小文字の区別なし）

この例では、1つのバージョンしか作成しないため、「v1」フォルダのみとなりますが、複数バージョン作成したい場合は、「v2」などのフォルダを作成して下さい。

# 手順
### Config/application.rbを修正
```ruby:Config/application.rb
module TestApp
  class Application < Rails::Application
    # 省略
    
    config.paths.add File.join('app', 'apis'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'apis', '*')]
  end
```
最後の2行を追記します。これにより、app/apis/ 配下のRubyファイルが読み込まれるようにします。

### 基底となるAPIクラスをapp/apis/apiに作成
```ruby:app/apis/api/root.rb
module API
  class Root < Grape::API
    # http://localhost:3000/api/
    prefix 'api'

    mount API::V1::Root
  end
end
```
ここでは、各バージョンの基底となるAPIクラスをマウントしています。
今回は、1つのバージョンのみとなります。

### v1の中で基底となるAPIクラスを作成
```ruby:app/apis/api/v1/root.rb
module API
  module V1
    class Root < Grape::API
      # http://localhost:3000/api/v1/
      version 'v1'
      format :json 

      mount API::V1::Articles
    end
  end
end
```
ここで各APIの実態をマウントします。

### 各APIの実態を作成
```ruby:app/apis/api/v1/articles.rb
module API
  module V1
    class Articles < Grape::API
      resource :articles do

        # GET /api/v1/articles
        desc 'Retrun all article'
        get '/' do
          Article.all
        end

        # GET /api/v1/articles/{:id}
        desc 'Retrun a article'
        params do
          requires :id, type: Integer
        end
        get ':id' do
          Article.find(params[:id])
        end

      end      
    end
  end
end
```
ここでは、２つのAPIを定義しています。
1つ目は、Articlesテーブルの全データを取得。
2つ目は、Articlesテーブルの中から、パラメータで指定されたIDに合致するデータを取得。

ここで注意すべき点は、クラス名です。
既に存在するクラスと同一の名前は避けるべきです。

今回の例の場合は、APIクラスの名称は「Articles」にしています。
仮に「Article」という名称にすると、Articleモデルのクラス名と同じ名称となるため、Article.allなどのArticleモデルクラスのメソッド実行時にエラーが発生します。

どうしても同一名称にしたい場合は、モデルクラスのメソッド実行時は以下のようにします。
::Article.all
※「::」を前につける

# 動作確認
rails sにて起動後に、APIのURLをブラウザに入力するとAPIを実行できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279050/90cab701-8061-f8f1-0c30-ba78c4a2acef.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279050/52ee08f5-27dd-d44c-878e-22a74e022e73.png)

コマンドを実行して確認することも可能です。

```console
$ curl -X GET http://localhost:3000/api/v1/articles
[{"id":1,"title":"タイトル1","content":"内容1","status":2,"created_at":"2018-06-11T21:47:58.801Z","updated_at":"2018-07-16T21:48:52.106Z","published_at":"2018-07-16T21:48:50.698Z"},{"id":2,"title":"タイトル2","content":"内容2","status":2,"created_at":"2018-06-11T21:47:58.993Z","updated_at":"2018-07-16T21:48:52.805Z","published_at":"2018-07-16T21:48:52.751Z"},{"id":3,"title":"タイトル3","content":"内容3","status":1,"created_at":"2018-06-11T21:47:59.194Z","updated_at":"2018-07-16T21:48:53.025Z","published_at":"2018-07-16T
※一部のみ

$ curl -X GET http://localhost:3000/api/v1/articles/2
{"id":2,"title":"タイトル2","content":"内容2","status":2,"created_at":"2018-06-11T21:47:58.993Z","updated_at":"2018-07-16T21:48:52.805Z","published_at":"2018-07-16T21:48:52.751Z"}
```

# 参考にしたサイト
[[Rails4] Grape で API を簡単に実装 ＆ API を複数バージョンで分ける方法](https://qiita.com/hkusu/items/2ca0323cc276ab31e926)