diff --git a/CHANGELOG.md b/CHANGELOG.md index b6b0103d..66ab1138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Misc: - [#1878](https://github.com/rails-api/active_model_serializers/pull/1878) Cache key generation for serializers now uses `ActiveSupport::Cache.expand_cache_key` instead of `Array#join` by default and is also overridable. This change should be backward-compatible. (@markiz) - [#1799](https://github.com/rails-api/active_model_serializers/pull/1799) Add documentation for setting the adapter. (@ScottKbka) +- [#1909](https://github.com/rails-api/active_model_serializers/pull/1909) Add documentation for relationship links. (@vasilakisfil, @NullVoxPopuli) ### [v0.10.2 (2016-07-05)](https://github.com/rails-api/active_model_serializers/compare/v0.10.1...v0.10.2) diff --git a/docs/README.md b/docs/README.md index 57abb0fa..b7d8c152 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,6 +24,7 @@ This is the documentation of ActiveModelSerializers, it's focused on the **0.10. - [How to add root key](howto/add_root_key.md) - [How to add pagination links](howto/add_pagination_links.md) +- [How to add relationship links](howto/add_relationship_links.md) - [Using ActiveModelSerializers Outside Of Controllers](howto/outside_controller_use.md) - [Testing ActiveModelSerializers](howto/test.md) - [Passing Arbitrary Options](howto/passing_arbitrary_options.md) diff --git a/docs/howto/add_relationship_links.md b/docs/howto/add_relationship_links.md new file mode 100644 index 00000000..b942acc7 --- /dev/null +++ b/docs/howto/add_relationship_links.md @@ -0,0 +1,137 @@ +[Back to Guides](../README.md) + +# How to add relationship links + +ActiveModelSerializers offers you many ways to add links in your JSON, depending on your needs. +The most common use case for links is supporting nested resources. + +The following examples are without included relationship data (`include` param is empty), +specifically the following Rails controller was used for these examples: + +```ruby +class Api::V1::UsersController < ApplicationController + def show + render jsonapi: User.find(params[:id]), + serializer: Api::V1::UserSerializer, + include: [] + end +``` + +Bear in mind though that ActiveModelSerializers are [framework-agnostic](outside_controller_use.md), Rails is just a common example here. + +### Links as an attribute of a resource +**This is applicable to JSONAPI, JSON and Attributes adapters** + +You can define an attribute in the resource, named `links`. + +```ruby +class Api::V1::UserSerializer < ActiveModel::Serializer + attributes :id, :name, :links + + def links + { + self: api_v1_user_path(object.id), + microposts: api_v1_microposts_path(user_id: object.id) + } + end +end +``` + +This will resilt in (example is in jsonapi adapter): +```json +{ + "data": { + "id": "1", + "type": "users", + "attributes": { + "name": "Example User", + "links": { + "self": "/api/v1/users/1", + "microposts": "/api/v1/microposts?user_id=1" + } + } + } +} +``` + + +### Links as a property of the resource definiton +**This is only applicable to JSONAPI adapter** + +You can use the `links` class method to define the links you need in the resource's primary data. + +```ruby +class Api::V1::UserSerializer < ActiveModel::Serializer + attributes :id, :name + + link(:self) { api_v1_user_path(object.id) } + link(:microposts) { api_v1_microposts_path(user_id: object.id) } +end +``` + +This will resilt in (example is in jsonapi adapter): +```json +{ + "data": { + "id": "1", + "type": "users", + "attributes": { + "name": "Example User" + }, + "links": { + "self": "/api/v1/users/1", + "microposts": "/api/v1/microposts?user_id=1" + } + } +} +``` + +### Links that follow the JSONAPI spec +**This is only applicable to JSONAPI adapter** + +If you have a JSONAPI-strict client that you are working with (like `ember-data`) +you need to construct the links inside the relationships. Also the link to fetch the +relationship data must be under the `related` attribute, whereas to manipulate the +relationship (in case of many-to-many relationship) must be under the `self` attribute. + +You can find more info in the [spec](http://jsonapi.org/format/#document-resource-object-relationships). + +Here is how you can do this: + +```ruby +class Api::V1::UserSerializer < ActiveModel::Serializer + attributes :id, :name + + has_many :microposts, serializer: Api::V1::MicropostSerializer do + link(:related) { api_v1_microposts_path(user_id: object.id) } + end + + #this is needed to avoid n+1, gem core devs are working to remove this necessity + #more on: https://github.com/rails-api/active_model_serializers/issues/1325 + def microposts + object.microposts.loaded ? object.microposts : object.microposts.none + end +end +``` + +This will result in: + +```json +{ + "data": { + "id": "1", + "type": "users", + "attributes": { + "name": "Example User" + }, + "relationships": { + "microposts": { + "data": [], + "links": { + "related": "/api/v1/microposts?user_id=1" + } + } + } + } +} +```