jsonapi-renderer 0.1.1.beta2 → 0.1.1.beta3
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 +4 -4
- data/README.md +5 -3
- data/lib/jsonapi/renderer/document.rb +53 -0
- data/lib/jsonapi/renderer/resources_processor.rb +67 -0
- data/lib/jsonapi/renderer.rb +9 -104
- metadata +35 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e0ff29d67fa35e41f7a46f6f4bec480555d9318
|
4
|
+
data.tar.gz: 0d2a619490327182f40f978a917bc80b534f09ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c7b8a58093c1a7a01e1bf352b4232471f483c910386c24d77cc32301bfeb477089a163e78ab57a55d4d3e900a4945ee031cb892fe45e4a0854a3d8fab6d741f
|
7
|
+
data.tar.gz: e61f0a433b6a84b238e9717128073ec934557a9e7ec9e912a29adad883d9c29e902ab65c56862b456407bc617b50239c16a1638ce45f088c63e68bccf83755be
|
data/README.md
CHANGED
@@ -4,6 +4,7 @@ Ruby gem for rendering [JSON API](http://jsonapi.org) documents.
|
|
4
4
|
## Status
|
5
5
|
|
6
6
|
[](https://badge.fury.io/rb/jsonapi-renderer)
|
7
|
+
[](http://travis-ci.org/jsonapi-rb/renderer?branch=master)
|
7
8
|
|
8
9
|
## Installation
|
9
10
|
```ruby
|
@@ -53,11 +54,12 @@ class ResourceInterface
|
|
53
54
|
# relationships, or nil.
|
54
55
|
# @return [Hash]
|
55
56
|
def as_jsonapi(options = {}); end
|
57
|
+
end
|
56
58
|
```
|
57
59
|
|
58
60
|
#### Rendering a single resource
|
59
61
|
```ruby
|
60
|
-
JSONAPI.render(resource,
|
62
|
+
JSONAPI.render(data: resource,
|
61
63
|
include: include_string,
|
62
64
|
fields: fields_hash,
|
63
65
|
meta: meta_hash,
|
@@ -68,7 +70,7 @@ This returns a JSON API compliant hash representing the described document.
|
|
68
70
|
|
69
71
|
#### Rendering a collection of resources
|
70
72
|
```ruby
|
71
|
-
JSONAPI.render(resources,
|
73
|
+
JSONAPI.render(data: resources,
|
72
74
|
include: include_string,
|
73
75
|
fields: fields_hash,
|
74
76
|
meta: meta_hash,
|
@@ -80,7 +82,7 @@ This returns a JSON API compliant hash representing the described document.
|
|
80
82
|
### Rendering errors
|
81
83
|
|
82
84
|
```ruby
|
83
|
-
JSONAPI.render_errors(errors,
|
85
|
+
JSONAPI.render_errors(errors: errors,
|
84
86
|
meta: meta_hash,
|
85
87
|
links: links_hash)
|
86
88
|
```
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'jsonapi/include_directive'
|
2
|
+
require 'jsonapi/renderer/resources_processor'
|
3
|
+
|
4
|
+
module JSONAPI
|
5
|
+
module Renderer
|
6
|
+
class Document
|
7
|
+
def initialize(params = {})
|
8
|
+
@data = params.fetch(:data, :no_data)
|
9
|
+
@errors = params.fetch(:errors, [])
|
10
|
+
@meta = params.fetch(:meta, nil)
|
11
|
+
@links = params.fetch(:links, {})
|
12
|
+
@fields = params.fetch(:fields, {})
|
13
|
+
@jsonapi = params.fetch(:jsonapi, nil)
|
14
|
+
@include = JSONAPI::IncludeDirective.new(params.fetch(:include, {}))
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
@hash ||= document_hash
|
19
|
+
end
|
20
|
+
alias to_h to_hash
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def document_hash
|
25
|
+
{}.tap do |hash|
|
26
|
+
if @data != :no_data
|
27
|
+
hash.merge!(data_hash)
|
28
|
+
elsif @errors.any?
|
29
|
+
hash.merge!(errors_hash)
|
30
|
+
end
|
31
|
+
hash[:links] = @links if @links.any?
|
32
|
+
hash[:meta] = @meta unless @meta.nil?
|
33
|
+
hash[:jsonapi] = @jsonapi unless @jsonapi.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def data_hash
|
38
|
+
primary, included =
|
39
|
+
ResourcesProcessor.new(Array(@data), @include, @fields).process
|
40
|
+
{}.tap do |hash|
|
41
|
+
hash[:data] = @data.respond_to?(:each) ? primary : primary[0]
|
42
|
+
hash[:included] = included if included.any?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def errors_hash
|
47
|
+
{}.tap do |hash|
|
48
|
+
hash[:errors] = @errors.map(&:as_jsonapi)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module JSONAPI
|
4
|
+
module Renderer
|
5
|
+
class ResourcesProcessor
|
6
|
+
def initialize(resources, include, fields)
|
7
|
+
@resources = resources
|
8
|
+
@include = include
|
9
|
+
@fields = fields
|
10
|
+
@primary = []
|
11
|
+
@included = []
|
12
|
+
@hashes = {}
|
13
|
+
@queue = []
|
14
|
+
@processed = Set.new # NOTE(beauby): Set of [type, id, prefix].
|
15
|
+
end
|
16
|
+
|
17
|
+
def process
|
18
|
+
@resources.each do |res|
|
19
|
+
process_resource(res, '', @include, true)
|
20
|
+
@processed.add([res.jsonapi_type, res.jsonapi_id, ''])
|
21
|
+
end
|
22
|
+
until @queue.empty?
|
23
|
+
res, prefix, include_dir = @queue.pop
|
24
|
+
process_resource(res, prefix, include_dir, false)
|
25
|
+
end
|
26
|
+
|
27
|
+
[@primary, @included]
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def merge_resources!(a, b)
|
33
|
+
b[:relationships].each do |name, rel|
|
34
|
+
a[:relationships][name][:data] ||= rel[:data] if rel.key?(:data)
|
35
|
+
if rel.key?(:links)
|
36
|
+
(a[:relationships][name][:links] ||= {}).merge!(rel[:links])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_resource(res, prefix, include_dir, is_primary)
|
42
|
+
ri = [res.jsonapi_type, res.jsonapi_id]
|
43
|
+
hash = res.as_jsonapi(fields: @fields[res.jsonapi_type.to_sym],
|
44
|
+
include: include_dir.keys)
|
45
|
+
if @hashes.key?(ri)
|
46
|
+
merge_resources!(@hashes[ri], hash)
|
47
|
+
else
|
48
|
+
(is_primary ? @primary : @included) << (@hashes[ri] = hash)
|
49
|
+
end
|
50
|
+
process_relationships(res, prefix, include_dir)
|
51
|
+
end
|
52
|
+
|
53
|
+
def process_relationships(res, prefix, include_dir)
|
54
|
+
res.jsonapi_related(include_dir.keys).each do |key, data|
|
55
|
+
Array(data).each do |child_res|
|
56
|
+
next if child_res.nil?
|
57
|
+
child_prefix = "#{prefix}.#{key}"
|
58
|
+
next unless @processed.add?([child_res.jsonapi_type,
|
59
|
+
child_res.jsonapi_id,
|
60
|
+
child_prefix])
|
61
|
+
@queue << [child_res, child_prefix, include_dir[key]]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/jsonapi/renderer.rb
CHANGED
@@ -1,98 +1,15 @@
|
|
1
|
-
require 'jsonapi/
|
1
|
+
require 'jsonapi/renderer/document'
|
2
2
|
|
3
3
|
module JSONAPI
|
4
|
-
class Renderer
|
5
|
-
def initialize(resources, options = {})
|
6
|
-
@resources = resources
|
7
|
-
@errors = options[:errors] || false
|
8
|
-
@meta = options[:meta] || nil
|
9
|
-
@links = options[:links] || {}
|
10
|
-
@fields = options[:fields] || {}
|
11
|
-
# NOTE(beauby): Room for some nifty defaults on those.
|
12
|
-
@jsonapi = options[:jsonapi_object] || nil
|
13
|
-
@include = JSONAPI::IncludeDirective.new(options[:include] || {})
|
14
|
-
end
|
15
|
-
|
16
|
-
def as_json
|
17
|
-
return @json unless @json.nil?
|
18
|
-
|
19
|
-
process_resources
|
20
|
-
@json = {}
|
21
|
-
|
22
|
-
if @errors
|
23
|
-
@json[:errors] = @resources.map(&:as_jsonapi)
|
24
|
-
else
|
25
|
-
@json[:data] = @resources.respond_to?(:each) ? @primary : @primary[0]
|
26
|
-
@json[:included] = @included if @included.any?
|
27
|
-
end
|
28
|
-
@json[:links] = @links if @links.any?
|
29
|
-
@json[:meta] = @meta unless @meta.nil?
|
30
|
-
@json[:jsonapi] = @jsonapi unless @jsonapi.nil?
|
31
|
-
|
32
|
-
@json
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def process_resources
|
38
|
-
@primary = []
|
39
|
-
@included = []
|
40
|
-
@hashes = {}
|
41
|
-
@processed = Set.new # NOTE(beauby): Set of [type, id, prefix].
|
42
|
-
@queue = []
|
43
|
-
|
44
|
-
Array(@resources).each do |res|
|
45
|
-
process_resource(res, '', @include, true)
|
46
|
-
@processed.add([res.jsonapi_type, res.jsonapi_id, ''])
|
47
|
-
end
|
48
|
-
until @queue.empty?
|
49
|
-
res, prefix, include_dir = @queue.pop
|
50
|
-
process_resource(res, prefix, include_dir, false)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def merge_resources!(a, b)
|
55
|
-
b[:relationships].each do |name, rel|
|
56
|
-
a[:relationships][name][:data] ||= rel[:data] if rel.key?(:data)
|
57
|
-
(a[:relationships][name][:links] ||= {})
|
58
|
-
.merge!(rel[:links]) if rel.key?(:links)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def process_resource(res, prefix, include_dir, is_primary)
|
63
|
-
ri = [res.jsonapi_type, res.jsonapi_id]
|
64
|
-
hash = res.as_jsonapi(fields: @fields[res.jsonapi_type.to_sym],
|
65
|
-
include: include_dir.keys)
|
66
|
-
if @hashes.key?(ri)
|
67
|
-
merge_resources!(@hashes[ri], hash)
|
68
|
-
else
|
69
|
-
(is_primary ? @primary : @included) << (@hashes[ri] = hash)
|
70
|
-
end
|
71
|
-
process_relationships(res, prefix, include_dir)
|
72
|
-
end
|
73
|
-
|
74
|
-
def process_relationships(res, prefix, include_dir)
|
75
|
-
res.jsonapi_related(include_dir.keys).each do |key, data|
|
76
|
-
Array(data).each do |child_res|
|
77
|
-
next if child_res.nil?
|
78
|
-
child_prefix = "#{prefix}.#{key}"
|
79
|
-
next unless @processed.add?([child_res.jsonapi_type,
|
80
|
-
child_res.jsonapi_id,
|
81
|
-
child_prefix])
|
82
|
-
@queue << [child_res, child_prefix, include_dir[key]]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
4
|
module_function
|
89
5
|
|
90
|
-
# Render a
|
6
|
+
# Render a JSON API document.
|
91
7
|
#
|
92
|
-
# @param [
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
8
|
+
# @param [Hash] params
|
9
|
+
# @option [(#jsonapi_id, #jsonapi_type, #jsonapi_related, #as_jsonapi),
|
10
|
+
# Array<(#jsonapi_id, #jsonapi_type, #jsonapi_related, #as_jsonapi)>,
|
11
|
+
# nil] data Primary resource(s) to be rendered.
|
12
|
+
# @option [Array<#jsonapi_id>] errors Errors to be rendered.
|
96
13
|
# @option [String, Hash{Symbol => Hash}] include Relationships to be
|
97
14
|
# included.
|
98
15
|
# @option [Hash{Symbol, Array<Symbol>}] fields List of requested fields
|
@@ -101,19 +18,7 @@ module JSONAPI
|
|
101
18
|
# included.
|
102
19
|
# @option [Hash] links Top-level links to be included.
|
103
20
|
# @option [Hash] jsonapi_object JSON API object.
|
104
|
-
def render(
|
105
|
-
Renderer.new(
|
106
|
-
end
|
107
|
-
|
108
|
-
# Render an error JSON API document.
|
109
|
-
#
|
110
|
-
# @param [Array<#jsonapi_id>] errors Errors to be rendered.
|
111
|
-
# @param [Hash] options All optional.
|
112
|
-
# @option [Hash] meta Non-standard top-level meta information to be
|
113
|
-
# included.
|
114
|
-
# @option [Hash] links Top-level links to be included.
|
115
|
-
# @option [Hash] jsonapi_object JSON API object.
|
116
|
-
def render_errors(errors)
|
117
|
-
Renderer.new(errors, errors: true).as_json
|
21
|
+
def render(params)
|
22
|
+
Renderer::Document.new(params).to_hash
|
118
23
|
end
|
119
24
|
end
|
metadata
CHANGED
@@ -1,16 +1,44 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-renderer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.1.
|
4
|
+
version: 0.1.1.beta3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lucas Hosseini
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
12
|
-
dependencies:
|
13
|
-
|
11
|
+
date: 2016-11-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '11.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '11.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.5'
|
41
|
+
description: Efficiently render JSON API documents.
|
14
42
|
email: lucas.hosseini@gmail.com
|
15
43
|
executables: []
|
16
44
|
extensions: []
|
@@ -20,7 +48,9 @@ files:
|
|
20
48
|
- lib/jsonapi/include_directive.rb
|
21
49
|
- lib/jsonapi/include_directive/parser.rb
|
22
50
|
- lib/jsonapi/renderer.rb
|
23
|
-
|
51
|
+
- lib/jsonapi/renderer/document.rb
|
52
|
+
- lib/jsonapi/renderer/resources_processor.rb
|
53
|
+
homepage: https://github.com/jsonapi-rb/renderer
|
24
54
|
licenses:
|
25
55
|
- MIT
|
26
56
|
metadata: {}
|