Model serialization, paging, side-loading and filtering
restpack_serializer allows you to quickly provide a set of RESTful endpoints for your application. It is an implementation of the emerging JSON API standard.
NOTE: This gem needs maintainers: #128
After adding the gem restpack_serializer to your Gemfile, add this code to config/initializers/restpack_serializer.rb:
Dir[Rails.root.join('app/serializers/**/*.rb')].eachdo |path|
requirepathendLet's say we have an Album model:
classAlbum < ActiveRecord::Baseattr_accessible:title,:year,:artistbelongs_to:artisthas_many:songsendrestpack_serializer allows us to define a corresponding serializer:
classAlbumSerializerincludeRestPack::Serializerattributes:id,:title,:year,:artist_id,:hrefendAlbumSerializer.as_json(album) produces:
{"id": "1","title": "Kid A","year": 2000,"artist_id": 1,"href": "/albums/1"}as_json accepts an optional context hash parameter which can be used by your Serializers to customize their output:
classAlbumSerializerincludeRestPack::Serializerattributes:id,:title,:year,:artist_id,:extrasoptional:scorecan_include:artists,:songscan_filter_by:yeardefextrasif@context[:admin?]{markup_percent: 95}endendendAlbumSerializer.as_json(album,{admin?: true})All attributes are serialized by default. If you'd like to skip an attribute, you can pass an option in the @context as follows:
AlbumSerializer.as_json(album,{include_title?: false})You can also define optional attributes which aren't included by default. To include:
AlbumSerializer.as_json(album,{include_score?: true})The AlbumSerializer provides page and resource methods which provide paged collection and singular resource GET endpoints.
classAlbumsController < ApplicationControllerdefindexrenderjson: AlbumSerializer.page(params)enddefshowrenderjson: AlbumSerializer.resource(params)endendThese endpoint will live at URLs such as /albums and /albums/142857:
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums/4.json
The AlbumSerializer also provides a single method which will return a serialized resource similar to as_json above.
page, resource and single methods take an optional scope argument allowing us to enforce arbitrary constraints:
AlbumSerializer.page(params,Albums.where("year < 1950"))In addition to scope, all three methods also accept an optional context hash:
AlbumSerializer.page(params,Albums.where("year < 1950"),{admin?: true})Other features:
Collections are paged by default. page and page_size parameters are available:
- http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?page=2
- http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?page=2&page_size=3
Paging details are included in a meta attribute:
http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?page=2&page_size=3 yields:
{"songs": [{"id": "4","title": "How to Dissapear Completely","href": "/songs/4","links": {"artist": "1","album": "1"}},{"id": "5","title": "Treefingers","href": "/songs/5","links": {"artist": "1","album": "1"}},{"id": "6","title": "Optimistic","href": "/songs/6","links": {"artist": "1","album": "1"}}],"meta": {"songs": {"page": 2,"page_size": 3,"count": 42,"include": [],"page_count": 14,"previous_page": 1,"next_page": 3,"first_href": "/songs?page_size=3","previous_href": "/songs?page_size=3","next_href": "/songs?page=3&page_size=3","last_href": "/songs?page=14&page_size=3"}},"links": {"songs.artist": {"href": "/artists/{songs.artist}","type": "artists"},"songs.album": {"href": "/albums/{songs.album}","type": "albums"}}}URL Templates to related data are included in the links element. These can be used to construct URLs such as:
- /artists/1
- /albums/1
Side-loading allows related resources to be optionally included in a single API response. Valid side-loads can be defined in Serializers by using can_include as follows:
classAlbumSerializerincludeRestPack::Serializerattributes:id,:title,:year,:artist_id,:hrefcan_include:songs,:artistsendIn this example, we are allowing related songs and artists to be included in API responses. Side-loads can be specifed by using the include parameter:
which yields:
{"albums": [{"id": "1","title": "Kid A","year": 2000,"href": "/albums/1","links": {"artist": "1"}},{"id": "2","title": "Amnesiac","year": 2001,"href": "/albums/2","links": {"artist": "1"}},{"id": "3","title": "Murder Ballads","year": 1996,"href": "/albums/3","links": {"artist": "2"}},{"id": "4","title": "Curtains","year": 2005,"href": "/albums/4","links": {"artist": "3"}}],"meta": {"albums": {"page": 1,"page_size": 10,"count": 4,"include": ["artists"],"page_count": 1,"previous_page": null,"next_page": null,"first_href": '/albums',"previous_href": null,"next_href": null,"last_href": '/albums'}},"links": {"albums.songs": {"href": "/songs?album_id={albums.id}","type": "songs"},"albums.artist": {"href": "/artists/{albums.artist}","type": "artists"},"artists.albums": {"href": "/albums?artist_id={artists.id}","type": "albums"},"artists.songs": {"href": "/songs?artist_id={artists.id}","type": "songs"}},"linked": {"artists": [{"id": "1","name": "Radiohead","website": "http://radiohead.com/","href": "/artists/1"},{"id": "2","name": "Nick Cave & The Bad Seeds","website": "http://www.nickcave.com/","href": "/artists/2"},{"id": "3","name": "John Frusciante","website": "http://johnfrusciante.com/","href": "/artists/3"}]}}An album :has_many songs, so the side-loaded songs are paged. The meta.songs includes previous_href and next_href which point to the previous and next page of this side-loaded data. These URLs take the form:
Simple filtering based on primary and foreign keys is supported by default:
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?id=1
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?ids=1,2,4
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?artist_id=1
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?artist_ids=2,3
Custom filters can be defined with the can_filter_by option:
classAccountincludeRestPack::Serializerattributes:id,:application_id,:created_by,:name,:hrefcan_filter_by:application_idendSide-loading is available when filtering:
Sorting attributes can be defined with the can_sort_by option:
classAccountincludeRestPack::Serializerattributes:id,:application_id,:created_by,:name,:hrefcan_sort_by:id,:nameend- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?sort=id
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?sort=-name
- http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?sort=name,-id
bundlerake spec




