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.