mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
We discussed this previously, but I think it's time for the mailing list to be removed from the README. Every day more discussion, issues, and pull requests happen here then ever before. The mailing list is not representative of this activity and only dilutes the purpose of the blossoming community we're finding here. A related note: I think we should actively encourage folks to ask questions on StackOverflow with the AMS tag, and put some documentation in here about that. I can open a separate PR for this later, but it would require more than a few of us to actively monitor SO and help where we can. If we successfully do this, then I think we effectively cover all the use cases the mailing list originally may have had.
309 lines
7.7 KiB
Markdown
309 lines
7.7 KiB
Markdown
# ActiveModel::Serializers
|
|
|
|
[](https://travis-ci.org/rails-api/active_model_serializers)
|
|
|
|
ActiveModel::Serializers brings convention over configuration to your JSON generation.
|
|
|
|
AMS does this through two components: **serializers** and **adapters**. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.
|
|
|
|
# MAINTENANCE, PLEASE READ
|
|
|
|
This is the master branch of AMS. It will become the `0.10.0` release when it's
|
|
ready, but it's not. You probably don't want to use it yet. As such, we recommend
|
|
that any new projects you start use the latest `0.8.x` version of this gem. This
|
|
version is the most widely used, and will most closely resemble the forthcoming release.
|
|
|
|
There are two released versions of AMS that you may want to use: `0.9.x` and
|
|
`0.8.x`. `9` was recently `master`, so if you were using master, you probably want
|
|
to use it. `8` was the version that was on RubyGems, so if you were using that,
|
|
that's probably what you want.
|
|
|
|
`0.10.x` will be based on the `0.8.0` code, but with a more flexible
|
|
architecture. We'd love your help. [Learn how you can help here.](https://github.com/rails-api/active_model_serializers/blob/master/CONTRIBUTING.md)
|
|
|
|
Thanks!
|
|
|
|
## Example
|
|
|
|
Given two models, a `Post(title: string, body: text)` and a
|
|
`Comment(name:string, body:text, post_id:integer)`, you will have two
|
|
serializers:
|
|
|
|
```ruby
|
|
class PostSerializer < ActiveModel::Serializer
|
|
cache key: 'posts', expires_in: 3.hours
|
|
attributes :title, :body
|
|
|
|
has_many :comments
|
|
|
|
url :post
|
|
end
|
|
```
|
|
|
|
and
|
|
|
|
```ruby
|
|
class CommentSerializer < ActiveModel::Serializer
|
|
attributes :name, :body
|
|
|
|
belongs_to :post
|
|
|
|
url [:post, :comment]
|
|
end
|
|
```
|
|
|
|
Generally speaking, you as a user of AMS will write (or generate) these
|
|
serializer classes. If you want to use a different adapter, such as a JsonApi, you can
|
|
change this in an initializer:
|
|
|
|
```ruby
|
|
ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::JsonApi
|
|
```
|
|
|
|
or
|
|
|
|
```ruby
|
|
ActiveModel::Serializer.config.adapter = :json_api
|
|
```
|
|
|
|
You won't need to implement an adapter unless you wish to use a new format or
|
|
media type with AMS.
|
|
|
|
If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:
|
|
|
|
```ruby
|
|
class PostSerializer < ActiveModel::Serializer
|
|
attributes :id, :body
|
|
|
|
# look up :subject on the model, but use +title+ in the JSON
|
|
attribute :subject, :key => :title
|
|
has_many :comments
|
|
end
|
|
```
|
|
|
|
In your controllers, when you use `render :json`, Rails will now first search
|
|
for a serializer for the object and use it if available.
|
|
|
|
```ruby
|
|
class PostsController < ApplicationController
|
|
def show
|
|
@post = Post.find(params[:id])
|
|
|
|
render json: @post
|
|
end
|
|
end
|
|
```
|
|
|
|
In this case, Rails will look for a serializer named `PostSerializer`, and if
|
|
it exists, use it to serialize the `Post`.
|
|
|
|
### Specify a serializer
|
|
|
|
If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.
|
|
|
|
#### 1. For a resource:
|
|
|
|
```ruby
|
|
render json: @post, serializer: PostPreviewSerializer
|
|
```
|
|
|
|
#### 2. For an array resource:
|
|
|
|
```ruby
|
|
# Use the default `ArraySerializer`, which will use `each_serializer` to
|
|
# serialize each element
|
|
render json: @posts, each_serializer: PostPreviewSerializer
|
|
|
|
# Or, you can explicitly provide the collection serializer as well
|
|
render json: @posts, serializer: PaginatedSerializer, each_serializer: PostPreviewSerializer
|
|
```
|
|
|
|
### Meta
|
|
|
|
If you want a `meta` attribute in your response, specify it in the `render`
|
|
call:
|
|
|
|
```ruby
|
|
render json: @post, meta: { total: 10 }
|
|
```
|
|
|
|
The key can be customized using `meta_key` option.
|
|
|
|
```ruby
|
|
render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
|
|
```
|
|
|
|
`meta` will only be included in your response if there's a root. For instance,
|
|
it won't be included in array responses.
|
|
|
|
### Root key
|
|
|
|
If you want to define a custom root for your response, specify it in the `render`
|
|
call:
|
|
|
|
```ruby
|
|
render json: @post, root: "articles"
|
|
```
|
|
|
|
### Overriding association methods
|
|
|
|
If you want to override any association, you can use:
|
|
|
|
```ruby
|
|
class PostSerializer < ActiveModel::Serializer
|
|
attributes :id, :body
|
|
|
|
has_many :comments
|
|
|
|
def comments
|
|
object.comments.active
|
|
end
|
|
end
|
|
```
|
|
|
|
### Overriding attribute methods
|
|
|
|
If you want to override any attribute, you can use:
|
|
|
|
```ruby
|
|
class PostSerializer < ActiveModel::Serializer
|
|
attributes :id, :body
|
|
|
|
has_many :comments
|
|
|
|
def body
|
|
object.body.downcase
|
|
end
|
|
end
|
|
```
|
|
|
|
### Built in Adapters
|
|
|
|
#### JSONAPI
|
|
|
|
This adapter follows the format specified in
|
|
[jsonapi.org/format](http://jsonapi.org/format). It will include the associated
|
|
resources in the `"linked"` member when the resource names are included in the
|
|
`include` option.
|
|
|
|
```ruby
|
|
render @posts, include: ['authors', 'comments']
|
|
# or
|
|
render @posts, include: 'authors,comments'
|
|
```
|
|
|
|
## Installation
|
|
|
|
Add this line to your application's Gemfile:
|
|
|
|
```
|
|
gem 'active_model_serializers'
|
|
```
|
|
|
|
And then execute:
|
|
|
|
```
|
|
$ bundle
|
|
```
|
|
|
|
## Creating a Serializer
|
|
|
|
The easiest way to create a new serializer is to generate a new resource, which
|
|
will generate a serializer at the same time:
|
|
|
|
```
|
|
$ rails g resource post title:string body:string
|
|
```
|
|
|
|
This will generate a serializer in `app/serializers/post_serializer.rb` for
|
|
your new model. You can also generate a serializer for an existing model with
|
|
the serializer generator:
|
|
|
|
```
|
|
$ rails g serializer post
|
|
```
|
|
|
|
The generated seralizer will contain basic `attributes` and
|
|
`has_many`/`has_one`/`belongs_to` declarations, based on the model. For example:
|
|
|
|
```ruby
|
|
class PostSerializer < ActiveModel::Serializer
|
|
attributes :title, :body
|
|
|
|
has_many :comments
|
|
has_one :author
|
|
|
|
url :post
|
|
end
|
|
```
|
|
|
|
and
|
|
|
|
```ruby
|
|
class CommentSerializer < ActiveModel::Serializer
|
|
attributes :name, :body
|
|
|
|
belongs_to :post_id
|
|
|
|
url [:post, :comment]
|
|
end
|
|
```
|
|
|
|
The attribute names are a **whitelist** of attributes to be serialized.
|
|
|
|
The `has_many`, `has_one`, and `belongs_to` declarations describe relationships between
|
|
resources. By default, when you serialize a `Post`, you will get its `Comment`s
|
|
as well.
|
|
|
|
You may also use the `:serializer` option to specify a custom serializer class, for example:
|
|
|
|
```ruby
|
|
has_many :comments, serializer: CommentPreviewSerializer
|
|
```
|
|
|
|
The `url` declaration describes which named routes to use while generating URLs
|
|
for your JSON. Not every adapter will require URLs.
|
|
|
|
## Caching
|
|
|
|
To cache a serializer, call ```cache``` and pass its options.
|
|
The options are the same options of ```ActiveSupport::Cache::Store```, plus
|
|
a ```key``` option that will be the prefix of the object cache
|
|
on a pattern ```"#{key}/#{object.id}-#{object.updated_at}"```.
|
|
|
|
**[NOTE] Every object is individually cached.**
|
|
**[NOTE] The cache is automatically expired after update an object but it's not deleted.**
|
|
|
|
```ruby
|
|
cache(options = nil) # options: ```{key, expires_in, compress, force, race_condition_ttl}```
|
|
```
|
|
|
|
Take the example bellow:
|
|
|
|
```ruby
|
|
class PostSerializer < ActiveModel::Serializer
|
|
cache key: 'post', expires_in: 3.hours
|
|
attributes :title, :body
|
|
|
|
has_many :comments
|
|
|
|
url :post
|
|
end
|
|
```
|
|
|
|
On this example every ```Post``` object will be cached with
|
|
the key ```"post/#{post.id}-#{post.updated_at}"```. You can use this key to expire it as you want,
|
|
but in this case it will be automatically expired after 3 hours.
|
|
|
|
## Getting Help
|
|
|
|
If you find a bug, please report an [Issue](https://github.com/rails-api/active_model_serializers/issues/new).
|
|
|
|
If you have a question, please [post to Stack Overflow](http://stackoverflow.com/questions/tagged/active-model-serializers).
|
|
|
|
Thanks!
|
|
|
|
# Contributing
|
|
|
|
See [CONTRIBUTING.md](https://github.com/rails-api/active_model_serializers/blob/master/CONTRIBUTING.md)
|