README.md in active_model_serializers-0.9.13 vs README.md in active_model_serializers-0.10.0.rc1
- old
+ new
@@ -1,956 +1,326 @@
-[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png?branch=0-9-stable)](https://travis-ci.org/rails-api/active_model_serializers)
-[![Code Climate](https://codeclimate.com/github/rails-api/active_model_serializers.png)](https://codeclimate.com/github/rails-api/active_model_serializers)
-
# ActiveModel::Serializers
-## Purpose
+[![Build Status](https://travis-ci.org/rails-api/active_model_serializers.svg)](https://travis-ci.org/rails-api/active_model_serializers)
-`ActiveModel::Serializers` encapsulates the JSON serialization of objects.
-Objects that respond to read\_attribute\_for\_serialization
-(including `ActiveModel` and `ActiveRecord` objects) are supported.
+ActiveModel::Serializers brings convention over configuration to your JSON generation.
-Serializers know about both a model and the `current_user`, so you can
-customize serialization based upon whether a user is authorized to see the
-content.
+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.
-In short, **serializers replace hash-driven development with object-oriented
-development.**
+# RELEASE CANDIDATE, PLEASE READ
-# Installing
+This is the master branch of AMS. It will become the `0.10.0` release when it's
+ready. Currently this is a release candidate. This is **not** backward
+compatible with `0.9.0` or `0.8.0`.
-The easiest way to install `ActiveModel::Serializers` is to add it to your
-`Gemfile`:
+`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)
-```ruby
-gem "active_model_serializers"
-```
+## Example
-Then, install it on the command line:
+Given two models, a `Post(title: string, body: text)` and a
+`Comment(name:string, body:text, post_id:integer)`, you will have two
+serializers:
-```
-$ bundle install
-```
-
-#### Ruby 1.8 is no longer supported!
-
-If you must use a ruby 1.8 version (MRI 1.8.7, REE, Rubinius 1.8, or JRuby 1.8), you need to use version 0.8.x.
-Versions after 0.9.0 do not support ruby 1.8. To specify version 0.8, include this in your Gemfile:
-
```ruby
-gem "active_model_serializers", "~> 0.8.0"
-```
-
-
-# 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
-```
-
-### Support for POROs
-
-The PORO should include ActiveModel::SerializerSupport. That's all you need to
-do to have your POROs supported.
-
-For Rails versions before Rails 4 ActiveModel::Serializers expects objects to
-implement `read_attribute_for_serialization`.
-
-# render :json
-
-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`.
-
-This also works with `respond_with`, which uses `to_json` under the hood. Also
-note that any options passed to `render :json` will be passed to your
-serializer and available as `@serialization_options` inside.
-
-To specify a custom serializer for an object, you can specify the
-serializer when you render the object:
-
-```ruby
-render json: @post, serializer: FancyPostSerializer
-```
-
-### Use serialization outside of ActionController::Base
-
-When controller does not inherit from ActionController::Base,
-include Serialization module manually:
-
-```ruby
-class ApplicationController < ActionController::API
- include ActionController::Serialization
-end
-```
-
-## Arrays
-
-In your controllers, when you use `render :json` for an array of objects, AMS will
-use `ActiveModel::ArraySerializer` (included in this project) as the base serializer,
-and the individual `Serializer` for the objects contained in that array.
-
-```ruby
class PostSerializer < ActiveModel::Serializer
+ cache key: 'posts', expires_in: 3.hours
attributes :title, :body
-end
-class PostsController < ApplicationController
- def index
- @posts = Post.all
- render json: @posts
- end
-end
-```
+ has_many :comments
-Given the example above, the index action will return
-
-```json
-{
- "posts":
- [
- { "title": "Post 1", "body": "Hello!" },
- { "title": "Post 2", "body": "Goodbye!" }
- ]
-}
-```
-
-By default, the root element is the name of the controller. For example, `PostsController`
-generates a root element "posts". To change it:
-
-```ruby
-render json: @posts, root: "some_posts"
-```
-
-You may disable the root element for arrays at the top level, which will result in
-more concise json. See the next section for ways on how to do this. Disabling the
-root element of the array with any of those methods will produce
-
-```json
-[
- { "title": "Post 1", "body": "Hello!" },
- { "title": "Post 2", "body": "Goodbye!" }
-]
-```
-
-To specify a custom serializer for the items within an array:
-
-```ruby
-render json: @posts, each_serializer: FancyPostSerializer
-```
-
-## Render independently
-
-By default the setting of serializer is in controller as described above which is the
-recommended way. However, there may be cases you need to render the json object elsewhere
-say in a helper or a view when controller is only for main object.
-
-Then you can render the serialized JSON independently.
-
-```ruby
-def current_user_as_json_helper
- CurrentUserSerializer.new(current_user).to_json
+ url :post
end
```
-You can also render an array of objects using ArraySerializer.
+and
```ruby
-def users_array_as_json_helper(users)
- ActiveModel::ArraySerializer.new(users, each_serializer: UserSerializer).to_json
-end
-```
+class CommentSerializer < ActiveModel::Serializer
+ attributes :name, :body
+ belongs_to :post
-## Disabling the root element
-
-You have 4 options to disable the root element, each with a slightly different scope:
-
-#### 1. Disable root globally for all, or per class
-
-In an initializer:
-
-```ruby
-# Disable for all serializers (except ArraySerializer)
-ActiveModel::Serializer.root = false
-
-# Disable for ArraySerializer
-ActiveModel::ArraySerializer.root = false
-```
-
-#### 2. Disable root per render call in your controller
-
-```ruby
-render json: @posts, root: false
-```
-
-#### 3. Subclass the serializer, and specify using it
-
-```ruby
-class CustomArraySerializer < ActiveModel::ArraySerializer
- self.root = false
+ url [:post, :comment]
end
-
-# controller:
-render json: @posts, serializer: CustomArraySerializer
```
-#### 4. Define default_serializer_options in your controller
+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:
-If you define `default_serializer_options` method in your controller,
-all serializers in actions of this controller and it's children will use them.
-One of the options may be `root: false`
-
```ruby
-def default_serializer_options
- {
- root: false
- }
-end
+ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::JsonApi
```
-## Changing the Key Format
+or
-You can specify that serializers use the lower-camel key format at the config, class or instance level.
-
```ruby
-
-ActiveModel::Serializer.setup do |config|
- config.key_format = :lower_camel
-end
-
-class BlogLowerCamelSerializer < ActiveModel::Serializer
- format_keys :lower_camel
-end
-
-BlogSerializer.new(object, key_format: :lower_camel)
+ActiveModel::Serializer.config.adapter = :json_api
```
-## Changing the default association key type
+You won't need to implement an adapter unless you wish to use a new format or
+media type with AMS.
-You can specify that serializers use unsuffixed names as association keys by default.
+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
-ActiveModel::Serializer.setup do |config|
- config.default_key_type = :name
-end
-```
-
-This will build association keys like `comments` or `author` instead of `comment_ids` or `author_id`.
-
-## Getting the old version
-
-If you find that your project is already relying on the old rails to_json
-change `render :json` to `render json: @your_object.to_json`.
-
-# Attributes and Associations
-
-Once you have a serializer, you can specify which attributes and associations
-you would like to include in the serialized form.
-
-```ruby
class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
+ attributes :id, :body
+
+ # look up :subject on the model, but use +title+ in the JSON
+ attribute :subject, :key => :title
has_many :comments
end
```
-## Attributes
+In your controllers, when you use `render :json`, Rails will now first search
+for a serializer for the object and use it if available.
-For specified attributes, a serializer will look up the attribute on the
-object you passed to `render :json`. It uses
-`read_attribute_for_serialization`, which `ActiveRecord` objects implement as a
-regular attribute lookup.
-
-Before looking up the attribute on the object, a serializer will check for the
-presence of a method with the name of the attribute. This allows serializers to
-include properties beyond the simple attributes of the model. For example:
-
```ruby
-class PersonSerializer < ActiveModel::Serializer
- attributes :first_name, :last_name, :full_name
+class PostsController < ApplicationController
+ def show
+ @post = Post.find(params[:id])
- def full_name
- "#{object.first_name} #{object.last_name}"
+ render json: @post
end
end
```
-Within a serializer's methods, you can access the object being
-serialized as `object`.
+In this case, Rails will look for a serializer named `PostSerializer`, and if
+it exists, use it to serialize the `Post`.
-Since this shadows any attribute named `object`, you can include them through `object.object`. For example:
+### Specify a serializer
-```ruby
-class VersionSerializer < ActiveModel::Serializer
- attributes :version_object
+If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.
- def version_object
- object.object
- end
-end
-```
+#### 1. For a resource:
-You can also access the `scope` method, which provides an
-authorization context to your serializer. By default, the context
-is the current user of your application, but this
-[can be customized](#customizing-scope).
-
-Serializers provide a method named `filter`, which should return an array
-used to determine what attributes and associations should be included in the output.
-This is typically used to customize output based on `current_user`. For example:
-
```ruby
-class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body, :author
-
- def filter(keys)
- if scope.admin?
- keys
- else
- keys - [:author]
- end
- end
-end
+ render json: @post, serializer: PostPreviewSerializer
```
-And it's also safe to mutate keys argument by doing keys.delete(:author)
-in case you want to avoid creating two extra arrays. Note that if you do an
-in-place modification, you still need to return the modified array.
+#### 2. For an array resource:
-### Alias Attribute
-If you would like the key in the outputted JSON to be different from its name
-in ActiveRecord, you can declare the attribute with the different name
-and redefine that method:
-
```ruby
-class PostSerializer < ActiveModel::Serializer
- # look up subject on the model, but use title in the JSON
- def title
- object.subject
- end
+# Use the default `ArraySerializer`, which will use `each_serializer` to
+# serialize each element
+render json: @posts, each_serializer: PostPreviewSerializer
- attributes :id, :body, :title
- has_many :comments
-end
+# Or, you can explicitly provide the collection serializer as well
+render json: @posts, serializer: PaginatedSerializer, each_serializer: PostPreviewSerializer
```
-If you would like to add meta information to the outputted JSON, use the `:meta`
-option:
+### Meta
+If you want a `meta` attribute in your response, specify it in the `render`
+call:
+
```ruby
-render json: @posts, serializer: CustomArraySerializer, meta: {total: 10}
+render json: @post, meta: { total: 10 }
```
-The above usage of `:meta` will produce the following:
+The key can be customized using `meta_key` option.
-```json
-{
- "meta": { "total": 10 },
- "posts": [
- { "title": "Post 1", "body": "Hello!" },
- { "title": "Post 2", "body": "Goodbye!" }
- ]
-}
-```
-
-If you would like to change the meta key name you can use the `:meta_key` option:
-
```ruby
-render json: @posts, serializer: CustomArraySerializer, meta_object: { total: 10 }, meta_key: :meta_object
+render json: @post, meta: { total: 10 }, meta_key: "custom_meta"
```
-The above usage of `:meta_key` will produce the following:
+`meta` will only be included in your response if there's a root. For instance,
+it won't be included in array responses.
-```json
-{
- "meta_object": { "total": 10 },
- "posts": [
- { "title": "Post 1", "body": "Hello!" },
- { "title": "Post 2", "body": "Goodbye!" }
- ]
-}
-```
+### Root key
-When using meta information, your serializer cannot have the `{ root: false }` option, as this would lead to
-invalid JSON. If you do not have a root key, the meta information will be ignored.
+If you want to define a custom root for your response, specify it in the `render`
+call:
-If you would like direct, low-level control of attribute serialization, you can
-completely override the `attributes` method to return the hash you need:
-
```ruby
-class PersonSerializer < ActiveModel::Serializer
- attributes :first_name, :last_name
-
- def attributes
- hash = super
- if scope.admin?
- hash["ssn"] = object.ssn
- hash["secret"] = object.mothers_maiden_name
- end
- hash
- end
-end
+render json: @post, root: "articles"
```
-## Associations
+### Overriding association methods
-For specified associations, the serializer will look up the association and
-then serialize each element of the association. For instance, a `has_many
-:comments` association will create a new `CommentSerializer` for each comment
-and use it to serialize the comment.
+If you want to override any association, you can use:
-By default, serializers simply look up the association on the original object.
-You can customize this behavior by implementing a method with the name of the
-association and returning a different Array. Often, you will do this to
-customize the objects returned based on the current user (scope).
-
```ruby
class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
+ attributes :id, :body
+
has_many :comments
- # only let the user see comments he created.
def comments
- object.comments.where(created_by: scope)
+ object.comments.active
end
end
```
-As with attributes, you can change the JSON key that the serializer should
-use for a particular association.
+### Overriding attribute methods
-```ruby
-class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
+If you want to override any attribute, you can use:
- # look up comments, but use +my_comments+ as the key in JSON
- has_many :comments, root: :my_comments
-end
-```
-
-Also, as with attributes, serializers will execute a filter method to
-determine which associations should be included in the output. For
-example:
-
```ruby
class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
+ attributes :id, :body
+
has_many :comments
- def filter(keys)
- keys.delete :comments if object.comments_disabled?
- keys
+ def body
+ object.body.downcase
end
end
```
-Or ...
+### Built in Adapters
-```ruby
-class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
- has_one :author
- has_many :comments
+#### JSONAPI
- def filter(keys)
- keys.delete :author unless scope.admin?
- keys.delete :comments if object.comments_disabled?
- keys
- end
-end
-```
+This adapter follows RC3 of the format specified in
+[jsonapi.org/format](http://jsonapi.org/format). It will include the associated
+resources in the `"included"` member when the resource names are included in the
+`include` option.
-You may also use the `:serializer` option to specify a custom serializer class and the `:polymorphic` option to specify an association that is polymorphic (STI), e.g.:
-
```ruby
- has_many :comments, serializer: CommentShortSerializer
- has_one :reviewer, polymorphic: true
+ render @posts, include: ['authors', 'comments']
+ # or
+ render @posts, include: 'authors,comments'
```
-Serializers are only concerned with multiplicity, and not ownership. `belongs_to` ActiveRecord associations can be included using `has_one` in your serializer.
+## Installation
-## Embedding Associations
+Add this line to your application's Gemfile:
-By default, associations will be embedded inside the serialized object. So if
-you have a post, the outputted JSON will look like:
-
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comments": [
- { "id": 1, "body": "what a dumb post" }
- ]
- }
-}
```
-
-This is convenient for simple use-cases, but for more complex clients, it is
-better to supply an Array of IDs for the association. This makes your API more
-flexible from a performance standpoint and avoids wasteful duplication.
-
-To embed IDs instead of associations, simply use the `embed` class method:
-
-```ruby
-class PostSerializer < ActiveModel::Serializer
- embed :ids
-
- attributes :id, :title, :body
- has_many :comments
-end
+gem 'active_model_serializers'
```
-Now, any associations will be supplied as an Array of IDs:
+And then execute:
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comment_ids": [ 1, 2, 3 ]
- }
-}
```
+$ bundle
+```
-You may also choose to embed the IDs by the association's name underneath a
-`key` for the resource. For example, say we want to change `comment_ids`
-to `comments` underneath a `links` key:
+## Creating a Serializer
-```ruby
-class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
+The easiest way to create a new serializer is to generate a new resource, which
+will generate a serializer at the same time:
- has_many :comments, embed: :ids, key: :comments, embed_namespace: :links
-end
```
-
-The JSON will look like this:
-
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "links": {
- "comments": [ 1, 2, 3 ]
- }
- }
-}
+$ rails g resource post title:string body:string
```
-Alternatively, you can choose to embed only the ids or the associated objects per association:
+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:
-```ruby
-class PostSerializer < ActiveModel::Serializer
- attributes :id, :title, :body
-
- has_many :comments, embed: :objects
- has_many :tags, embed: :ids
-end
```
-
-The JSON will look like this:
-
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comments": [
- { "id": 1, "body": "what a dumb post" }
- ],
- "tag_ids": [ 1, 2, 3 ]
- }
-}
+$ rails g serializer post
```
-In addition to supplying an Array of IDs, you may want to side-load the data
-alongside the main object. This makes it easier to process the entire package
-of data without having to recursively scan the tree looking for embedded
-information. It also ensures that associations that are shared between several
-objects (like tags), are only delivered once for the entire payload.
+The generated seralizer will contain basic `attributes` and
+`has_many`/`has_one`/`belongs_to` declarations, based on the model. For example:
-You can specify that the data be included like this:
-
```ruby
class PostSerializer < ActiveModel::Serializer
- embed :ids, include: true
+ attributes :title, :body
- attributes :id, :title, :body
has_many :comments
-end
-```
+ has_one :author
-Assuming that the comments also `has_many :tags`, you will get a JSON like
-this:
-
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comment_ids": [ 1, 2 ]
- },
- "comments": [
- { "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
- { "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
- ],
- "tags": [
- { "id": 1, "name": "short" },
- { "id": 2, "name": "whiny" },
- { "id": 3, "name": "happy" }
- ]
-}
-```
-
-If you would like to namespace association JSON underneath a certain key in
-the root document (say, `linked`), you can specify an `embed_in_root_key`:
-
-```ruby
-class PostSerializer < ActiveModel::Serializer
- embed :ids, include: true, embed_in_root_key: :linked
-
- attributes: :id, :title, :body
- has_many :comments, :tags
+ url :post
end
```
-The above would yield the following JSON document:
+and
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comment_ids": [ 1, 2 ]
- },
- "linked": {
- "comments": [
- { "id": 1, "body": "what a dumb post", "tag_ids": [ 1, 2 ] },
- { "id": 2, "body": "i liked it", "tag_ids": [ 1, 3 ] },
- ],
- "tags": [
- { "id": 1, "name": "short" },
- { "id": 2, "name": "whiny" },
- { "id": 3, "name": "happy" }
- ]
- }
-}
-```
-
-When side-loading data, your serializer cannot have the `{ root: false }` option,
-as this would lead to invalid JSON. If you do not have a root key, the `include`
-instruction will be ignored
-
-You can also specify a different root for the embedded objects than the key
-used to reference them:
-
```ruby
-class PostSerializer < ActiveModel::Serializer
- embed :ids, include: true
+class CommentSerializer < ActiveModel::Serializer
+ attributes :name, :body
- attributes :id, :title, :body
- has_many :comments, key: :comment_ids, root: :comment_objects
+ belongs_to :post_id
+
+ url [:post, :comment]
end
```
-This would generate JSON that would look like this:
+The attribute names are a **whitelist** of attributes to be serialized.
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comment_ids": [ 1 ]
- },
- "comment_objects": [
- { "id": 1, "body": "what a dumb post" }
- ]
-}
-```
+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 can also specify a different attribute to use rather than the ID of the
-objects:
+You may also use the `:serializer` option to specify a custom serializer class, for example:
```ruby
-class PostSerializer < ActiveModel::Serializer
- embed :ids, include: true
-
- attributes :id, :title, :body
- has_many :comments, key: :external_id
-end
+ has_many :comments, serializer: CommentPreviewSerializer
```
-This would generate JSON that would look like this:
+The `url` declaration describes which named routes to use while generating URLs
+for your JSON. Not every adapter will require URLs.
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "body": "A body!",
- "comment_ids": [ "COMM001" ]
- },
- "comments": [
- { "id": 1, "external_id": "COMM001", "body": "what a dumb post" }
- ]
-}
-```
+## Caching
-**NOTE**: The `embed :ids` mechanism is primary useful for clients that process
-data in bulk and load it into a local store. For these clients, the ability to
-easily see all of the data per type, rather than having to recursively scan the
-data looking for information, is extremely useful.
+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}"```.
-If you are mostly working with the data in simple scenarios and manually making
-Ajax requests, you probably just want to use the default embedded behavior.
+The cache support is optimized to use the cached object in multiple request. An object cached on an ```show``` request will be reused at the ```index```. If there is a relationship with another cached serializer it will also be created and reused automatically.
+**[NOTE] Every object is individually cached.**
-## Embedding Polymorphic Associations
+**[NOTE] The cache is automatically expired after update an object but it's not deleted.**
-Because we need both the id and the type to be able to identify a polymorphic associated model, these are serialized in a slightly different format than common ones.
-
-When embedding entire objects:
-
```ruby
-class PostSerializer < ActiveModel::Serializer
- attributes :id, :title
- has_many :attachments, polymorphic: true
-end
+cache(options = nil) # options: ```{key, expires_in, compress, force, race_condition_ttl}```
```
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "attachments": [
- {
- "type": "image",
- "image": {
- "id": 3,
- "name": "logo",
- "url": "http://images.com/logo.jpg"
- }
- },
- {
- "type": "video",
- "video": {
- "id": 12,
- "uid": "XCSSMDFWW",
- "source": "youtube"
- }
- }
- ]
- }
-}
-```
+Take the example bellow:
-When embedding ids:
-
```ruby
class PostSerializer < ActiveModel::Serializer
- embed :ids
+ cache key: 'post', expires_in: 3.hours
+ attributes :title, :body
- attributes :id, :title
- has_many :attachments, polymorphic: true
-end
-```
+ has_many :comments
-```json
-{
- "post": {
- "id": 1,
- "title": "New post",
- "attachment_ids": [
- {
- "type": "image",
- "id": 12
- },
- {
- "type": "video",
- "id": 3
- }
- ]
- }
-}
-```
-
-
-## Customizing Scope
-
-In a serializer, `current_user` is the current authorization scope which the controller
-provides to the serializer when you call `render :json`. By default, this is
-`current_user`, but can be customized in your controller by calling
-`serialization_scope`:
-
-```ruby
-class ApplicationController < ActionController::Base
- serialization_scope :current_admin
+ url :post
end
```
-The above example will also change the scope from `current_user` to
-`current_admin`.
+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.
-Please note that, until now, `serialization_scope` doesn't accept a second
-object with options for specifying which actions should or should not take a
-given scope in consideration.
+### Fragmenting Caching
-To be clear, it's not possible, yet, to do something like this:
+If there is some API endpoint that shouldn't be fully cached, you can still optmise it, using Fragment Cache on the attributes and relationships that you want to cache.
-```ruby
-class SomeController < ApplicationController
- serialization_scope :current_admin, except: [:index, :show]
-end
-```
+You can define the attribute by using ```only``` or ```except``` option on cache method.
-So, in order to have a fine grained control of what each action should take in
-consideration for its scope, you may use something like this:
+**[NOTE] Cache serializers will be used at their relationships**
-```ruby
-class CitiesController < ApplicationController
- serialization_scope nil
+Example:
- def index
- @cities = City.all
-
- render json: @cities, each_serializer: CitySerializer
- end
-
- def show
- @city = City.find(params[:id])
-
- render json: @city, scope: current_admin
- end
-end
-```
-
-Assuming that the `current_admin` method needs to make a query in the database
-for the current user, the advantage of this approach is that, by setting
-`serialization_scope` to `nil`, the `index` action no longer will need to make
-that query, only the `show` action will.
-
-## Testing
-
-In order to test a Serializer, you can just call `.new` on it, passing the object to serialize:
-
-### MiniTest
-
```ruby
-class TestPostSerializer < Minitest::Test
- def setup
- @serializer = PostSerializer.new Post.new(id: 123, title: 'some title', body: 'some text')
- end
-
- def test_special_json_for_api
- assert_equal '{"post":{"id":123,"title":"some title","body":"some text"}}', @serializer.to_json
- end
-```
-
-### RSpec
-
-```ruby
-describe PostSerializer do
- it "creates special JSON for the API" do
- serializer = PostSerializer.new Post.new(id: 123, title: 'some title', body: 'some text')
- expect(serializer.to_json).to eql('{"post":{"id":123,"title":"some title","body":"some text"}}')
- end
-end
-```
-
-## Caching
-
-NOTE: This functionality was removed from AMS and it's in the TODO list.
-We need to re-think and re-design the caching strategy for the next
-version of AMS.
-
-To cache a serializer, call `cached` and define a `cache_key` method:
-
-```ruby
class PostSerializer < ActiveModel::Serializer
- cached # enables caching for this serializer
-
+ cache key: 'post', expires_in: 3.hours, only: [:title]
attributes :title, :body
- def cache_key
- [object, scope]
- end
-end
-```
+ has_many :comments
-The caching interface uses `Rails.cache` under the hood.
-
-# ApplicationSerializer
-
-By default, new serializers descend from ActiveModel::Serializer. However, if you wish to share behaviour across your serializers you can create an ApplicationSerializer at ```app/serializers/application_serializer.rb```:
-
-```ruby
-class ApplicationSerializer < ActiveModel::Serializer
+ url :post
end
```
-Any newly generated serializers will automatically descend from ApplicationSerializer.
+## Getting Help
-```
-$ rails g serializer post
-```
+If you find a bug, please report an [Issue](https://github.com/rails-api/active_model_serializers/issues/new).
-now generates:
+If you have a question, please [post to Stack Overflow](http://stackoverflow.com/questions/tagged/active-model-serializers).
-```ruby
-class PostSerializer < ApplicationSerializer
- attributes :id
-end
-```
+Thanks!
-# Design and Implementation Guidelines
+# Contributing
-## Keep it Simple
-
-`ActiveModel::Serializers` is capable of producing complex JSON views/large object
-trees, and it may be tempting to design in this way so that your client can make
-fewer requests to get data and so that related querying can be optimized.
-However, keeping things simple in your serializers and controllers may
-significantly reduce complexity and maintenance over the long-term development
-of your application. Please consider reducing the complexity of the JSON views
-you provide via the serializers as you build out your application, so that
-controllers/services can be more easily reused without a lot of complexity
-later.
-
-## Performance
-
-As you develop your controllers or other code that utilizes serializers, try to
-avoid n+1 queries by ensuring that data loads in an optimal fashion, e.g. if you
-are using ActiveRecord, you might want to use query includes or joins as needed
-to make the data available that the serializer(s) need.
+See [CONTRIBUTING.md](https://github.com/rails-api/active_model_serializers/blob/master/CONTRIBUTING.md)