jbuilder-json_api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +77 -0
- data/Rakefile +6 -0
- data/lib/jbuilder/json_api/version.rb +3 -0
- data/lib/jbuilder/json_api.rb +154 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1ff4461806b35c5a3d74588a69c25b2114cb229f
|
4
|
+
data.tar.gz: 14b6437c8ca3707ee94b7ecea417655976fb06d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 243d498cce513d4794dfa8babe42ee888f102b5dd328679bf923873597d5c4232425bcb67d329ed5a69ef3808e244066466b4133412b27709ee847ba21d23fc0
|
7
|
+
data.tar.gz: 297d98968a8d93e6628f309e5b21ad9954216327dca0d4962405233c540496f60a588d60a7cca8ba1ce226ecca74d1a356012fe8f42781d54c50e9d14e78b733
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Jbuilder::JsonApi | [](https://travis-ci.org/vladfaust/jbuilder-json_api) [](https://codeclimate.com/github/vladfaust/jbuilder-json_api) [](https://codeclimate.com/github/vladfaust/jbuilder-json_api/coverage)
|
2
|
+
|
3
|
+
Adds a `json.api_format!(resources)` method to quickly represent a resource or collection in a valid [JSON API](http://jsonapi.org/) format without any new superclasses or weird setups. Set'n'go! :rocket:
|
4
|
+
|
5
|
+
## Motivation
|
6
|
+
|
7
|
+
Official JSON API [implementations page](http://jsonapi.org/implementations/#server-libraries-ruby) shows us a variety of different serializers and other heavy-weight stuff. I' in love with [Jbuilder](https://github.com/rails/jbuilder), as it allows to format json responses with ease. Therefore I wanted to connect Jbuilder and JsonApi.org specs.
|
8
|
+
|
9
|
+
I'd like to notice that there already is one gem called [jbuilder-jsonapi](https://github.com/csexton/jbuilder-jsonapi) by [csexton](https://github.com/csexton), but it adds a links helper only. It's not enough for me! :facepunch:
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'jbuilder-json_api'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install jbuilder-json_api
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
Replace any content within any `*.json.jbuilder` file with the code below:
|
30
|
+
```ruby
|
31
|
+
# Common example
|
32
|
+
json.api_format! @resources, @errors, meta: @meta, access_level: @user_access_level
|
33
|
+
|
34
|
+
# Articles w/o meta or access levels example
|
35
|
+
json.api_format! @articles, @errors
|
36
|
+
```
|
37
|
+
You can also render formatted JSON straight from controller actions:
|
38
|
+
```ruby
|
39
|
+
respond_to do |f|
|
40
|
+
f.json { render layout: false, json: JSON.parse(JbuilderTemplate.new(view_context).api_format!(@item).target!) }
|
41
|
+
f.html { render nothing: true, status: :bad_request }
|
42
|
+
end
|
43
|
+
```
|
44
|
+
Each resource instance, as well as the included one, will be invoked with `json_api_attrs` & `json_api_relations` methods. These methods **MAY** be implemented within each model. `api_format!` method will try to get an object's permitted (**you are free do define authentication logic yourself!**) attributes and relations via those two methods.
|
45
|
+
|
46
|
+
Here is an example of implementation:
|
47
|
+
```ruby
|
48
|
+
# Item model
|
49
|
+
|
50
|
+
def json_api_attr (access_level = nil)
|
51
|
+
attrs = []
|
52
|
+
attrs += %w(name description price buyoutable item_type category) if %i(user admin).include?access_level
|
53
|
+
attrs += %w(real_price in_stock) if access_level == :admin
|
54
|
+
attrs
|
55
|
+
end
|
56
|
+
|
57
|
+
def json_api_relations (access_level = nil)
|
58
|
+
%w(category orders)
|
59
|
+
end
|
60
|
+
```
|
61
|
+
**Note** that the gem will call methods pulled with `json_api_relations and _attrs`. As for the above example, methods like `:name`, `:description`, `:orders` will be invoked for an Item instance. And yes, relations are fetched properly if an object responds to `orders`.
|
62
|
+
|
63
|
+
## Development
|
64
|
+
|
65
|
+
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.
|
66
|
+
|
67
|
+
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](https://rubygems.org).
|
68
|
+
|
69
|
+
## Contributing
|
70
|
+
|
71
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/vladfaust/jbuilder-json_api](https://github.com/vladfaust/jbuilder-json_api). It would be really good if someone contributes. :smile:
|
72
|
+
|
73
|
+
## ToDo
|
74
|
+
|
75
|
+
- [ ] Maybe add `Content-Type: application/vnd.api+json`. This spec is ignored right now :smirk:
|
76
|
+
- [ ] Add links tests
|
77
|
+
- [ ] Somehow implement `[fields]` parameter
|
data/Rakefile
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'jbuilder'
|
2
|
+
require 'jbuilder/json_api/version'
|
3
|
+
|
4
|
+
module JsonAPI
|
5
|
+
# Returns a valid-formatted JSON which follows JSON-API specifications:
|
6
|
+
# http://jsonapi.org/
|
7
|
+
#
|
8
|
+
# Arguments:
|
9
|
+
# :resources: - list of resources to render (may be even one or nil)
|
10
|
+
# :errors: - array of errors in below format:
|
11
|
+
# [{ status: 422, detail: 'This error occurs because...' }, {...}]
|
12
|
+
#
|
13
|
+
# Options:
|
14
|
+
# :access_level: - access level, e.g. nil, :user, :admin
|
15
|
+
# :meta: - a hash representing meta (additional) information
|
16
|
+
#
|
17
|
+
def api_format! (resources = nil, errors = nil, options = {})
|
18
|
+
options.merge access_level: nil
|
19
|
+
options.merge meta: nil
|
20
|
+
|
21
|
+
# Firstly, print meta
|
22
|
+
# http://jsonapi.org/format/#document-meta
|
23
|
+
#
|
24
|
+
if options[:meta] && !options[:meta].empty?
|
25
|
+
meta options[:meta]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Secondly, take care of errors. If there are any,
|
29
|
+
# no 'data' section should be represented.
|
30
|
+
# http://jsonapi.org/format/#document-top-level
|
31
|
+
#
|
32
|
+
# Read more at
|
33
|
+
# http://jsonapi.org/format/#errors
|
34
|
+
#
|
35
|
+
if errors && !errors.empty?
|
36
|
+
ignore_nil! (@ignore_nil.nil? ? true : @ignore_nil)
|
37
|
+
errors errors do |error|
|
38
|
+
id error[:id]
|
39
|
+
status error[:status]
|
40
|
+
detail error[:detail]
|
41
|
+
code error[:code]
|
42
|
+
title error[:title]
|
43
|
+
|
44
|
+
source do
|
45
|
+
pointer error[:pointer]
|
46
|
+
paramater error[:parameter]
|
47
|
+
end
|
48
|
+
|
49
|
+
links do
|
50
|
+
about error[:about]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return self
|
54
|
+
end
|
55
|
+
|
56
|
+
resources = ::Kernel::Array resources
|
57
|
+
|
58
|
+
# http://jsonapi.org/format/#document-links
|
59
|
+
#
|
60
|
+
links do
|
61
|
+
begin
|
62
|
+
set! 'self', @context.request.path
|
63
|
+
rescue
|
64
|
+
# No @context given, cannot find path
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
data do
|
69
|
+
resources.blank? ? array! : _api_resource_objects(resources, options[:access_level])
|
70
|
+
end
|
71
|
+
|
72
|
+
included = []
|
73
|
+
resources.each do |resource|
|
74
|
+
next unless resource.respond_to?'json_api_relations'
|
75
|
+
resource.json_api_relations(options[:access_level]).each do |relationship|
|
76
|
+
included += ::Kernel::Array(resource.send(relationship))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
included.uniq!
|
80
|
+
|
81
|
+
included do
|
82
|
+
_api_resource_objects(included, options[:access_level], resources) unless included.blank?
|
83
|
+
end
|
84
|
+
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Formats a resources array properly
|
91
|
+
# http://jsonapi.org/format/#document-resource-objects
|
92
|
+
#
|
93
|
+
def _api_resource_objects (resources, access_level, parent_resources = nil)
|
94
|
+
resources.each do |resource|
|
95
|
+
child! do
|
96
|
+
type resource.class.name.demodulize.to_s.downcase
|
97
|
+
id resource.id
|
98
|
+
|
99
|
+
# http://jsonapi.org/format/#document-resource-object-attributes
|
100
|
+
#
|
101
|
+
if resource.respond_to?'json_api_attrs'
|
102
|
+
attributes do
|
103
|
+
resource.json_api_attrs(access_level).each do |attribute|
|
104
|
+
set! attribute, resource.send(attribute)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# http://jsonapi.org/format/#document-resource-object-relationships
|
110
|
+
#
|
111
|
+
if resource.respond_to?'json_api_relations'
|
112
|
+
unless resource.json_api_relations(access_level).blank?
|
113
|
+
relationships do
|
114
|
+
resource.json_api_relations(access_level).each do |relationship|
|
115
|
+
set! relationship do
|
116
|
+
links do
|
117
|
+
begin
|
118
|
+
related @context.send("#{ relationship.pluralize }_path")
|
119
|
+
rescue
|
120
|
+
# No @context given, cannot find path
|
121
|
+
end
|
122
|
+
# TODO add a link to the relationship itself
|
123
|
+
end
|
124
|
+
|
125
|
+
data do
|
126
|
+
::Kernel::Array(resource.send(relationship)).each do |relationship_instance|
|
127
|
+
# Relationships shouldn't ever link to the parent resource
|
128
|
+
#
|
129
|
+
next if !parent_resources.nil? && parent_resources.include?(relationship_instance)
|
130
|
+
child! do
|
131
|
+
type relationship_instance.class.name.demodulize.to_s.downcase
|
132
|
+
id relationship_instance.id
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
links do
|
143
|
+
begin
|
144
|
+
set! 'self', @context.send("#{ resource.class.name.demodulize.to_s.downcase }_path", resource)
|
145
|
+
rescue
|
146
|
+
# No @context given, cannot find path
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
Jbuilder.include JsonAPI
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jbuilder-json_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vlad Faust
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jbuilder
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.11'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: factory_girl
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.5'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: codeclimate-test-reporter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Adds a method to build a valid JSON API (jsonapi.org) response without
|
98
|
+
any new superclasses or weird setups. Set'n'go!
|
99
|
+
email:
|
100
|
+
- vladislav.faust@gmail.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/jbuilder/json_api.rb
|
108
|
+
- lib/jbuilder/json_api/version.rb
|
109
|
+
homepage: https://github.com/vladfaust/jbuilder-json_api
|
110
|
+
licenses:
|
111
|
+
- MIT
|
112
|
+
metadata: {}
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 2.5.2
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Easily follow jsonapi.org specifications with Jbuilder
|
133
|
+
test_files: []
|