記事の詳細情報を取得するRails APIの作成

Rails APIの学習をしています。

今回は、articleモデルのデータを取得するAPIを作成していきます。

# 準備・使用環境

* Netflixが提供するライブラリ`FastJsonapi`を使用しています。
* 以前の投稿と同様の環境構築をしていることを前提とした実装になります。

https://qiita.com/ym0628/items/bc3f8c10b58a0d298059



# 期待するJSONレスポンスのデータ

```json
# http://localhost:3000/api/v1/articles/1　にアクセス

{
    "data": {
        "id": "1",
        "type": "article",
        "attributes": {
            "title": "MyString1",
            "contents": "MyText1",
            "status": "draft"
        },
        "relationships": {
            "user": {
                "data": {
                    "id": "1",
                    "type": "user"
                }
            }
        }
    },
    "included": [
        {
            "id": "1",
            "type": "user",
            "attributes": {
                "name": "MyString1",
                "email": "user+1@example.com"
            },
            "relationships": {
                "articles": {
                    "data": [
                        {
                            "id": "1",
                            "type": "article"
                        }
                    ]
                }
            }
        }
    ]
}
```



# ArticlesControllerの実装
```ruby
module Api
  module V1
    class ArticlesController < BaseController
      before_action :set_article, only: :show

      def show
        options = { include: [:user, :'user.name', :'user.email'] }
        options = { include: %i[user user.name user.email] }
        json_string = ArticleSerializer.new(@article, options).serialized_json

        render json: json_string
      end

      private

      def set_article
        @article = Article.find(params[:id])
      end
    end
  end
end
```
#### コードの解説
* このコードは、RubyのWebアプリケーションフレームワークであるRailsで使われる、`ArticlesController`クラスの一部である。
* `class ArticlesController < BaseController` は、`ArticlesController`という新しいクラスを作っていて、このクラスは`BaseController`という既存のクラスを継承している。
* `before_action :set_article, only: :show` は、showアクションが呼ばれる前に、`set_article`メソッドを実行するように指定している。
* `def set_article` は、`set_article`というメソッドを定義している。このメソッドは、`Article.find(params[:id])`というコードを使って、指定したIDの記事をデータベースから探し出し、`@article`インスタンス変数に保存している。

* 記事の詳細を返すshowメソッド。
* RubyのWebアプリケーションフレームワークであるRailsでよく使われる形。
* `options = { include: [:user, :'user.name', :'user.email'] }` は、記事の情報と一緒に関連するユーザーの情報（名前とメールアドレス）も取得するためのオプションを設定している。
* `json_string = ArticleSerializer.new(@article, options).serialized_json` は、`@article（記事）`と設定したオプションを使い、記事の情報をJSON形式に変換している。
* この時に使われる`ArticleSerializer`は、記事のデータをどのようにJSON化するかを定義したクラスである。
* 最後に `render json: json_string` で、変換したJSONをレスポンスとして返している。



# Userシリアライザーの作成

#### コマンドでUserシリアライザーを生成します。
```
$ rails g serializer User name email
```

#### 生成したシリアライザーにアソシエーションを追記
```ruby
# user_serializer.rb

class UserSerializer
  include FastJsonapi::ObjectSerializer
  attributes :name, :email
  has_many :articles
end
```

#### コードの解説

* このコードは、`UserSerializer`というクラスを定義している。
* これは`FastJsonapi`を使って、UserオブジェクトをJSON形式に変換するための設定を書いているクラスである。
* `include FastJsonapi::ObjectSerializer` は、`FastJsonapi`の`ObjectSerializer`モジュールをこのクラスに取り込むためのコードである。
* これによって、このクラスはJSONへの変換機能を持つようになる。
* `attributes :name, :email` は、変換したJSONに含める属性を指定している。
* この場合、Userオブジェクトの`name`と`email`がJSONに含まれるようになる。
* `has_many :articles` は、Userが複数のArticlesを持っている場合、それらのArticleも一緒にJSONに含めるように指示している。
* Articleオブジェクトは`ArticleSerializer`によって変換されるべきである。