Jbuilder meets jsonapi.org specifications
Ruby Shell
Latest commit 57168c4 Feb 16, 2016 @vladfaust Updated usage

README.md

Jbuilder::JsonApi | Gem Version [RubyGems Page](https://rubygems.org/gems/jbuilder-json_api) Build Status Dependency Status

Adds a json.api_format!(resources) method to quickly represent a resource or collection in a valid JSON API format without any new superclasses or weird setups. Set'n'go! 🚀

Motivation

Official JSON API implementations page shows us a variety of different serializers and other heavy-weight stuff. I'm in love with Jbuilder, as it allows to format json responses with ease. Therefore I wanted to connect Jbuilder and JsonApi.org specs.

I'd like to notice that there already is one gem called jbuilder-jsonapi by csexton, but it adds a links helper only. It's not enough for me! 👊

As a result, I've created a very lightweight & flexible solution - all you need is Jbuilder and this gem. Then you should delete everything within your *.json.jbuilder files and replace it with below recommendations (just one line! 😳). After you are free to customize parsed attributes and relationships with three tiny methods.

Installation

Add this line to your application's Gemfile:

gem 'jbuilder-json_api'

And then execute:

$ bundle

Or install it yourself as:

$ gem install jbuilder-json_api

Usage

Firstly, read JSON API specifications: http://jsonapi.org/format/

The gem adds method #api_format!(resources = nil, errors = nil, meta = nil, options = {}) to Jbuilder class and therefore to all its children, e.g. JbuilderTemplate. Possible arguments are:

  • resources goes for a collection of objects, e.g. array of Articles. It can also be a single object or just an empty array;
  • errors goes for a collection of errors. It must be an array of hashes;
  • meta is any hash representing some additional request-level information;
  • options can be any object. It will be passed to resources while the method is being executed.

Replace any content within any *.json.jbuilder file with the code below:

# Common example
json.api_format! @resources, @errors, meta, options

# Items example
json.api_format! @items, @errors, nil, access_level: :admin

# A simple items example
json.api_format! @items

You can also render formatted JSON straight from controller actions:

respond_to do |f|
    f.json { render layout: false, json: JSON.parse(JbuilderTemplate.new(view_context).api_format!(@item).target!) }
    f.html { render nothing: true, status: :bad_request }
end

Each resource instance, as well as the included one, will be invoked with json_api_attrs (options), json_api_relations (options) & json_api_meta (options) methods. These methods MAY be implemented within each model. api_format! method will try to get an object's permitted attributes (remember, you are free do define authentication logic yourself!) and relations and meta information via those three methods.

Here is an example of implementation:

# Inside Item model

def json_api_attrs (options = {})
  attrs = []
  attrs += %w(name description price buyoutable item_type category) if %i(user admin).include?options[:access_level]
  attrs += %w(real_price in_stock) if options[:access_level] == :admin
  attrs
end

def json_api_relations (options = {})
  %w(category orders)
end

def json_api_meta (options = {})
  { foo: :bar }
end

Note that the gem will call methods pulled via json_api_relations and _attrs. As for the above example, methods like :name, :description, :real_price, :orders will be invoked for an Item instance. And yes, relations are fetched properly and recursively if the object responds to orders.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/vladfaust/jbuilder-json_api. It would be really good if someone contributes. 😄

ToDo

  • Maybe add Content-Type: application/vnd.api+json. This spec is ignored right now 😏
  • Add links tests and improve them. Links now work only within views (where @context is present).
  • Somehow implement [fields] parameter

Versions

0.0.1 -> 1.0.0

Breaking:

  • Now any value can be forwarded to resources' methods via last options argument.
  • Added third argument meta, which is used to show meta information in the context of request

Not breaking:

  • Added support for json_api_meta (options) method.
  • Any internal error is now properly handled.