gem Active Model Serializers のドキュメントを翻訳しました

# 概要
gem [active_model_serializers](https://github.com/rails-api/active_model_serializers) の version [0-10-stable](https://github.com/rails-api/active_model_serializers/tree/0-10-stable) のドキュメントを翻訳しました。
Rails で API を作成するときに active_model_serializers を使うことも多いと思うので、参考になれば幸いです。

- 翻訳について
    - 翻訳サービス [Deepl](https://www.deepl.com/translator) と [Goole翻訳](https://translate.google.co.jp/) の訳文を参考にしている箇所があります。

- ライセンスについて
    - [active model serializers のライセンス](https://github.com/rails-api/active_model_serializers/blob/master/MIT-LICENSE)と同様に、[MIT ライセンス](https://opensource.org/licenses/MIT)に従います。

# 目次

- [**Adapters**](#adapters) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/adapters.md)
  - [Built in Adapters](#built-in-adapters)
    - [Attributes（デフォルト）](#attributes%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88)
      - [出力例](#%E5%87%BA%E5%8A%9B%E4%BE%8B)
    - [JSON](#json)
      - [出力例](#%E5%87%BA%E5%8A%9B%E4%BE%8B-1)
    - [JSON API](#json-api)
      - [出力例](#%E5%87%BA%E5%8A%9B%E4%BE%8B-2)
    - [Include オプション](#include-%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3)
      - [セキュリティに関する考慮事項](#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E8%80%83%E6%85%AE%E4%BA%8B%E9%A0%85)
  - [高度なアダプタの設定](#%E9%AB%98%E5%BA%A6%E3%81%AA%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%81%AE%E8%A8%AD%E5%AE%9A)
    - [アダプタを登録する](#%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B)
    - [アダプタの検索](#%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%81%AE%E6%A4%9C%E7%B4%A2)

- [**Caching**](#caching) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/caching.md)
  - [警告](#%E8%AD%A6%E5%91%8A)
  - [Fragment Caching](#fragment-caching)

- [**Configuration Options**](#configuration-options) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/configuration_options.md)
  - [一般](#%E4%B8%80%E8%88%AC)
    - [adapter](#adapter)
    - [serializer_lookup_enabled](#serializer_lookup_enabled)
    - [key_transform](#key_transform)
    - [default_includes](#default_includes)
    - [serializer_lookup_chain](#serializer_lookup_chain)
    - [use_sha1_digests](#use_sha1_digests)
  - [JSON API](#json-api-1)
    - [jsonapi_resource_type](#jsonapi_resource_type)
    - [jsonapi_namespace_separator](#jsonapi_namespace_separator)
    - [jsonapi_include_toplevel_object](#jsonapi_include_toplevel_object)
    - [jsonapi_version](#jsonapi_version)
    - [jsonapi_toplevel_meta](#jsonapi_toplevel_meta)
    - [jsonapi_use_foreign_key_on_belongs_to_relationship](#jsonapi_use_foreign_key_on_belongs_to_relationship)
  - [フック](#%E3%83%95%E3%83%83%E3%82%AF)

- [**Deserialization**](#deserialization) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/deserialization.md)
  - [JSON API](#json-api-2)
  - [Attributes/Json](#attributesjson)

- [**Fields**](#fields) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/fields.md)

- [**Getting Started**](#getting-started) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/getting_started.md)
  - [シリアライザーの作成](#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E3%83%BC%E3%81%AE%E4%BD%9C%E6%88%90)
    - [ネームスペースのあるモデル](#%E3%83%8D%E3%83%BC%E3%83%A0%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%81%82%E3%82%8B%E3%83%A2%E3%83%87%E3%83%AB)
    - [モデルの関連とネストされたシリアライザー](#%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E9%96%A2%E9%80%A3%E3%81%A8%E3%83%8D%E3%82%B9%E3%83%88%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E3%83%BC)
    - [`ApplicationSerializer` の拡張](#applicationserializer-%E3%81%AE%E6%8B%A1%E5%BC%B5)
  - [Rails との統合](#rails-%E3%81%A8%E3%81%AE%E7%B5%B1%E5%90%88)

- [**Instrumentation**](#instrumentation) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/instrumentation.md)
  - [Events](#events)
  - [LogSubscriber](#logsubscriber)

- [**Key Transforms**](#key-transforms) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/key_transforms.md)
  - [Adapter option](#adapter-option)
  - [Configuration option](#configuration-option)
  - [Adapter default](#adapter-default)

- [**Logging**](#logging) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/logging.md)

- [**Rendering**](#rendering) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/rendering.md)
  - [暗黙のシリアライザ](#%E6%9A%97%E9%BB%99%E3%81%AE%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6)
  - [明示的なシリアライザ](#%E6%98%8E%E7%A4%BA%E7%9A%84%E3%81%AA%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6)
    - [1. 単一のリソース](#1-%E5%8D%98%E4%B8%80%E3%81%AE%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9)
    - [2. リソースのコレクション](#2-%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)
  - [non-ActiveRecord オブジェクトのシリアライズ](#non-activerecord-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%BA)
  - [SerializableResource options](#serializableresource-options)
    - [adapter_opts](#adapter_opts)
      - [fields](#fields)
      - [adapter](#adapter-1)
      - [key_transform](#key_transform-1)
      - [meta](#meta)
        - [トップレベル](#%E3%83%88%E3%83%83%E3%83%97%E3%83%AC%E3%83%99%E3%83%AB)
        - [リソースレベル](#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%AC%E3%83%99%E3%83%AB)
      - [links](#links)
        - [トップレベル](#%E3%83%88%E3%83%83%E3%83%97%E3%83%AC%E3%83%99%E3%83%AB-1)
        - [リソースレベル](#%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%AC%E3%83%99%E3%83%AB-1)
    - [serializer_opts](#serializer_opts)
      - [include](#include)
      - [Overriding the root key](#overriding-the-root-key)
      - [namespace](#namespace)
      - [serializer](#serializer)
      - [scope](#scope)
      - [scope_name](#scope_name)
  - [`render` メソッドなしのシリアライザの使用](#render-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AA%E3%81%97%E3%81%AE%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E3%81%AE%E4%BD%BF%E7%94%A8)
  - [ページネイション](#%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%8D%E3%82%A4%E3%82%B7%E3%83%A7%E3%83%B3)
- [**Serializers**](#serializers) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/serializers.md)
  - [属性](#%E5%B1%9E%E6%80%A7)
    - [::attributes メソッド](#attributes-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [::attribute メソッド](#attribute-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
  - [関連付け](#%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91)
    - [::has_one メソッド](#has_one-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [::has_many メソッド](#has_many-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [::belongs_to メソッド](#belongs_to-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
  - [ポリモーフィックリレーション](#%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%83%AA%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)
  - [キャッシュ](#%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5)
    - [::cache メソッド](#cache-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [#cache_key メソッド](#cache_key-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
  - [その他](#%E3%81%9D%E3%81%AE%E4%BB%96)
    - [::type メソッド](#type-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [::link メソッド](#link-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [#object メソッド](#object-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [#root メソッド](#root-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [#scope メソッド](#scope-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
      - [コントローラーの認可コンテキスト](#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%83%BC%E3%81%AE%E8%AA%8D%E5%8F%AF%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88)
    - [#read_attribute_for_serialization(key) メソッド](#read_attribute_for_serializationkey-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
    - [#links メソッド](#links-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
      - [#json_key メソッド](#json_key-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
  - [例](#%E4%BE%8B)
  - [詳細情報](#%E8%A9%B3%E7%B4%B0%E6%83%85%E5%A0%B1)
  - [関連付けメソッドのオーバーライド](#%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89)
  - [属性メソッドのオーバーライド](#%E5%B1%9E%E6%80%A7%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89)
  - [関連付けられたシリアライザ検索のオーバーライド](#%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%82%89%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E6%A4%9C%E7%B4%A2%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89)

- [**Read Me ActiveModelSerializers**](#read-me-activemodelserializers) [原文](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/README.md)
  - [About](#about)
  - [インストール](#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
  - [入門](#%E5%85%A5%E9%96%80)
  - [Getting Help](#getting-help)
  - [ドキュメント](#%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88)
  - [高レベルの動作](#%E9%AB%98%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AE%E5%8B%95%E4%BD%9C)
  - [アーキテクチャ](#%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3)
    - [ActiveModel::Serializer](#activemodelserializer)
      - [ActiveModel::CollectionSerializer](#activemodelcollectionserializer)
    - [ActiveModelSerializers::Adapter::Base](#activemodelserializersadapterbase)
    - [ActiveModelSerializers::SerializableResource](#activemodelserializersserializableresource)
    - [Primitive handling](#primitive-handling)
    - [オプションのパースの行われ方](#%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%83%91%E3%83%BC%E3%82%B9%E3%81%AE%E8%A1%8C%E3%82%8F%E3%82%8C%E6%96%B9)
    - [「シリアライズ可能なリソース」とはどのようなものか？](#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%BA%E5%8F%AF%E8%83%BD%E3%81%AA%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%82%82%E3%81%AE%E3%81%8B)
  - [Semantic Versioning](#semantic-versioning)
  - [Contributing](#contributing)

# Adapters

ActiveModelSerializers は、グローバルに、またはシリアライズするとき（通常はレンダリング時）に、どのアダプタを使用するかを設定する機能を提供します。

グローバルなアダプタ設定は [`ActiveModelSerializers.config`](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#configuration-options) で設定されます。
できれば初期化時に一度だけ設定することが望ましいです。

例

```ruby
ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonApi
```

```ruby
ActiveModelSerializers.config.adapter = :json_api
```

```ruby
ActiveModelSerializers.config.adapter = :json
```

ローカルのアダプタのオプションは `adapter: adapter` の形式で記載されます。`adapter` にはグローバル設定と同じ値が入ります。

[Advanced adapter configuration](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#%E9%AB%98%E5%BA%A6%E3%81%AA%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%81%AE%E8%A8%AD%E5%AE%9A) に記載されているように、設定されたアダプタは、シンボル、クラス、またはクラス名として設定できます。

`Attributes` アダプタにはルートキーは含まれず、単純にシリアライズされた属性となります。

レスポンスドキュメントにルートキーを含めたい場合は、`JSON` または `JSON API` アダプタを使用してください。

***重要***: アダプタ設定は直接使用されるシリアライザのインスタンスには効果がありません。つまり、 `UserSerializer.new(user).as_json` は `Attributes` アダプタのように振る舞います。推奨する使用方法の詳細については [Outside Controller Usage](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/howto/outside_controller_use.md) をご覧ください。

## Built in Adapters

### Attributes（デフォルト）

デフォルトのアダプタで、ルートキーなしで json レスポンスを生成します。特定の規則には従っていません。

#### 出力例

```json
{
  "title": "Title 1",
  "body": "Body 1",
  "publish_at": "2020-03-16T03:55:25.291Z",
  "author": {
    "first_name": "Bob",
    "last_name": "Jones"
  },
  "comments": [
    {
      "body": "cool"
    },
    {
      "body": "awesome"
    }
  ]
}
```

### JSON

json レスポンスは常にルートキーを伴ってレンダリングされます。

ルートキーは下記の方法で上書きできます。
* render を呼び出すときに `root` オプションを渡す方法。詳細は [Rendering Guides](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#overriding-the-root-key) をご覧ください。
* シリアライザの `type` を設定する方法。詳細は [Serializers Guide](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#type-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89) をご覧ください。

特定の規則には従っていません。

#### 出力例

```json
{
  "post": {
    "title": "Title 1",
    "body": "Body 1",
    "publish_at": "2020-03-16T03:55:25.291Z",
    "author": {
      "first_name": "Bob",
      "last_name": "Jones"
    },
    "comments": [{
      "body": "cool"
    }, {
      "body": "awesome"
    }]
  }
}
```

### JSON API

このアダプタは [jsonapi.org/format](http://jsonapi.org/format) における[指定フォーマット](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/jsonapi/schema.md)の **version 1.0** に従います。

#### 出力例

```json
{
  "data": {
    "id": "1337",
    "type": "posts",
    "attributes": {
      "title": "Title 1",
      "body": "Body 1",
      "publish-at": "2020-03-16T03:55:25.291Z"
    },
    "relationships": {
      "author": {
        "data": {
          "id": "1",
          "type": "authors"
        }
      },
      "comments": {
        "data": [{
          "id": "7",
          "type": "comments"
        }, {
          "id": "12",
          "type": "comments"
        }]
      }
    },
    "links": {
      "post-authors": "https://example.com/post_authors"
    },
    "meta": {
      "rating": 5,
      "favorite-count": 10
    }
  }
}
```

### Include オプション

どの[シリアライザの関連付け](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91)がレンダリングされるかは `include` オプションを使用して指定できます。include オプションの使用方法は [JSON API 仕様の include オプション](http://jsonapi.org/format/#fetching-includes)と同じであり、すべてのアダプタで利用できます。

使用例

```ruby
  render json: @posts, include: ['author', 'comments', 'comments.author']
  # or
  render json: @posts, include: 'author,comments,comments.author'
```

`include` オプションの形式は下記のいずれかです。

- リレーションパスのカンマ区切りのリストで構成される文字列
- シンボルとハッシュの配列
- その2つの組み合わせ

空の文字列または空の配列は、関連付けのレンダリングを防ぎます。

さらに、2種類のワイルドカードを使用できます。

- `*` は1レベルの関連付けを含みます。
- `**` すべての関連付けを再帰的に含みます。

ワイルドカードは他のパスと組み合わせることができます。

```ruby
  render json: @posts, include: '**' # or '*' for a single layer
```

下記はポストをレンダリングして 次のリソースを include しています。

- author
- author の comments
- author の comments によって参照されるすべてのリソース（再帰的）

上記のように、任意の組み合わせで他のパスと組み合わせることができます。

```ruby
  render json: @posts, include: 'author.comments.**'
```

**注意:** ワイルドカードは ActiveModelSerializer 固有のものであり、JSON API 仕様の一部ではありません。

JSON API アダプタのデフォルトの include は、関連付けの設定がありません。 JSON および Attributes アダプタのデフォルトは、すべての関連付けが設定されています。

JSON API アダプタの場合、関連するリソースは `"included"` 項目に集められます。JSON アダプタと Attributes アダプタの場合は、関連するリソースは属性の中でレンダリングされます。

JSON API アダプタのみ、関連付けられたリソースのどの属性がレンダリングされるかを指定することができます。この機能は [sparse fieldset](http://jsonapi.org/format/#fetching-sparse-fieldsets) と呼ばれています。

```ruby
  render json: @posts, include: 'comments', fields: { comments: ['content', 'created_at'] }
```

#### セキュリティに関する考慮事項

含まれるオプションはクエリパラメータから取得される可能性があるため（つまりユーザーがコントロールできる）

```ruby
  render json: @posts, include: params[:include]
```

ユーザーは `include=**` を渡すことができます。

ユーザーが指定する include を適切にフィルタリングすることをお勧めします。

## 高度なアダプタの設定

### アダプタを登録する

上記のように、デフォルトのアダプタは指定したクラスを使用するように設定することができます。

たとえば、レンダリングするときは、アダプタはクラスあるいはシンボルでも指定することができます。
たとえば、`:great_example` , `ActiveModelSerializers::Adapter::GreatExample` のように、シンボルで指定されたときは、アダプタは登録されたものでなければなりません。

アダプタを登録する2つの方法があります。

1) 一番シンプルな方法は `ActiveModelSerializers::Adapter::Base` を継承することです。下記の例は `Example::UsefulAdapter` を `"example/useful_adapter"` として登録しています。

```ruby
module Example
  class UsefulAdapter < ActiveModelSerializers::Adapter::Base
  end
end
```

登録された名前がアンダースコアのネームスペースとクラスであることに気がつくと思います。

`ActiveModelSerializers::Adapter::Base` を継承したとき、秘密裏にそのサブクラスは `("example/useful_adapter" を Example::UsefulAdapter とする)`という風に登録されます。


2) `ActiveModelSerializers::Adapter` クラスの `register` メソッドを直接呼び出すことで、どんなクラスでもアダプタとして登録することができます。下記の例では、`MyAdapter` を `:special_adapter` として登録しています。

```ruby
class MyAdapter; end
ActiveModelSerializers::Adapter.register(:special_adapter, MyAdapter)
```

### アダプタの検索

| メソッド | 返り値 |
| :------------ |:---------------|
| `ActiveModelSerializers::Adapter.adapter_map` | すべてのアダプタのハッシュを返す。 `{ adapter_name => adapter_class }` |
| `ActiveModelSerializers::Adapter.adapters` | すべての `adapter_names` のソートされた配列を返す。 |
| `ActiveModelSerializers::Adapter.lookup(name_or_klass)` | `adapter_class`を返す。もし見つからない場合は、`ActiveModelSerializers::Adapter::UnknownAdapter` エラーが起こる。  |
| `ActiveModelSerializers::Adapter.adapter_class(adapter)` |`ActiveModelSerializers::Adapter.lookup(adapter)` に対する移譲。 |
| `ActiveModelSerializers::Adapter.configured_adapter` | `ActiveModelSerializers::Adapter.lookup(config.adapter)` を実行する便利なメソッド。 |

登録されたアダプタの名前は常にストリングです。しかし、シンボル、ストリングどちらでも検索することができます。
`get(:my_adapter)` と `get("MyAdapter")` のどちらも使用できるように、シンボルとストリングはアンダースコアで変換されます。

詳細は [the Adapter class on GitHub](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/adapter.rb) をご覧ください。

# Caching

## 警告

現在、AMSのキャッシュには問題があります。[キャッシュはパフォーマンスを改善しません。](https://github.com/rails-api/active_model_serializers/issues/1586)キャッシュを行うと、アプリケーションの速度を上昇させるのではなく、速度を低下させる場合があります。本番環境で使用する前に、実装するキャッシュをベンチマークすることをお勧めします。

___

シリアライザーをキャッシュするには、```cache``` を呼び出してオプションを渡します。オプションは ```ActiveSupport::Cache::Store``` と同じです。それに加えて、```"#{key}/#{object.id}-#{object.updated_at}"``` パターンのオブジェクトキャッシュのプレフィックスが入る ```key``` オプションもあります。

キャッシュのサポートは、複数のリクエスト間でキャッシュされたオブジェクトを使用するように最適化されています。```show``` リクエストでキャッシュされたオブジェクトは ```index``` リクエストで再利用されます。もし別のキャッシュされたシリアライザーとリレーションがある場合は、そのリレーションは自動的に作成および再利用されます。

**[注意] すべてのオブジェクトは個別にキャッシュされます。**

**[注意] キャッシュは、オブジェクトが更新されると自動的に期限切れになりますが、削除されません。**

```ruby
cache(options = nil) # options: ```{key, expires_in, compress, force, race_condition_ttl}```
```

以下の例をご覧ください。

```ruby
class PostSerializer < ActiveModel::Serializer
  cache key: 'post', expires_in: 3.hours
  attributes :title, :body

  has_many :comments
end
```

この例では、すべての ```Post``` オブジェクトは ```"post/#{post.id}-#{post.updated_at}"``` キーでキャッシュされます。必要に応じてこのキーを使用してキャッシュを期限切れにすることができますが、この場合、3時間後に自動的に期限切れになります。

## Fragment Caching

完全にキャッシュすべきではないAPIエンドポイントがある場合でも、属性とリレーションに対してフラグメントキャッシュを使用することで最適化することができます。

cache メソッドの ```only``` または ```except``` オプションを使用することで、キャッシュを適用する属性を定義することができます。

**[注意] キャッシュが適用されるのは自身のリレーションに対してです。**

例

```ruby
class PostSerializer < ActiveModel::Serializer
  cache key: 'post', expires_in: 3.hours, only: [:title]
  attributes :title, :body

  has_many :comments
end
```

# Configuration Options

`ActiveModelSerializers.config`　に下記の設定オプションを記載することができます。なるべくイニシャライザに記載するようにしてください。

## 一般

### adapter

使用する [adapter](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#adapters)。

設定可能な値:

- `:attributes` (default)
- `:json`
- `:json_api`

### serializer_lookup_enabled

自動でシリアライザの検索を可能にします。

設定可能な値:

- `true` (デフォルト)
- `false`

`false` を設定したときは、シリアライザを明示的に指定しなければなりません。

### key_transform

使用する [key transform](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#key-transforms)。


| オプション | 結果 |
|----|----|
| `:camel` | ExampleKey |
| `:camel_lower` | exampleKey |
| `:dash` | example-key |
| `:unaltered` | 元の変更されていないキー |
| `:underscore` | example_key |
| `nil` | アダプタのデフォルトを使用 |

各アダプタにはデフォルトのキー変換が設定されています。

| アダプタ | デフォルトのキー変換 |
|----|----|
| `Attributes` | `:unaltered` |
| `Json` | `:unaltered` |
| `JsonApi` | `:dash` |

`config.key_transform` はアダプタの持つデフォルト設定をグローバルにオーバーライドします。アダプタはこの設定よりもレンダリング時のオプションである `:key_transform` を優先します。

*注意: キー変換はコンピューターリソースを多く使う操作です。キー変換が不必要な場合は、`config.key_transform` に `:unaltered` を設定すると、パーフォマンスが向上します。*

### default_includes

デフォルトでシリアライズするリレーションシップです。デフォルトでは、`'*'` が設定されていて、これは関連するオブジェクトの1レベル目を含みます。詳細は、[includes](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#include-%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3) をご覧ください。

### serializer_lookup_chain

シリアライザがどのように検索されるかを設定します。デフォルトでは、ルックアップチェインには下記が設定されています。

```ruby
ActiveModelSerializers::LookupChain::DEFAULT
```

これは下記の記述の略記です。

```ruby
[
  ActiveModelSerializers::LookupChain::BY_PARENT_SERIALIZER,
  ActiveModelSerializers::LookupChain::BY_NAMESPACE,
  ActiveModelSerializers::LookupChain::BY_RESOURCE_NAMESPACE,
  ActiveModelSerializers::LookupChain::BY_RESOURCE
]
```

各配列の項目は手順を表しています。シリアライザ検索の手順は、 `resource_class`, `serializer_class`, `namespace` の3つの引数で生成されます。

次のことに注意してください:
 - `resource_class` はレンダリングされるリソースのクラスです。
 - デフォルトでは `serializer_class` は `ActiveModel::Serializer` です。
  - 関連付けの検索においては、それは親シリアライザになります。
 - `namespace` はコントローラーのネームスペースか任意の指定された [namespace render option](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#namespace) の `namespace` のどちらかです。

設定例は次の通りになります。

```ruby
ActiveModelSerializers.config.serializer_lookup_chain = [
  lambda do |resource_class, serializer_class, namespace|
    "API::#{namespace}::#{resource_class}"
  end
]
```

もしすでに存在するルックアップチェインを追加したいときは、`unshift` を使ってください。

```ruby
ActiveModelSerializers.config.serializer_lookup_chain.unshift(
  lambda do |resource_class, serializer_class, namespace|
    # ...
  end
)
```

詳細は [lookup_chain.rb](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/lookup_chain.rb) をご覧ください。

### use_sha1_digests

シリアライザをキャッシュするときに内部的に使用するハッシュアルゴリズムを決定します。

設定可能な値:

- `true`
- `false` (デフォルト)

この値が `true` のときは、ActiveModelSerializers は SHA1 を使用します。それ以外の場合、デフォルトで MD5 が使用されます。
この値を変更すると、シリアライザのキャッシュが無効になる可能性があることに注意してください。

## JSON API

### jsonapi_resource_type

[シリアライザで明確に指定されていないときに](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#type-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)、リソースの  [type](http://jsonapi.org/format/#document-resource-identifier-objects) が単数形と複数形のどちらなのかを設定します。

設定可能な値:

- `:singular`
- `:plural` (デフォルト)

### jsonapi_namespace_separator

`type` 属性をレンダリングするために、ネームスペースのあるモデルの区切り文字列を設定してください。

| 区切り | 例: Admin::User |
|----|----|
| `'-'` (デフォルト) | 'admin-users'
| `'--'` (推奨) | 'admin--users'

詳細な議論は [Recommendation for dasherizing (kebab-case-ing) namespaced object, such as `Admin::User`](https://github.com/json-api/json-api/issues/850) をご覧ください。

### jsonapi_include_toplevel_object

レスポンスドキュメントに [top level jsonapi member](http://jsonapi.org/format/#document-jsonapi-object) を含める。

設定可能な値:

- `true`
- `false` (デフォルト)

### jsonapi_version

APIが準拠している仕様の最新バージョン。

デフォルト: `'1.0'`.

*`jsonapi_include_toplevel_object` が `true`* のときに使用されます。

### jsonapi_toplevel_meta

オプションの最上位メタデータです。空の場合は含まれません。

デフォルト: `{}`.

*`jsonapi_include_toplevel_object` が `true`* のときに使用されます。

### jsonapi_use_foreign_key_on_belongs_to_relationship

true を設定すると、関連付けあるいはシリアライザを呼び出さずに、リレーションシップはリソースオブジェクトの識別子を決定します。これは関連付けオブジェクトの呼び出しが不要なクエリをトリガーするときに便利です。

たとえば、`comment` が `post` に属し、コメントが外部キーとして `post_id` を使うとき、関連付けオプションの `comment.post_id` と `type` としてリソースオブジェクト識別子 `id` を決定します。
あるいは単純に、`belongs_to :post, type: :posts, foreign_key: :post_id` として動作します。

注意: インスタンス化をしないと関連付けオブジェクトのタイプを決定できないため、ポリモーフィックリレーションではこのオプションは効果がありません。

デフォルト: `false`

## フック

ActiveModelSerializers が読み込まれたときにフックを実行するためには、`ActiveSupport.on_load(:action_controller) do end` を使用してください。

# Deserialization

現在、これは実験的な機能です。インターフェースは変わる可能性があります。

## JSON API

`ActiveModelSerializers::Deserialization` には `jsonapi_parse` と `jsonapi_parse!` の2つのメソッドが定義されています。それらは、JSON API ペイロードを表す `Hash` または `ActionController::Parameters` のインスタンスを受け取り、モデルの作成・更新に直接使用できるハッシュを返します。バングバージョンはパースが失敗すると `InvalidDocument` 例外を発生させますが、セーフバージョンは空ハッシュを返すだけです。

- パラメーター
  - ドキュメント: `Hash` または `ActionController::Parameters` インスタンス
  - オプション:
    - only: ホワイトリストの対象となるフィールドの `Array`
    - except: ブラックリストの対象となるフィールドの `Array`
    - keys: 名前を変更する必要があるフィールド の `Hash`(例 `{ :author => :user, :date => :created_at }`)

例

```ruby
class PostsController < ActionController::Base
  def create
    Post.create(create_params)
  end

  def create_params
    ActiveModelSerializers::Deserialization.jsonapi_parse(params, only: [:title, :content, :author])
  end
end
```

下記が与えられる JSON API ドキュメントです。

```
document = {
  'data' => {
    'id' => 1,
    'type' => 'post',
    'attributes' => {
      'title' => 'Title 1',
      'date' => '2015-12-20'
    },
    'relationships' => {
      'author' => {
        'data' => {
          'type' => 'user',
          'id' => '2'
        }
      },
      'second_author' => {
        'data' => nil
      },
      'comments' => {
        'data' => [{
          'type' => 'comment',
          'id' => '3'
        },{
          'type' => 'comment',
          'id' => '4'
        }]
      }
    }
  }
}
```

オプションを指定せずにドキュメント全体をパースすることができます。

```ruby
ActiveModelSerializers::Deserialization.jsonapi_parse(document)
#=>
# {
#   title: 'Title 1',
#   date: '2015-12-20',
#   author_id: 2,
#   second_author_id: nil
#   comment_ids: [3, 4]
# }
```

フィールド、リレーション、およびポリモーフィックリレーションは、オプションを介して指定することができます。

```ruby
ActiveModelSerializers::Deserialization
  .jsonapi_parse(document, only: [:title, :date, :author],
                           keys: { date: :published_at },
                           polymorphic: [:author])
#=>
# {
#   title: 'Title 1',
#   published_at: '2015-12-20',
#   author_id: '2',
#   author_type: 'user'
# }
```

## Attributes/Json

現在、これらのアダプターの deserialization はありません。

# Fields

もし何らかの理由で返すフィールドを制限する必要がある場合は、`fields` オプションを使用する必要があります。

たとえば、次のようなシリアライザーがあり、

```ruby
class UserSerializer < ActiveModel::Serializer
  attributes :access_token, :first_name, :last_name
end
```

特定のコントローラーでは、`access_token` のみを返したい場合に `fields` オプションが役立ちます。

```ruby
class AnonymousController < ApplicationController
  def create
    render json: User.create(activation_state: 'anonymous'), fields: [:access_token], status: 201
  end
end
```

これは `json` および `attributes` アダプタに対してのみ有効であることに注意してください。 `json_api` アダプタの場合は下記を使用します。

```ruby
render json: @user, fields: { users: [:access_token] }
```

ここでは `users` は JSONAPI のタイプです。

# Getting Started

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

新しいシリアライザーを作成する最も簡単な方法は、新しいリソースを生成することです。これによって、シリアライザーの作成も同時に行われます。

```
$ rails g resource post title:string body:string
```

これにより新しいモデルのシリアライザーが `app/serializers/post_serializer.rb` に作成されます。シリアライザージェネレーターを使用して、既存のモデルのシリアライザーを作成することもできます。

```
$ rails g serializer post
```

作成されたシリアライザーにはモデルに基づいて、基本的な `attributes` と `has_many`/`has_one`/`belongs_to` の宣言が記載されます。

以下の例をご覧ください。

```ruby
class PostSerializer < ActiveModel::Serializer
  attributes :title, :body

  has_many :comments
  has_one :author
end
```

```ruby
class CommentSerializer < ActiveModel::Serializer
  attributes :name, :body

  belongs_to :post
end
```

宣言されている属性の名前は、シリアライズされるモデルの属性のホワイトリストになります。

`has_many` `has_one` `belongs_to` の宣言はリソース間のリレーションを記述しています。デフォルトでは、`Post` をシリアライズすると、`Comments` もシリアライズされます。

詳細については、[Serializers](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#serializers) を参照してください。

### ネームスペースのあるモデル

`Api::V1::Post` のようなネームスペース内のモデルをシリアライズするとき、ActiveModelSerializers は対応するシリアライザーが同じネームスペースの中（`Api::V1::PostSerializer`）にいることを期待します。

### モデルの関連とネストされたシリアライザー

次のような関連付けを持つモデルのシリアライザーを宣言する場合

```ruby
class PostSerializer < ActiveModel::Serializer
  has_many :comments
end
```

ActiveModelSerializers は優先的に `PostSerializer::CommentSerializer` を探し、それが見つからない場合は `::CommentSerializer` を探します。これにより、モデルを他のモデルの関連付けとしてシリアライズする方法をより詳細に制御できます。

たとえば、下記をご覧ください。

```ruby
class CommentSerializer < ActiveModel::Serializer
  attributes :body, :date, :nb_likes
end

class PostSerializer < ActiveModel::Serializer
  has_many :comments
  class CommentSerializer < ActiveModel::Serializer
    attributes :body_short
  end
end
```

ActiveModelSerializersは、`Post` の一部として `Comment` をシリアライズするときに`PostSerializer::CommentSerializer` を使用します。そのため、`：body_short` 属性のみが含まれます。しかし、`Comment` を直接シリアライズするときは `::CommentSerializer` を使用します。その際は、`:body, :date, :nb_likes` 属性が含まれます。

### `ApplicationSerializer` の拡張

デフォルトでは、新しいシリアライザーは `ActiveModel::Serializer` を継承しています。もしシリアライザー全体でふるまいを共有したいときは、`app/serializers/application_serializer.rb` に `ApplicationSerializer` を作成することができます。

```ruby
class ApplicationSerializer < ActiveModel::Serializer
end
```

その後、新しく生成されたシリアライザーは自動的に `ApplicationSerializer` を継承します。

```
$ rails g serializer post
```

下記が生成されたシリアライザーです。

```ruby
class PostSerializer < ApplicationSerializer
  attributes :id
end
````

## Rails との統合

ActiveModelSerializers は Rails アプリと自動的に統合されるので、コントローラーを更新する必要はありません。
下記はコントローラーの例です。

```ruby
class PostsController < ApplicationController

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

end
```

もしリンク生成の Rails url ヘルパーを使用したいときは（例：`link(:resources) { resources_url }` ）、`Rails.application.routes.default_url_options` を設定してください。

```ruby
Rails.application.routes.default_url_options = {
    host: 'example.com'
}
```

# Instrumentation

ActiveModelSerializers は [ActiveSupport::Notification API](http://guides.rubyonrails.org/active_support_instrumentation.html#subscribing-to-an-event) を使用します。これにより、ロギングなどのイベントを購読することができます。

## Events

名前

`render.active_model_serializers`

ペイロード (例)

```ruby
{
  serializer: PostSerializer,
  adapter: ActiveModelSerializers::Adapter::Attributes
}
```

購読

```ruby
ActiveSupport::Notifications.subscribe 'render.active_model_serializers' do |name, started, finished, unique_id, data|
  # 任意の処理
end
ActiveSupport::Notifications.subscribe 'render.active_model_serializers' do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
  # event.payload
  # 任意の処理
end
```

## [LogSubscriber](http://api.rubyonrails.org/classes/ActiveSupport/LogSubscriber.html)

ActiveModelSerializers には `render.active_model_serializers` に付随する `ActiveModelSerializers::LogSubscriber` が含まれています。

# Key Transforms

Key Transforms は、シリアライズされたレスポンスの中で参照されるものも含めてキーの文字形式を変更します。

提供されるキー変換の種類:

| オプション | 結果 |
|----|----|
| `:camel` | ExampleKey |
| `:camel_lower` | exampleKey |
| `:dash` | example-key |
| `:unaltered` | 元々のキーを使用 |
| `:underscore` | example_key |
| `nil` | アダプタのデフォルトを使用 |

キー変換の優先順位は下記の通りです:

##### Adapter option

`key_transform` はレンダリングのオプションとして提供されます。

```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```

##### Configuration option

`key_transform` は `ActiveModelSerializers.config.key_transform` に設定します。

```ActiveModelSerializers.config.key_transform = :camel_lower```

##### Adapter default

各アダプタはデフォルトの変換設定を持っています:

| アダプタ | デフォルト設定 |
|----|----|
| `Json` | `:unaltered` |
| `JsonApi` | `:dash` |

# Logging

Rails アプリケーションのデフォルトのロガーは `Rails.logger` です。

`Rails.logger` がないときは、標準出力にログを出力する `ActiveSupport::TaggedLogging` のインスタンスがデフォルトのロガーになります。

たとえば下記のように、イニシャライザでロガーをカスタマイズすることもできます。

```ruby
ActiveModelSerializers.logger = Logger.new(STDOUT)
```

`config/initializers/active_model_serializers.rb` に下記を記載することで、ロガーを無効にすることもできます。

```ruby
require 'active_model_serializers'
ActiveSupport::Notifications.unsubscribe(ActiveModelSerializers::Logging::RENDER_EVENT)
```

# Rendering

## 暗黙のシリアライザ

コントローラーで `render :json` を使うとき、Rails はまず最初にオブジェクトのシリアライザを探し、もし利用可能ならそのシリアライザを使用します。

```ruby
class PostsController < ApplicationController
  def show
    @post = Post.find(params[:id])

    render json: @post
  end
end
```

上記の場合、Rails は `PostSerializer` を探し、それが存在する場合は、そのシリアライザを使用して `Post` をシリアライズします。

## 明示的なシリアライザ

もしデフォルト以外のシリアライザを使いたいときは、render メソッドに明示的にシリアライザを渡すことができます。

### 1. 単一のリソース

```ruby
  render json: @post, serializer: PostPreviewSerializer
```

### 2. リソースのコレクション

各々のリソースに対して `each_serializer` でシリアライザを指定してください。

```ruby
render json: @posts, each_serializer: PostPreviewSerializer
```

コレクションのデフォルトのシリアライザは `CollectionSerializer` です。

`serializer` オプションでコレクションシリアライザを指定してください。

```ruby
render json: @posts, serializer: CollectionSerializer, each_serializer: PostPreviewSerializer
```

## non-ActiveRecord オブジェクトのシリアライズ

[README](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%BA%E5%8F%AF%E8%83%BD%E3%81%AA%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%82%82%E3%81%AE%E3%81%8B) をご覧ください。

## SerializableResource options

[README](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#activemodelserializersserializableresource) をご覧ください。

### adapter_opts

#### fields

`json` または `attributes` アダプタを使用している場合、 fields オプションを使用できます。

```ruby
render json: @user, fields: [:access_token]
```

詳細は [Fields](fields.md) をご覧ください。

#### adapter

このオプションを使用することで、登録済みのアダプタを渡して明示的にアダプタを設定できます。オプションは `:attributes`, `:json`, または `:json_api` です。

```
ActiveModel::Serializer.config.adapter = :json_api
```

#### key_transform

例
```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```

詳細は [Key Transforms](key_transforms.md) をご覧ください。

#### meta

`meta` 項目は非標準のメタ情報を含むために使用することができます。`meta` はレスポンスにおいていくつかの水準で利用されます。

##### トップレベル

レスポンスでトップレベルの `meta` を設定するときは、`render` の呼び出し時に `meta` を指定してください。

```ruby
render json: @post, meta: { total: 10 }
```

`meta_key`　オプションを使用することでキーをカスタマイズすることができます。

```ruby
render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
```

 `JsonApi` や `Json` アダプタのように `root` をサポートするアダプタを使用するときのみ、レスポンスに `meta` は含まれます。デフォルトアダプタである `Attributes` は `root` を持っていません。

##### リソースレベル

レスポンスでリソースレベルの `meta` を設定するには、シリアライザの中で下記の方法の内の一つを使って meta を定義してください。

単独の静的な文字列の場合

```ruby
meta stuff: 'value'
```

ハッシュを含むブロックの場合

```ruby
meta do
  {
    rating: 4,
    comments_count: object.comments.count
  }
end
```


#### links

たとえば `link(:resources) { resources_url }` のように、リンク生成のためにRailsのURLヘルパー使いたいときは、必ず `Rails.application.routes.default_url_options` をアプリケーションに設定してください。


##### トップレベル

JsonApi はトップレベルで指定する [links object](http://jsonapi.org/format/#document-links) をサポートしています。`render` メソッドでそれを指定することができます。

```ruby
  links_object = {
    href: "http://example.com/api/posts",
    meta: {
      count: 10
    }
  }
  render json: @posts, links: links_object
```

結果は下記になります。

```json
{
  "data": [
    {
      "type": "posts",
      "id": "1",
      "attributes": {
        "title": "JSON API is awesome!",
        "body": "You should be using JSON API",
        "created": "2015-05-22T14:56:29.000Z",
        "updated": "2015-05-22T14:56:28.000Z"
      }
    }
  ],
  "links": {
    "href": "http://example.com/api/posts",
    "meta": {
      "count": 10
    }
  }
}
```

この機能は JsonApi に固有であるため、[JsonApi Adapter](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#json-api) を使用する必要があります。

##### リソースレベル

シリアライザの中で、下記の方法の内の一つを使ってそれぞれのリンクを定義してください。

静的な文字列の場合。

```ruby
link :link_name, 'https://example.com/resource'
```

ブロックの場合。Rails を使うとURLヘルパーを使用することができます。
必ず `Rails.application.routes.default_url_options` をアプリケーションに設定してください。

```ruby
link :link_name_ do
  "https://example.com/resource/#{object.id}"
end

link(:link_name) { "https://example.com/resource/#{object.id}" }

link(:link_name) { resource_url(object) }

link(:link_name) { url_for(controller: 'controller_name', action: 'index', only_path: false) }

```

### serializer_opts

#### include

[Adapters: Include Option](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#include-%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3) をご覧ください。

#### Overriding the root key

ルートキーのオーバーライドはJSONアダプタのときのみ適用されます。

通常、リソースルートはシリアライズされるリソースのクラス名が使用されます。
たとえば、`UserPostSerializer.new(UserPost.new)` はアダプタのコレクション複数化ルールに応じて、`user_post` または `user_posts` をルートとしてシリアライズされます。

イニシャライザで JSON アダプタを使用するとき（ActiveModelSerializers.config.adapter = :json）、あるいは、render メソッドの呼び出し時に JSON アダプタを渡すと、`render` の引数としてルートキーを渡すことができます。

例

```ruby
  render json: @user_post, root: "admin_post", adapter: :json
```

これは下記のようにレンダリングされます。

```json
  {
    "admin_post": {
      "title": "how to do open source"
    }
  }
```

注意： デフォルトである `Attributes` アダプタはリソースルートを含みません。 :json_api アダプタを使用するときも単独のトップレベルのルートを作成することはできません。

#### namespace

シリアライザの検索に使用されるネームスペースはコントローラーがもとになっています。

暗黙的なネームスペースを設定するために、コントローラーに before filter を作成してください。

```ruby
before_action do
  self.namespace_for_serializer = Api::V2
end
```

`namespace` オプションを render メソッドに渡すことができます。

```ruby
@post = Post.first
render json: @post, namespace: Api::V2
```

これはシリアライザの検索に `Api::V2::PostSerializer` の存在を確認するように伝えます。
これによって、`Api::V2::PostSerializer`　をシリアライザの検索時に探すようになります。もし `@post` に何らかのリレーションがレンダリングされるときは、そのリレーションは `Api::V2` のネームスペースも使用します。


`namespace` は、ストリング・インターポーション（つまり to_s を呼び出すこと）によってネームスペースを表すことができる任意のオブジェクトにすることができます。

- モジュール `Api::V2`
- ストリング `'Api::V2'`
- シンボル `:'Api::V2'`

ストリングとシンボルを使うことで、 Ruby はトップレベルにネームスペースが定義されていると考えるので注意してください。


#### serializer

デフォルトではないシリアライザを使いたいときは、使用するシリアライザを指定してください。

単独のリソースのとき：

```ruby
@post = Post.first
render json: @post, serializer: SpecialPostSerializer
```

コレクションのにおいて個々のアイテムに使うシリアライザを指定するときは（たとえば `index` アクションのとき）、 `each_serializer` を使用してください。

```ruby
@posts = Post.all
render json: @posts, each_serializer: SpecialPostSerializer
```

#### scope

[Serializers: Scope](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#scope-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89) をご覧ください。

#### scope_name

[Serializers: Scope](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#scope-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89) をご覧ください。

## `render` メソッドなしのシリアライザの使用

[Usage outside of a controller](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/howto/outside_controller_use.md#serializing-before-controller-render) をご覧ください。

## ページネイション

[How to add pagination links](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/howto/add_pagination_links.md) をご覧ください。

# Serializers

シリアライザクラスが与えられた場合

```ruby
class SomeSerializer < ActiveModel::Serializer
end
```

下記のメソッドを定義できます。


## 属性

### ::attributes メソッド

リソースの `title` と `body` のシリアライズ化

| シリアライザの記載             | #attributes メソッドの返り値 |
|---------------------------- |-------------|
| `attributes :title, :body`  | `{ title: 'Some Title', body: 'Some Body' }`
| `attributes :title, :body`<br>`def body "Special #{object.body}" end` | `{ title: 'Some Title', body: 'Special Some Body' }`


### ::attribute メソッド

リソースの `title` のシリアライズ化

| シリアライザの記載               | #attributes メソッドの返り値 |
|---------------------------- |-------------|
| `attribute :title`          | `{ title: 'Some Title' } `
| `attribute :title, key: :name` | `{ name: 'Some Title' } `
| `attribute(:title) { 'A Different Title'}` | `{ title: 'A Different Title' } `
| `attribute :title`<br>`def title 'A Different Title' end` | `{ title: 'A Different Title' }`

`if` あるいは `unless` オプションは属性を条件付きにすることができます。if, unless はシリアライザのメソッド名のシンボル、あるいはラムダリテラルを受け取ります。

例

```ruby
attribute :private_data, if: :is_current_user?
attribute :another_private_data, if: -> { scope.admin? }

def is_current_user?
  object.id == current_user.id
end
```

## 関連付け

The interface for associations is, generically:
関連付けのインターフェースは一般的に、

> `association_type(association_name, options, &block)`

の形を取ります。

- `association_type` は `has_one`, `has_many`, `belongs_to` のいずれかです。
- `association_name` はシリアライザが呼び出すメソッド名です。
- 任意: `options` には下記を設定することができます。
  - `key:` シリアライズされる関連付けに使用される名前。
  - `serializer:`
  - `if:`
  - `unless:`
  - `virtual_value:`
  - `polymorphic:` シリアライズされる関連付けにポリモーフィックなリレーションがネストされているときに定義してください。
  - `type:` JSON:API が使用されたときのリソースタイプ。特に `belongs_to` のリレーションで使用されます。
  - `class_name:` `type` が与えられていないときに `type` を決定するために使用されるストリングのモデル名。たとえば、`class_name: "Comment"` はタイプ `comments` を意味します。
  - `foreign_key:` 関連付けのオブジェクトの不必要な読み込みを避けるために、`belongs_to` リレーションシップにおいて JSON:API で使用されます。
  - `namespace:` シリアライザを検索するときと `serializer` オプションが指定されていないときに使用されます。親シリアライザの instance options の `:namespace` を遡ります。instance options の `:namespace`　は render メソッドのオプションとして渡されます。詳細は、[Rendering#namespace](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#namespace) をご覧ください。
- 任意: `&block` は関連付けの属性を返すコンテキストです。
  - `association_name` メソッドが呼び出されるのを防ぎます。
  - ブロックの戻り値は関連付けの値として使用されます。
  - ブロックに `serializer` を生成する。
  - JSON API の関連付けにおいて `include_data false` は `data` キーがレンダリングされることを防ぐ。

### ::has_one メソッド

例

```ruby
has_one :bio
has_one :blog, key: :site
has_one :blog, class_name: "Blog"
has_one :maker, virtual_value: { id: 1 }

has_one :blog do |serializer|
  serializer.cached_blog
end

def cached_blog
  cache_store.fetch("cached_blog:#{object.updated_at}") do
    Blog.find(object.blog_id)
  end
end
```

```ruby
has_one :blog, if: :show_blog?
# ストリングあるいはラムダも使うことができる。
# has_one :blog, if: 'scope.admin?'
# has_one :blog, if: -> (serializer) { serializer.scope.admin? }
# has_one :blog, if: -> { scope.admin? }

def show_blog?
  scope.admin?
end
```

### ::has_many メソッド

例

```ruby
has_many :comments
has_many :comments, key: :reviews
has_many :comments, serializer: CommentPreviewSerializer
has_many :comments, class_name: "Comment"
has_many :reviews, virtual_value: [{ id: 1 }, { id: 2 }]
has_many :comments, key: :last_comments do
  last(1)
end
```

### ::belongs_to メソッド

例

```ruby
belongs_to :author, serializer: AuthorPreviewSerializer
belongs_to :author, key: :writer
belongs_to :author, class_name: "Author"
belongs_to :post
belongs_to :blog
def blog
  Blog.new(id: 999, name: 'Custom blog')
end
```

## ポリモーフィックリレーション

ポリモーフィックリレーションは、他の関連付けのようにリレーションを指定することでシリアライズされます。以下の例をご覧ください。

```ruby
class PictureSerializer < ActiveModel::Serializer
  has_one :imageable
end
```

[overriding serializer_for](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%82%89%E3%82%8C%E3%81%9F%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%A9%E3%82%A4%E3%82%B6%E6%A4%9C%E7%B4%A2%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%89) を行うことによって、シリアライザを指定することができます。ポリモーフィックリレーションの詳細については、各アダプタの [tests](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/test/adapter/polymorphic_test.rb) をご覧ください。

## キャッシュ

### ::cache メソッド

例

```ruby
cache key: 'post', expires_in: 0.1, skip_digest: true
cache expires_in: 1.day, skip_digest: true
cache key: 'writer', skip_digest: true
cache only: [:name], skip_digest: true
cache except: [:content], skip_digest: true
cache key: 'blog'
cache only: [:id]
```

### #cache_key メソッド

例

```ruby
# Uses a custom non-time-based cache key
def cache_key
  "#{self.class.name.downcase}/#{self.id}"
end
```

## その他

### ::type メソッド

`:json_api` アダプタを使用するとき、`::type` メソッドはシリアライザでレンダリングされる JSONAPI [type](http://jsonapi.org/format/#document-resource-object-identification) を定義します。

`:json` アダプタを使用するとき、`::type` メソッドはルートキーの名前を定義します。

`::type` メソッドは `String` と `Symbol` のどちらもパラメーターとして受け取ります。

注意: このメソッドは、`:json_api` あるいは `:json` アダプタを使用する場合にのみ役立ちます。

例

```ruby
class UserProfileSerializer < ActiveModel::Serializer
  type 'profile'

  attribute :name
end
class AuthorProfileSerializer < ActiveModel::Serializer
  type :profile

  attribute :name
end
```

`:json_api` アダプタの場合、上記のシリアライザは下記のようにレンダリングされます。

``` json
{
  "data": {
    "id": "1",
    "type": "profile",
    "attributes": {
      "name": "Julia"
    }
  }
}
```

`:json` アダプタの場合、上記のシリアライザは下記のようにレンダリングされます。

``` json
{
  "profile": {
    "name": "Julia"
  }
}
```

### ::link メソッド

```ruby
link :self do
  href "https://example.com/link_author/#{object.id}"
end
link(:author) { link_author_url(object) }
link(:link_authors) { link_authors_url }
link :other, 'https://example.com/resource'
link(:posts) { link_author_posts_url(object) }
```

属性のように、links はオプションのコンディションをサポートします。

```ruby
link(:secret, if: :internal?) { object.secret_link }

def internal?
  instance_options[:context] == :internal
end
```

### #object メソッド

シリアライズされているオブジェクトを返します。

### #root メソッド

`JSON` アダプタに含まれるリソースルートを返します。[Adapters Document](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#adapters) にあるように、`Attribute` アダプタ（デフォルト）と `JSON API` アダプタはトップレベルにルートキーを含みません。
デフォルトでは、リソースルートはシリアライズされるオブジェクトクラスの `model_name` から生成されます。

ルートを指定する方法はいくつかあります:
* [Overriding the root key](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#overriding-the-root-key)
* [Setting `type`](serializers.md#type)
* `root: 'specific_name'` のようにシリアライザの初期化をするときに、`root` オプションを指定する。

```ruby
ActiveModelSerializers::SerializableResource.new(foo, root: 'bar')
```

### #scope メソッド

外部メソッドへのアクセスをシリアライザに含めることができます。

シリアライザに認可コンテキストを提供することを目的としているため、 たとえば、管理者に投稿のすべてのコメントを表示するか、あるいはそうでなければ公開されたコメントのみを表示するということができます。

- `scope` は `options[:scope]` から来ているシリアライザインスタンスのメソッドです。nil であることもあります。
- `scope_name` は新しいシリアライザに渡されるオプションです（`options[:scope_name]`）。シリアライザは、`scope` を呼び出す名前でメソッドを定義します。例 `def current_user; scope; end`

注意: シリアライザインスタンスがその名前に応答するメソッドをすでに持っている場合は、メソッドは定義されません。

いくつか例をご覧ください。

まず、通常のシナリオなので、シリアライザがコントローラーでインスタンス化されると仮定します。
シリアライズを行うコンテキストを `controller` と呼びます。

| options | `Serializer#scope` | method definition |
|-------- | ------------------|--------------------|
| `scope: current_user, scope_name: :current_user` | `current_user` | `Serializer#current_user` calls `controller.current_user`
| `scope: view_context, scope_name: :view_context` | `view_context` | `Serializer#view_context` calls `controller.view_context`

スコープを利用して、カレントユーザーに関連するオブジェクトをカスタマイズできます。

たとえば、現在のユーザーに表示される投稿を、そのユーザーが作成した投稿に制限することができます。

```ruby
class PostSerializer < ActiveModel::Serializer
  attributes :id, :title, :body

  # scope comments to those created_by the current user
  has_many :comments do
    object.comments.where(created_by: current_user)
  end
end
```

メソッドを上記のように記述するか、`object.comments.where（created_by：scope）` として記述するかは好みの問題です。（`scope_name` は設定されているものとします）

スコープには、すべての利用可能なコントローラーの参照を設定できることに注意してください。これを利用すると、他のデータスコープまたはプレゼンテーションヘルパーへのアクセスを提供することができます。

#### コントローラーの認可コンテキスト

コントローラーでは、scope/scope_name オプションは [`serialization_scope` method](https://github.com/rails-api/active_model_serializers/blob/d02cd30fe55a3ea85e1d351b6e039620903c1871/lib/action_controller/serialization.rb#L13-L20) と同じです。
デフォルトでは、`serialization_scope` には `:current_user` が設定されています。

具体的には、`scope_name` のデフォルトは `:current_user` です。ただ、`serialization_scope :view_context` を設定することもできます。`scope_name` が存在してコントローラーが `scope_name` に応答するとき、`scope` が `send(scope_name)` に設定されます。

そのため、`render :json` を呼び出したとき、シリアライザの中では`current_user` が現在の認可範囲としてコントローラーから与えられます。

**重要**: スコープはレンダリング時に設定され、すべてのリクエストで `current_user` が呼び出されるわけではないので、スコープをカスタマイズしたくなるかもしれません。このことは、バージョン0.9でも[問題](https://github.com/rails-api/active_model_serializers/pull/1252#issuecomment-159810477)となっていました。

`current_user` から `view_context` にスコープを変更することができます。この変更は `ActionController::Base` のサブクラスに記載されます。

```diff
class SomeController < ActionController::Base
+  serialization_scope :view_context

  def current_user
    User.new(id: 2, name: 'Bob', admin: true)
  end

  def edit
    user = User.new(id: 1, name: 'Pete')
    render json: user, serializer: AdminUserSerializer, adapter: :json_api
  end
end
```

下記のように、シリアライザの中で `view_context` メソッドを使用できます。

```diff
class AdminUserSerializer < ActiveModel::Serializer
  attributes :id, :name, :can_edit

  def can_edit?
+    view_context.current_user.admin?
  end
end
```

`#edit` アクションをレンダリングすると下記の結果が得られます。

```json
{"data":{"id":"1","type":"users","attributes":{"name":"Pete","can_edit":true}}}
```

ここでは、`can_edit` は `view_context.current_user.admin?` の値（trueが返る）です。

また、特定のアクションに対して `serialization_scope` として設定するものを指示することもできます。

下記の例では、`Admin::PostSerializer` に対してのみ `admin_user` を使用し、それ以外では `current_user` を使用しています。

```ruby
class PostsController < ActionController::Base

  before_action only: :edit do
    self.class.serialization_scope :admin_user
  end

  def show
    render json: @post, serializer: PostSerializer
  end

  def edit
    @post.save
    render json: @post, serializer: Admin::PostSerializer
  end

  private

  def admin_user
    User.new(id: 2, name: 'Bob', admin: true)
  end

  def current_user
    User.new(id: 2, name: 'Bob', admin: false)
  end
end
```

異なるリソースを読み込む別のコントローラーメソッドやヘルパーへの参照などのように、目的のスコープを提供するどんなコントローラーの参照も利用可能なことに注意してください。たとえば、`ActionController::API` は `ActionView::ViewContext` を含まず、`serialization_scope` を使用して任意のヘルパーをシリアライザに渡すためには異なる参照を必要とします。

### #read_attribute_for_serialization(key) メソッド

たとえば、`read_attribute_for_serialization(:title) #=> 'Hello World'` のように、与えられたキーがシリアライズされた値。

### #links メソッド

`links` ノードを変更します。デフォルトでは、このノードには、[::link](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#link-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89) メソッドを使用して設定された属性が入力されます。`links: nil` を使用することで、`links` ノードを除去します。

```ruby
ActiveModelSerializers::SerializableResource.new(
  @post,
  adapter: :json_api,
  links: {
    self: {
      href: 'http://example.com/posts',
      meta: {
        stuff: 'value'
      }
    }
  }
)
```

#### #json_key メソッド

リソースルートとしてアダプタに使用されるキーを返します。詳細は、[root](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#root-%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89) をご覧ください。

## 例

`Post(title: string, body: text)` と `Comment(name: string, body: text, post_id: integer)` の2つのモデルがあるとき、2つのシリアライザを作成することになります。

```ruby
class PostSerializer < ActiveModel::Serializer
  cache key: 'posts', expires_in: 3.hours
  attributes :title, :body

  has_many :comments
end
```


```ruby
class CommentSerializer < ActiveModel::Serializer
  attributes :name, :body

  belongs_to :post
end
```

一般的な ActiveModelSerializers の使い方としては、これらのシリアライザのクラスを記載・生成します。

## 詳細情報

詳細は [the Serializer class on GitHub](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model/serializer.rb) をご覧ください。

## 関連付けメソッドのオーバーライド

関連付けをオーバーライドするには、ブロックと一緒に `has_many`, `has_one`, `belongs_to` を呼び出します。

```ruby
class PostSerializer < ActiveModel::Serializer
  has_many :comments do
    object.comments.active
  end
end
```

## 属性メソッドのオーバーライド

属性をオーバーライドするには、ブロックと一緒に `attribute` を呼び出します。

```ruby
class PostSerializer < ActiveModel::Serializer
  attribute :body do
    object.body.downcase
  end
end
```

## 関連付けられたシリアライザ検索のオーバーライド

関連付けのために特定のシリアライザの検索を定義したいときは、`ActiveModel::Serializer.serializer_for` メソッドをオーバーライドすることで定義した条件に基づいてシリアライザクラスを返すことができます。

```ruby
class MySerializer < ActiveModel::Serializer
  def self.serializer_for(model, options)
    return SparseAdminSerializer if model.class.name == 'Admin'
    super
  end

  # the rest of the serializer
end
```

# Read Me ActiveModelSerializers
## About

ActiveModelSerializers はJSON生成に設定よりも規約をもたらします。

ActiveModelSerializers は **serializers** と **adapters** の2つのコンポーネントを通して動作します。

シリアライザは_どの_属性とリレーションシップがシリアライズされるかを記載します。

アダプタは_どのように_属性とリレーションがシリアライズされるかを記載します。

SerializableResource はリソース、アダプタ、シリアライザを調整してリソースをシリアライズします。SerializableResource は Rails JSON Renderer に使用される `#as_json`, `#to_json` , `#serializable_hash` メソッドを持っています。（実際は SerializableResource はこれらのメソッドをアダプタに移譲します。）

デフォルトでは、ActiveModelSerializers は **Attributes アダプタ** を使用します（JSON のルートキーはありません）。
しかし、私たちは [jsonapi.org/format](https://jsonapi.org/format) で指定された バージョン1.0の形式に追従する **JsonApi アダプタ** を使用することを強く勧めます。
下記のセクションでアダプタの変更方法を確認してください。

`0.10.x` は `0.9.x` と `0.8.x` と後方互換性は**ありません**。

`0.10.x` は `0.8.0` のコードをもとにしていますが、より柔軟なアーキテクチャーを持っています。私たちはあなたの手助けを歓迎します。[貢献の仕方](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/CONTRIBUTING.md)。

## インストール

下記の行を Gemfile に追加してください。

```
gem 'active_model_serializers', '~> 0.10.0'
```

そして下記を実行してください:

```
$ bundle
```

## 入門

基礎的なことについては [Getting Started](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#getting-started) をご覧ください。

詳細情報は  [Guides](docs) と [High-level behavior](https://qiita.com/ikamirin/items/be809c845f6104aa6f48#%E9%AB%98%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AE%E5%8B%95%E4%BD%9C) に記載されています。

## Getting Help

もしバグを見つけた場合は、 [Issue](https://github.com/rails-api/active_model_serializers/issues/new) を報告して [contributing guide](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/CONTRIBUTING.md) を見てください。

質問があるときは、[Stack Overflow に投稿](https://stackoverflow.com/questions/tagged/active-model-serializers)してください.

チャットで話したいときは、[community slack](https://amserializers.herokuapp.com) に参加してください。

## ドキュメント

もし https://github.com/rails-api/active_model_serializers でこの文章を読んでいるなら、あなたは `master` ブランチのドキュメントを読んでいます。`master` ブランチ はまだリリースされていない機能を含んでいる可能性があります。関連するドキュメントについては、以下をご覧ください。

- [0.10 (0-10-stable) Documentation](https://github.com/rails-api/active_model_serializers/tree/0-10-stable)
- [0.10.10 (latest release) Documentation](https://github.com/rails-api/active_model_serializers/tree/v0.10.10)
    - [![API Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/active_model_serializers/0.10.10)
    - [Guides](docs)
- [0.9 (0-9-stable) Documentation](https://github.com/rails-api/active_model_serializers/tree/0-9-stable)
    - [![API Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/active_model_serializers/0.9.7)
- [0.8 (0-8-stable) Documentation](https://github.com/rails-api/active_model_serializers/tree/0-8-stable)
    - [![API Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/active_model_serializers/0.8.4)


## 高レベルの動作

[adapters](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model_serializers/adapter.rb) からアダプタを選択してください。

``` ruby
ActiveModelSerializers.config.adapter = :json_api # Default: `:attributes`
```

[シリアライズ可能なモデル](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model/serializer/lint.rb) が与えられた場合。

```ruby
# either
class SomeResource < ActiveRecord::Base
  # columns: title, body
end
# or
class SomeResource < ActiveModelSerializers::Model
  attributes :title, :body
end
```

下記のようにイニシャライズします。

```ruby
resource = SomeResource.new(title: 'ActiveModelSerializers', body: 'Convention over configuration')
```

シリアライズ可能なモデルのシリアライザが与えられた場合、

```ruby
class SomeSerializer < ActiveModel::Serializer
  attribute :title, key: :name
  attributes :body
end
```

モデルは下記のようにシリアライズされます。

```ruby
options = {}
serialization = ActiveModelSerializers::SerializableResource.new(resource, options)
serialization.to_json
serialization.as_json
```

SerializableResource はアダプタに移譲を行い、アダプタは下記のように構築します。

```ruby
adapter_options = {}
adapter = ActiveModelSerializers::Adapter.create(serializer, adapter_options)
adapter.to_json
adapter.as_json
adapter.serializable_hash
```

アダプタはシリアライザの属性と関連付けを構成します（別名 includes）。

```ruby
serializer_options = {}
serializer = SomeSerializer.new(resource, serializer_options)
serializer.attributes
serializer.associations
```

## アーキテクチャ

このセクションは ActiveModelSerializers の 0.10.x バージョンのアーキテクチャに焦点を当てています。
もし 0.8 あるいは 0.9 のバージョンに興味がある場合は、[0.8 README](https://github.com/rails-api/active_model_serializers/blob/0-8-stable/README.md) ,
[0.9 README](https://github.com/rails-api/active_model_serializers/blob/0-9-stable/README.md) を参照してください。

オリジナルの文章は[こちら](https://github.com/rails-api/active_model_serializers/blob/d72b66d4c5355b0ff0a75a04895fcc4ea5b0c65e/README.textile)でも見ることができます。

### ActiveModel::Serializer

**`ActiveModel::Serializer`** は [シリアライズ可能なリソース](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/serialization.rb) をラップし、`attributes` メソッドなどを使えるようにします。
ActiveModel::Serializer はリソースのシリアライズにおいてどの属性と関連付けを表すかを指定します。
ActiveModel::Serializer はアダプタに自身の属性を JSON ドキュメントに変換するように要求します。ActiveModel::Serializer だけではシリアライズを行うことはできません。
アダプタを [presenter](https://blog.steveklabnik.com/posts/2011-09-09-better-ruby-presenters) として考えると良いかもしれません。

#### ActiveModel::CollectionSerializer

**`ActiveModel::CollectionSerializer`** はリソースの集合を複数のシリアライザとして表します。もしシリアライザがない場合は基本要素を表します。

### ActiveModelSerializers::Adapter::Base

**`ActiveModelSerializers::Adapter::Base`** はシリアライザから生成された JSON ドキュメントの構造を記述します。たとえば、`Attributes` アダプタは各シリアライザを未変更の属性として表します。`JsonApi` アダプタはシリアライザを [JSON API](https://jsonapi.org/) ドキュメントとして表します。

### ActiveModelSerializers::SerializableResource

**`ActiveModelSerializers::SerializableResource`**　は `to_json` と `as_json` メソッドに応答するオブジェクトに対してシリアライザとアダプタを調整するように動作します。ActiveModelSerializers::SerializableResource はコントローラーにおいてレンダリング時にシリアライズするリソースを要約するために使用されます。しかし、コントローラーの外でも利用することはできます。

### Primitive handling

定義: プリミティブは通常、文字列か配列です。それらに対してシリアライザは定義されていません。リソースが JSON に変換されるとき（`as_json` あるいは `to_json` メソッド）にそれらはシリアライズされます。（以下は、シリアライザのないオブジェクトにも適用されます。）

- ActiveModelSerializers は `render json:` に渡されたプリミティブをハンドリングしません。

内部的には、コントローラーでシリアライザが見つけられない場合は、リソースは ActiveModelSerializers によって処理されません。

- しかし、プリミティブな値が属性、あるいはコレクションの1つであるとき、それは変更されません。

コレクションとコレクションシリアライザ（CollectionSerializer）をシリアライズし、リソースに対応するシリアライザを識別できないとき、[`:no_serializer`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128) をスローします。
たとえば、`Reflection#build_association` によってキャッチされ、関連付けの値が直接設定されたときです。

```ruby
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
```

（これはアダプタによって `serializer.associations(*)` として呼び出されます。）

### オプションのパースの行われ方

高レベルの概要:

- **コレクション**について
  - `:serializer` はコレクションに対するシリアライザを指定します。
  - `:each_serializer` はコレクションの中の各シリアライザを指定します。
- **単独のリソース**においては、`:serializer` オプションはそのリソースのシリアライザです。
- オプションはシリアライザのオプションとアダプタのオプションに別けられます。アダプタオプションのキーは [`ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model_serializers/serializable_resource.rb#L5) から指定されます。残りのオプションはすべてシリアライザのオプションです。

詳細:

1. **ActionController::Serialization**
  1. `serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)`
    1. `options` are partitioned into `adapter_opts` and everything else (`serializer_opts`).`options` は `adapter_opts` とその他（`serializer_opts`）に別れている。`adapter_opts` のキーは [`ActiveModelSerializers::SerializableResource::ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model_serializers/serializable_resource.rb#L5) に定義されている。
1. **ActiveModelSerializers::SerializableResource**
  1. `if serializable_resource.serializer?` (シリアライザが存在し、アダプタが使用されている)
    - そこでは `serializer?` は `use_adapter? && !!(serializer)` を行なっています。
      - `use_adapter?`: 明示的なアダプタが与えられていないとき、あるいは明示的な値が truthy のときに True を返す。明示的なアダプタが falsy のときに False を返す。
      - `serializer`:
          1. 明示的に `:serializer` オプションで指定したシリアライザ。
          2. 暗黙的に `ActiveModel::Serializer.serializer_for(resource)` から来るシリアライザ
  1. `serializer` を確認することを副次効果:
     - `:serializer` オプションは serializer_opts ハッシュから除去されます。
     - `:each_serializer` オプションがあるとき、`:each_serializer` オプションは除去されて `:serializer` として設定されます。
  1. シリアライザとアダプタは下記のように作成されます。
      1. `serializer_instance = serializer.new(resource, serializer_opts)`
      2. `adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)`
1. **ActiveModel::Serializer::CollectionSerializer#new**
  1. `serializer_instance` が `CollectionSerializer` で `:serializer` オプションが存在するとき、[そのシリアライザは各リソースに渡されます。](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model/serializer/collection_serializer.rb#L77-L79)
1. **ActiveModel::Serializer#attributes** はシリアライザに定義されたリソースの属性をアダプタによって取得するために使用されます。

(Rails では、Rails の JSON レンダリングによるリソースのシリアライズ化において `as_json(options)` あるいは `to_json(options)` メソッドにも `options` は 渡されます。ActiveModelSerializers の機能ではないですがこのことについて知っておくことは重要です。)

### 「シリアライズ可能なリソース」とはどのようなものか？

- `ActiveRecord::Base`オブジェクト。
- [Lint](https://www.rubydoc.info/gems/active_model_serializers/ActiveModel/Serializer/Lint/Tests)
  [(code)](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model/serializer/lint.rb) 渡す任意の Ruby オブジェクト

ActiveModelSerializers は [`ActiveModelSerializers::Model`](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/lib/active_model_serializers/model.rb) を提供しています。それはシンプルなシリアライズ可能な PORO (Plain-Old Ruby Object) です。

`ActiveModelSerializers::Model` は参考実装としてもあるいは本番コードの中でも使うことができます。

```ruby
class MyModel < ActiveModelSerializers::Model
  attributes :id, :name, :level
end
```

`MyModel` が ActiveRecord::Base オブジェクトかどうかに関わらず、`MyModel` のデフォルトのシリアライザは `MyModelSerializer` になります。

コントローラの外では、それらのルールはレコードの場合と**まったく**同じです。

```ruby
render json: MyModel.new(level: 'awesome'), adapter: :json
```

は下記と同様にシリアライズされます。

```ruby
ActiveModelSerializers::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
```

## Semantic Versioning

This project adheres to [semver](https://semver.org/)

## Contributing

See [CONTRIBUTING.md](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/CONTRIBUTING.md)