概要
gem active_model_serializers の version 0-10-stable のドキュメントを翻訳しました。
Rails で API を作成するときに active_model_serializers を使うことも多いと思うので、参考になれば幸いです。
-
翻訳について
-
ライセンスについて
- active model serializers のライセンスと同様に、MIT ライセンスに従います。
目次
Adapters
ActiveModelSerializers は、グローバルに、またはシリアライズするとき(通常はレンダリング時)に、どのアダプタを使用するかを設定する機能を提供します。
グローバルなアダプタ設定は ActiveModelSerializers.config
で設定されます。
できれば初期化時に一度だけ設定することが望ましいです。
例
ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonApi
ActiveModelSerializers.config.adapter = :json_api
ActiveModelSerializers.config.adapter = :json
ローカルのアダプタのオプションは adapter: adapter
の形式で記載されます。adapter
にはグローバル設定と同じ値が入ります。
Advanced adapter configuration に記載されているように、設定されたアダプタは、シンボル、クラス、またはクラス名として設定できます。
Attributes
アダプタにはルートキーは含まれず、単純にシリアライズされた属性となります。
レスポンスドキュメントにルートキーを含めたい場合は、JSON
または JSON API
アダプタを使用してください。
重要: アダプタ設定は直接使用されるシリアライザのインスタンスには効果がありません。つまり、 UserSerializer.new(user).as_json
は Attributes
アダプタのように振る舞います。推奨する使用方法の詳細については Outside Controller Usage をご覧ください。
Built in Adapters
Attributes(デフォルト)
デフォルトのアダプタで、ルートキーなしで 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 をご覧ください。 - シリアライザの
type
を設定する方法。詳細は Serializers Guide をご覧ください。
特定の規則には従っていません。
出力例
{
"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 における指定フォーマットの version 1.0 に従います。
出力例
{
"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 オプション
どのシリアライザの関連付けがレンダリングされるかは include
オプションを使用して指定できます。include オプションの使用方法は JSON API 仕様の include オプションと同じであり、すべてのアダプタで利用できます。
使用例
render json: @posts, include: ['author', 'comments', 'comments.author']
# or
render json: @posts, include: 'author,comments,comments.author'
include
オプションの形式は下記のいずれかです。
- リレーションパスのカンマ区切りのリストで構成される文字列
- シンボルとハッシュの配列
- その2つの組み合わせ
空の文字列または空の配列は、関連付けのレンダリングを防ぎます。
さらに、2種類のワイルドカードを使用できます。
-
*
は1レベルの関連付けを含みます。 -
**
すべての関連付けを再帰的に含みます。
ワイルドカードは他のパスと組み合わせることができます。
render json: @posts, include: '**' # or '*' for a single layer
下記はポストをレンダリングして 次のリソースを include しています。
- author
- author の comments
- author の comments によって参照されるすべてのリソース(再帰的)
上記のように、任意の組み合わせで他のパスと組み合わせることができます。
render json: @posts, include: 'author.comments.**'
注意: ワイルドカードは ActiveModelSerializer 固有のものであり、JSON API 仕様の一部ではありません。
JSON API アダプタのデフォルトの include は、関連付けの設定がありません。 JSON および Attributes アダプタのデフォルトは、すべての関連付けが設定されています。
JSON API アダプタの場合、関連するリソースは "included"
項目に集められます。JSON アダプタと Attributes アダプタの場合は、関連するリソースは属性の中でレンダリングされます。
JSON API アダプタのみ、関連付けられたリソースのどの属性がレンダリングされるかを指定することができます。この機能は sparse fieldset と呼ばれています。
render json: @posts, include: 'comments', fields: { comments: ['content', 'created_at'] }
セキュリティに関する考慮事項
含まれるオプションはクエリパラメータから取得される可能性があるため(つまりユーザーがコントロールできる)
render json: @posts, include: params[:include]
ユーザーは include=**
を渡すことができます。
ユーザーが指定する include を適切にフィルタリングすることをお勧めします。
高度なアダプタの設定
アダプタを登録する
上記のように、デフォルトのアダプタは指定したクラスを使用するように設定することができます。
たとえば、レンダリングするときは、アダプタはクラスあるいはシンボルでも指定することができます。
たとえば、:great_example
, ActiveModelSerializers::Adapter::GreatExample
のように、シンボルで指定されたときは、アダプタは登録されたものでなければなりません。
アダプタを登録する2つの方法があります。
- 一番シンプルな方法は
ActiveModelSerializers::Adapter::Base
を継承することです。下記の例はExample::UsefulAdapter
を"example/useful_adapter"
として登録しています。
module Example
class UsefulAdapter < ActiveModelSerializers::Adapter::Base
end
end
登録された名前がアンダースコアのネームスペースとクラスであることに気がつくと思います。
ActiveModelSerializers::Adapter::Base
を継承したとき、秘密裏にそのサブクラスは ("example/useful_adapter" を Example::UsefulAdapter とする)
という風に登録されます。
-
ActiveModelSerializers::Adapter
クラスのregister
メソッドを直接呼び出すことで、どんなクラスでもアダプタとして登録することができます。下記の例では、MyAdapter
を:special_adapter
として登録しています。
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 をご覧ください。
Caching
警告
現在、AMSのキャッシュには問題があります。キャッシュはパフォーマンスを改善しません。キャッシュを行うと、アプリケーションの速度を上昇させるのではなく、速度を低下させる場合があります。本番環境で使用する前に、実装するキャッシュをベンチマークすることをお勧めします。
シリアライザーをキャッシュするには、cache
を呼び出してオプションを渡します。オプションは ActiveSupport::Cache::Store
と同じです。それに加えて、"#{key}/#{object.id}-#{object.updated_at}"
パターンのオブジェクトキャッシュのプレフィックスが入る key
オプションもあります。
キャッシュのサポートは、複数のリクエスト間でキャッシュされたオブジェクトを使用するように最適化されています。show
リクエストでキャッシュされたオブジェクトは index
リクエストで再利用されます。もし別のキャッシュされたシリアライザーとリレーションがある場合は、そのリレーションは自動的に作成および再利用されます。
[注意] すべてのオブジェクトは個別にキャッシュされます。
[注意] キャッシュは、オブジェクトが更新されると自動的に期限切れになりますが、削除されません。
cache(options = nil) # options: ```{key, expires_in, compress, force, race_condition_ttl}```
以下の例をご覧ください。
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
オプションを使用することで、キャッシュを適用する属性を定義することができます。
[注意] キャッシュが適用されるのは自身のリレーションに対してです。
例
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。
設定可能な値:
-
:attributes
(default) :json
:json_api
serializer_lookup_enabled
自動でシリアライザの検索を可能にします。
設定可能な値:
-
true
(デフォルト) false
false
を設定したときは、シリアライザを明示的に指定しなければなりません。
key_transform
使用する key transform。
オプション | 結果 |
---|---|
: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 をご覧ください。
serializer_lookup_chain
シリアライザがどのように検索されるかを設定します。デフォルトでは、ルックアップチェインには下記が設定されています。
ActiveModelSerializers::LookupChain::DEFAULT
これは下記の記述の略記です。
[
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 のnamespace
のどちらかです。
設定例は次の通りになります。
ActiveModelSerializers.config.serializer_lookup_chain = [
lambda do |resource_class, serializer_class, namespace|
"API::#{namespace}::#{resource_class}"
end
]
もしすでに存在するルックアップチェインを追加したいときは、unshift
を使ってください。
ActiveModelSerializers.config.serializer_lookup_chain.unshift(
lambda do |resource_class, serializer_class, namespace|
# ...
end
)
詳細は lookup_chain.rb をご覧ください。
use_sha1_digests
シリアライザをキャッシュするときに内部的に使用するハッシュアルゴリズムを決定します。
設定可能な値:
true
-
false
(デフォルト)
この値が true
のときは、ActiveModelSerializers は SHA1 を使用します。それ以外の場合、デフォルトで MD5 が使用されます。
この値を変更すると、シリアライザのキャッシュが無効になる可能性があることに注意してください。
JSON API
jsonapi_resource_type
シリアライザで明確に指定されていないときに、リソースの type が単数形と複数形のどちらなのかを設定します。
設定可能な値:
:singular
-
:plural
(デフォルト)
jsonapi_namespace_separator
type
属性をレンダリングするために、ネームスペースのあるモデルの区切り文字列を設定してください。
区切り | 例: Admin::User |
---|---|
'-' (デフォルト) |
'admin-users' |
'--' (推奨) |
'admin--users' |
詳細な議論は Recommendation for dasherizing (kebab-case-ing) namespaced object, such as Admin::User
をご覧ください。
jsonapi_include_toplevel_object
レスポンスドキュメントに top level jsonapi member を含める。
設定可能な値:
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 }
)
- only: ホワイトリストの対象となるフィールドの
- ドキュメント:
例
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'
}]
}
}
}
}
オプションを指定せずにドキュメント全体をパースすることができます。
ActiveModelSerializers::Deserialization.jsonapi_parse(document)
#=>
# {
# title: 'Title 1',
# date: '2015-12-20',
# author_id: 2,
# second_author_id: nil
# comment_ids: [3, 4]
# }
フィールド、リレーション、およびポリモーフィックリレーションは、オプションを介して指定することができます。
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
オプションを使用する必要があります。
たとえば、次のようなシリアライザーがあり、
class UserSerializer < ActiveModel::Serializer
attributes :access_token, :first_name, :last_name
end
特定のコントローラーでは、access_token
のみを返したい場合に fields
オプションが役立ちます。
class AnonymousController < ApplicationController
def create
render json: User.create(activation_state: 'anonymous'), fields: [:access_token], status: 201
end
end
これは json
および attributes
アダプタに対してのみ有効であることに注意してください。 json_api
アダプタの場合は下記を使用します。
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
の宣言が記載されます。
以下の例をご覧ください。
class PostSerializer < ActiveModel::Serializer
attributes :title, :body
has_many :comments
has_one :author
end
class CommentSerializer < ActiveModel::Serializer
attributes :name, :body
belongs_to :post
end
宣言されている属性の名前は、シリアライズされるモデルの属性のホワイトリストになります。
has_many
has_one
belongs_to
の宣言はリソース間のリレーションを記述しています。デフォルトでは、Post
をシリアライズすると、Comments
もシリアライズされます。
詳細については、Serializers を参照してください。
ネームスペースのあるモデル
Api::V1::Post
のようなネームスペース内のモデルをシリアライズするとき、ActiveModelSerializers は対応するシリアライザーが同じネームスペースの中(Api::V1::PostSerializer
)にいることを期待します。
モデルの関連とネストされたシリアライザー
次のような関連付けを持つモデルのシリアライザーを宣言する場合
class PostSerializer < ActiveModel::Serializer
has_many :comments
end
ActiveModelSerializers は優先的に PostSerializer::CommentSerializer
を探し、それが見つからない場合は ::CommentSerializer
を探します。これにより、モデルを他のモデルの関連付けとしてシリアライズする方法をより詳細に制御できます。
たとえば、下記をご覧ください。
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
を作成することができます。
class ApplicationSerializer < ActiveModel::Serializer
end
その後、新しく生成されたシリアライザーは自動的に ApplicationSerializer
を継承します。
$ rails g serializer post
下記が生成されたシリアライザーです。
class PostSerializer < ApplicationSerializer
attributes :id
end
Rails との統合
ActiveModelSerializers は Rails アプリと自動的に統合されるので、コントローラーを更新する必要はありません。
下記はコントローラーの例です。
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
を設定してください。
Rails.application.routes.default_url_options = {
host: 'example.com'
}
Instrumentation
ActiveModelSerializers は ActiveSupport::Notification API を使用します。これにより、ロギングなどのイベントを購読することができます。
Events
名前
render.active_model_serializers
ペイロード (例)
{
serializer: PostSerializer,
adapter: ActiveModelSerializers::Adapter::Attributes
}
購読
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
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
のインスタンスがデフォルトのロガーになります。
たとえば下記のように、イニシャライザでロガーをカスタマイズすることもできます。
ActiveModelSerializers.logger = Logger.new(STDOUT)
config/initializers/active_model_serializers.rb
に下記を記載することで、ロガーを無効にすることもできます。
require 'active_model_serializers'
ActiveSupport::Notifications.unsubscribe(ActiveModelSerializers::Logging::RENDER_EVENT)
Rendering
暗黙のシリアライザ
コントローラーで render :json
を使うとき、Rails はまず最初にオブジェクトのシリアライザを探し、もし利用可能ならそのシリアライザを使用します。
class PostsController < ApplicationController
def show
@post = Post.find(params[:id])
render json: @post
end
end
上記の場合、Rails は PostSerializer
を探し、それが存在する場合は、そのシリアライザを使用して Post
をシリアライズします。
明示的なシリアライザ
もしデフォルト以外のシリアライザを使いたいときは、render メソッドに明示的にシリアライザを渡すことができます。
1. 単一のリソース
render json: @post, serializer: PostPreviewSerializer
2. リソースのコレクション
各々のリソースに対して each_serializer
でシリアライザを指定してください。
render json: @posts, each_serializer: PostPreviewSerializer
コレクションのデフォルトのシリアライザは CollectionSerializer
です。
serializer
オプションでコレクションシリアライザを指定してください。
render json: @posts, serializer: CollectionSerializer, each_serializer: PostPreviewSerializer
non-ActiveRecord オブジェクトのシリアライズ
README をご覧ください。
SerializableResource options
README をご覧ください。
adapter_opts
fields
json
または attributes
アダプタを使用している場合、 fields オプションを使用できます。
render json: @user, fields: [:access_token]
詳細は Fields をご覧ください。
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 をご覧ください。
meta
meta
項目は非標準のメタ情報を含むために使用することができます。meta
はレスポンスにおいていくつかの水準で利用されます。
トップレベル
レスポンスでトップレベルの meta
を設定するときは、render
の呼び出し時に meta
を指定してください。
render json: @post, meta: { total: 10 }
meta_key
オプションを使用することでキーをカスタマイズすることができます。
render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
JsonApi
や Json
アダプタのように root
をサポートするアダプタを使用するときのみ、レスポンスに meta
は含まれます。デフォルトアダプタである Attributes
は root
を持っていません。
リソースレベル
レスポンスでリソースレベルの meta
を設定するには、シリアライザの中で下記の方法の内の一つを使って meta を定義してください。
単独の静的な文字列の場合
meta stuff: 'value'
ハッシュを含むブロックの場合
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 をサポートしています。render
メソッドでそれを指定することができます。
links_object = {
href: "http://example.com/api/posts",
meta: {
count: 10
}
}
render json: @posts, links: links_object
結果は下記になります。
{
"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 を使用する必要があります。
リソースレベル
シリアライザの中で、下記の方法の内の一つを使ってそれぞれのリンクを定義してください。
静的な文字列の場合。
link :link_name, 'https://example.com/resource'
ブロックの場合。Rails を使うとURLヘルパーを使用することができます。
必ず Rails.application.routes.default_url_options
をアプリケーションに設定してください。
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 をご覧ください。
Overriding the root key
ルートキーのオーバーライドはJSONアダプタのときのみ適用されます。
通常、リソースルートはシリアライズされるリソースのクラス名が使用されます。
たとえば、UserPostSerializer.new(UserPost.new)
はアダプタのコレクション複数化ルールに応じて、user_post
または user_posts
をルートとしてシリアライズされます。
イニシャライザで JSON アダプタを使用するとき(ActiveModelSerializers.config.adapter = :json)、あるいは、render メソッドの呼び出し時に JSON アダプタを渡すと、render
の引数としてルートキーを渡すことができます。
例
render json: @user_post, root: "admin_post", adapter: :json
これは下記のようにレンダリングされます。
{
"admin_post": {
"title": "how to do open source"
}
}
注意: デフォルトである Attributes
アダプタはリソースルートを含みません。 :json_api アダプタを使用するときも単独のトップレベルのルートを作成することはできません。
namespace
シリアライザの検索に使用されるネームスペースはコントローラーがもとになっています。
暗黙的なネームスペースを設定するために、コントローラーに before filter を作成してください。
before_action do
self.namespace_for_serializer = Api::V2
end
namespace
オプションを render メソッドに渡すことができます。
@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
デフォルトではないシリアライザを使いたいときは、使用するシリアライザを指定してください。
単独のリソースのとき:
@post = Post.first
render json: @post, serializer: SpecialPostSerializer
コレクションのにおいて個々のアイテムに使うシリアライザを指定するときは(たとえば index
アクションのとき)、 each_serializer
を使用してください。
@posts = Post.all
render json: @posts, each_serializer: SpecialPostSerializer
scope
Serializers: Scope をご覧ください。
scope_name
Serializers: Scope をご覧ください。
render
メソッドなしのシリアライザの使用
Usage outside of a controller をご覧ください。
ページネイション
How to add pagination links をご覧ください。
Serializers
シリアライザクラスが与えられた場合
class SomeSerializer < ActiveModel::Serializer
end
下記のメソッドを定義できます。
属性
::attributes メソッド
リソースの title
と body
のシリアライズ化
シリアライザの記載 | #attributes メソッドの返り値 |
---|---|
attributes :title, :body |
{ title: 'Some Title', body: 'Some Body' } |
attributes :title, :body 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 def title 'A Different Title' end
|
{ title: 'A Different Title' } |
if
あるいは unless
オプションは属性を条件付きにすることができます。if, unless はシリアライザのメソッド名のシンボル、あるいはラムダリテラルを受け取ります。
例
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 をご覧ください。
-
- 任意:
&block
は関連付けの属性を返すコンテキストです。-
association_name
メソッドが呼び出されるのを防ぎます。 - ブロックの戻り値は関連付けの値として使用されます。
- ブロックに
serializer
を生成する。 - JSON API の関連付けにおいて
include_data false
はdata
キーがレンダリングされることを防ぐ。
-
::has_one メソッド
例
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
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 メソッド
例
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 メソッド
例
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
ポリモーフィックリレーション
ポリモーフィックリレーションは、他の関連付けのようにリレーションを指定することでシリアライズされます。以下の例をご覧ください。
class PictureSerializer < ActiveModel::Serializer
has_one :imageable
end
overriding serializer_for を行うことによって、シリアライザを指定することができます。ポリモーフィックリレーションの詳細については、各アダプタの tests をご覧ください。
キャッシュ
::cache メソッド
例
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 メソッド
例
# Uses a custom non-time-based cache key
def cache_key
"#{self.class.name.downcase}/#{self.id}"
end
その他
::type メソッド
:json_api
アダプタを使用するとき、::type
メソッドはシリアライザでレンダリングされる JSONAPI type を定義します。
:json
アダプタを使用するとき、::type
メソッドはルートキーの名前を定義します。
::type
メソッドは String
と Symbol
のどちらもパラメーターとして受け取ります。
注意: このメソッドは、:json_api
あるいは :json
アダプタを使用する場合にのみ役立ちます。
例
class UserProfileSerializer < ActiveModel::Serializer
type 'profile'
attribute :name
end
class AuthorProfileSerializer < ActiveModel::Serializer
type :profile
attribute :name
end
:json_api
アダプタの場合、上記のシリアライザは下記のようにレンダリングされます。
{
"data": {
"id": "1",
"type": "profile",
"attributes": {
"name": "Julia"
}
}
}
:json
アダプタの場合、上記のシリアライザは下記のようにレンダリングされます。
{
"profile": {
"name": "Julia"
}
}
::link メソッド
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 はオプションのコンディションをサポートします。
link(:secret, if: :internal?) { object.secret_link }
def internal?
instance_options[:context] == :internal
end
#object メソッド
シリアライズされているオブジェクトを返します。
#root メソッド
JSON
アダプタに含まれるリソースルートを返します。Adapters Document にあるように、Attribute
アダプタ(デフォルト)と JSON API
アダプタはトップレベルにルートキーを含みません。
デフォルトでは、リソースルートはシリアライズされるオブジェクトクラスの model_name
から生成されます。
ルートを指定する方法はいくつかあります:
- Overriding the root key
- Setting
type
-
root: 'specific_name'
のようにシリアライザの初期化をするときに、root
オプションを指定する。
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
|
スコープを利用して、カレントユーザーに関連するオブジェクトをカスタマイズできます。
たとえば、現在のユーザーに表示される投稿を、そのユーザーが作成した投稿に制限することができます。
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 と同じです。
デフォルトでは、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でも問題となっていました。
current_user
から view_context
にスコープを変更することができます。この変更は ActionController::Base
のサブクラスに記載されます。
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
メソッドを使用できます。
class AdminUserSerializer < ActiveModel::Serializer
attributes :id, :name, :can_edit
def can_edit?
+ view_context.current_user.admin?
end
end
#edit
アクションをレンダリングすると下記の結果が得られます。
{"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
を使用しています。
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 メソッドを使用して設定された属性が入力されます。links: nil
を使用することで、links
ノードを除去します。
ActiveModelSerializers::SerializableResource.new(
@post,
adapter: :json_api,
links: {
self: {
href: 'http://example.com/posts',
meta: {
stuff: 'value'
}
}
}
)
#json_key メソッド
リソースルートとしてアダプタに使用されるキーを返します。詳細は、root をご覧ください。
例
Post(title: string, body: text)
と Comment(name: string, body: text, post_id: integer)
の2つのモデルがあるとき、2つのシリアライザを作成することになります。
class PostSerializer < ActiveModel::Serializer
cache key: 'posts', expires_in: 3.hours
attributes :title, :body
has_many :comments
end
class CommentSerializer < ActiveModel::Serializer
attributes :name, :body
belongs_to :post
end
一般的な ActiveModelSerializers の使い方としては、これらのシリアライザのクラスを記載・生成します。
詳細情報
詳細は the Serializer class on GitHub をご覧ください。
関連付けメソッドのオーバーライド
関連付けをオーバーライドするには、ブロックと一緒に has_many
, has_one
, belongs_to
を呼び出します。
class PostSerializer < ActiveModel::Serializer
has_many :comments do
object.comments.active
end
end
属性メソッドのオーバーライド
属性をオーバーライドするには、ブロックと一緒に attribute
を呼び出します。
class PostSerializer < ActiveModel::Serializer
attribute :body do
object.body.downcase
end
end
関連付けられたシリアライザ検索のオーバーライド
関連付けのために特定のシリアライザの検索を定義したいときは、ActiveModel::Serializer.serializer_for
メソッドをオーバーライドすることで定義した条件に基づいてシリアライザクラスを返すことができます。
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 で指定された バージョン1.0の形式に追従する JsonApi アダプタ を使用することを強く勧めます。
下記のセクションでアダプタの変更方法を確認してください。
0.10.x
は 0.9.x
と 0.8.x
と後方互換性はありません。
0.10.x
は 0.8.0
のコードをもとにしていますが、より柔軟なアーキテクチャーを持っています。私たちはあなたの手助けを歓迎します。貢献の仕方。
インストール
下記の行を Gemfile に追加してください。
gem 'active_model_serializers', '~> 0.10.0'
そして下記を実行してください:
$ bundle
入門
基礎的なことについては Getting Started をご覧ください。
詳細情報は Guides と High-level behavior に記載されています。
Getting Help
もしバグを見つけた場合は、 Issue を報告して contributing guide を見てください。
質問があるときは、Stack Overflow に投稿してください.
チャットで話したいときは、community slack に参加してください。
ドキュメント
もし https://github.com/rails-api/active_model_serializers でこの文章を読んでいるなら、あなたは master
ブランチのドキュメントを読んでいます。master
ブランチ はまだリリースされていない機能を含んでいる可能性があります。関連するドキュメントについては、以下をご覧ください。
- 0.10 (0-10-stable) Documentation
- 0.10.10 (latest release) Documentation
- 0.9 (0-9-stable) Documentation
- 0.8 (0-8-stable) Documentation
高レベルの動作
adapters からアダプタを選択してください。
ActiveModelSerializers.config.adapter = :json_api # Default: `:attributes`
シリアライズ可能なモデル が与えられた場合。
# either
class SomeResource < ActiveRecord::Base
# columns: title, body
end
# or
class SomeResource < ActiveModelSerializers::Model
attributes :title, :body
end
下記のようにイニシャライズします。
resource = SomeResource.new(title: 'ActiveModelSerializers', body: 'Convention over configuration')
シリアライズ可能なモデルのシリアライザが与えられた場合、
class SomeSerializer < ActiveModel::Serializer
attribute :title, key: :name
attributes :body
end
モデルは下記のようにシリアライズされます。
options = {}
serialization = ActiveModelSerializers::SerializableResource.new(resource, options)
serialization.to_json
serialization.as_json
SerializableResource はアダプタに移譲を行い、アダプタは下記のように構築します。
adapter_options = {}
adapter = ActiveModelSerializers::Adapter.create(serializer, adapter_options)
adapter.to_json
adapter.as_json
adapter.serializable_hash
アダプタはシリアライザの属性と関連付けを構成します(別名 includes)。
serializer_options = {}
serializer = SomeSerializer.new(resource, serializer_options)
serializer.attributes
serializer.associations
アーキテクチャ
このセクションは ActiveModelSerializers の 0.10.x バージョンのアーキテクチャに焦点を当てています。
もし 0.8 あるいは 0.9 のバージョンに興味がある場合は、0.8 README ,
0.9 README を参照してください。
オリジナルの文章はこちらでも見ることができます。
ActiveModel::Serializer
ActiveModel::Serializer
は シリアライズ可能なリソース をラップし、attributes
メソッドなどを使えるようにします。
ActiveModel::Serializer はリソースのシリアライズにおいてどの属性と関連付けを表すかを指定します。
ActiveModel::Serializer はアダプタに自身の属性を JSON ドキュメントに変換するように要求します。ActiveModel::Serializer だけではシリアライズを行うことはできません。
アダプタを presenter として考えると良いかもしれません。
ActiveModel::CollectionSerializer
ActiveModel::CollectionSerializer
はリソースの集合を複数のシリアライザとして表します。もしシリアライザがない場合は基本要素を表します。
ActiveModelSerializers::Adapter::Base
ActiveModelSerializers::Adapter::Base
はシリアライザから生成された JSON ドキュメントの構造を記述します。たとえば、Attributes
アダプタは各シリアライザを未変更の属性として表します。JsonApi
アダプタはシリアライザを JSON API ドキュメントとして表します。
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
をスローします。
たとえば、Reflection#build_association
によってキャッチされ、関連付けの値が直接設定されたときです。
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
(これはアダプタによって serializer.associations(*)
として呼び出されます。)
オプションのパースの行われ方
高レベルの概要:
-
コレクションについて
-
:serializer
はコレクションに対するシリアライザを指定します。 -
:each_serializer
はコレクションの中の各シリアライザを指定します。
-
-
単独のリソースにおいては、
:serializer
オプションはそのリソースのシリアライザです。 - オプションはシリアライザのオプションとアダプタのオプションに別けられます。アダプタオプションのキーは
ADAPTER_OPTION_KEYS
から指定されます。残りのオプションはすべてシリアライザのオプションです。
詳細:
- ActionController::Serialization
-
serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)
1.options
are partitioned intoadapter_opts
and everything else (serializer_opts
).options
はadapter_opts
とその他(serializer_opts
)に別れている。adapter_opts
のキーはActiveModelSerializers::SerializableResource::ADAPTER_OPTION_KEYS
に定義されている。 - ActiveModelSerializers::SerializableResource
-
if serializable_resource.serializer?
(シリアライザが存在し、アダプタが使用されている)
- そこではserializer?
はuse_adapter? && !!(serializer)
を行なっています。-
use_adapter?
: 明示的なアダプタが与えられていないとき、あるいは明示的な値が truthy のときに True を返す。明示的なアダプタが falsy のときに False を返す。 -
serializer
:- 明示的に
:serializer
オプションで指定したシリアライザ。 - 暗黙的に
ActiveModel::Serializer.serializer_for(resource)
から来るシリアライザ
- 明示的に
-
-
serializer
を確認することを副次効果:-
:serializer
オプションは serializer_opts ハッシュから除去されます。 -
:each_serializer
オプションがあるとき、:each_serializer
オプションは除去されて:serializer
として設定されます。
-
- シリアライザとアダプタは下記のように作成されます。
serializer_instance = serializer.new(resource, serializer_opts)
adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)
- ActiveModel::Serializer::CollectionSerializer#new
-
serializer_instance
がCollectionSerializer
で:serializer
オプションが存在するとき、そのシリアライザは各リソースに渡されます。 - ActiveModel::Serializer#attributes はシリアライザに定義されたリソースの属性をアダプタによって取得するために使用されます。
(Rails では、Rails の JSON レンダリングによるリソースのシリアライズ化において as_json(options)
あるいは to_json(options)
メソッドにも options
は 渡されます。ActiveModelSerializers の機能ではないですがこのことについて知っておくことは重要です。)
「シリアライズ可能なリソース」とはどのようなものか?
ActiveModelSerializers は ActiveModelSerializers::Model
を提供しています。それはシンプルなシリアライズ可能な PORO (Plain-Old Ruby Object) です。
ActiveModelSerializers::Model
は参考実装としてもあるいは本番コードの中でも使うことができます。
class MyModel < ActiveModelSerializers::Model
attributes :id, :name, :level
end
MyModel
が ActiveRecord::Base オブジェクトかどうかに関わらず、MyModel
のデフォルトのシリアライザは MyModelSerializer
になります。
コントローラの外では、それらのルールはレコードの場合とまったく同じです。
render json: MyModel.new(level: 'awesome'), adapter: :json
は下記と同様にシリアライズされます。
ActiveModelSerializers::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
Semantic Versioning
This project adheres to semver
Contributing
See CONTRIBUTING.md