jsonapi-renderer 0.1.3 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64a6b359e09767d1fb82f5c99e5c00493180fee2
4
- data.tar.gz: 7cbe497431c5af06536206776c5ea4c791085e3c
3
+ metadata.gz: ccb0dad8d132bc0c9faa63ed697f2b081b8d734e
4
+ data.tar.gz: 55d657476428b0d6c484963fb01ea24f628d826e
5
5
  SHA512:
6
- metadata.gz: 560dd5946e8a744de498eabc762f1f90f4c834a215a2b57e58adba24b9b5f6d6e1e5b878123195b82c2ec6f58f64468cdb530159cd30e5bb99f226134238d66a
7
- data.tar.gz: 4fdf98ad9829edfc5e254b4df9a7a7f765ee9de05784c76c6f6e35ee73f64b154e75bf40af6953873f0d1cfdeb0dbb096401cc982eac546388930b0219a5741b
6
+ metadata.gz: a8a4a13a02cd3214d4fe6605af7d6d96cc5218d2a566f541a702477030d94c9d5b402e177b6cbce40ed420e705bffb317c1c4f05d3a7cac9622972a667b57c03
7
+ data.tar.gz: d8666ed16a3e328e6eed21ac79585e72319fca38a149d06f1ce17bee706259aa227bc875dcf7c7463aee678434aac6884f5d87fe1869e0cc75932bd75a658467
data/README.md CHANGED
@@ -48,7 +48,7 @@ class ResourceInterface
48
48
  # @return [String]
49
49
  def jsonapi_id; end
50
50
 
51
- # Returns a hash containing, for each included relationship, an array of the
51
+ # Returns a hash containing, for each included relationship, an array of the
52
52
  # resources to be included from that one.
53
53
  # @param included_relationships [Array<Symbol>] The keys of the relationships
54
54
  # to be included.
@@ -57,8 +57,8 @@ class ResourceInterface
57
57
 
58
58
  # Returns a JSON API-compliant representation of the resource as a hash.
59
59
  # @param options [Hash]
60
- # @option fields [Array<Symbol>, Nil] The requested fields, or nil.
61
- # @option include [Array<Symbol>] The requested relationships to
60
+ # @option fields [Set<Symbol>, Nil] The requested fields, or nil.
61
+ # @option include [Set<Symbol>] The requested relationships to
62
62
  # include (defaults to []).
63
63
  # @return [Hash]
64
64
  def as_jsonapi(options = {}); end
@@ -87,6 +87,18 @@ JSONAPI.render(data: resources,
87
87
 
88
88
  This returns a JSON API compliant hash representing the described document.
89
89
 
90
+ #### Rendering a relationship
91
+ ```ruby
92
+ JSONAPI.render(data: resource,
93
+ relationship: :posts,
94
+ include: include_string,
95
+ fields: fields_hash,
96
+ meta: meta_hash,
97
+ links: links_hash)
98
+ ```
99
+
100
+ This returns a JSON API compliant hash representing the described document.
101
+
90
102
  ### Rendering errors
91
103
 
92
104
  ```ruby
@@ -100,6 +112,32 @@ returns a JSON API-compliant representation of the error.
100
112
 
101
113
  This returns a JSON API compliant hash representing the described document.
102
114
 
115
+ ### Caching
116
+
117
+ The generated JSON fragments can be cached in any cache implementation
118
+ supporting the `fetch_multi` method.
119
+
120
+ When using caching, the serializable resources must implement an
121
+ additional `jsonapi_cache_key` method:
122
+ ```ruby
123
+ # Returns a cache key for the resource, parametered by the `include` and
124
+ # `fields` options.
125
+ # @param options [Hash]
126
+ # @option fields [Set<Symbol>, Nil] The requested fields, or nil.
127
+ # @option include [Set<Symbol>] The requested relationships to
128
+ # include (defaults to []).
129
+ # @return [String]
130
+ def jsonapi_cache_key(options = {}); end
131
+ ```
132
+
133
+ The cache instance must be passed to the renderer as follows:
134
+ ```ruby
135
+ JSONAPI.render(data: resources,
136
+ include: include_string,
137
+ fields: fields_hash,
138
+ cache: cache_instance)
139
+ ```
140
+
103
141
  ## License
104
142
 
105
143
  jsonapi-renderer is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,42 @@
1
+ require 'jsonapi/renderer/resources_processor'
2
+
3
+ module JSONAPI
4
+ class Renderer
5
+ # @private
6
+ class CachedResourcesProcessor < ResourcesProcessor
7
+ class JSONString < String
8
+ def to_json(*)
9
+ self
10
+ end
11
+ end
12
+
13
+ def initialize(cache)
14
+ @cache = cache
15
+ end
16
+
17
+ def process_resources
18
+ [@primary, @included].each do |resources|
19
+ cache_hash = cache_key_map(resources)
20
+ processed_resources = @cache.fetch_multi(cache_hash.keys) do |key|
21
+ res, include, fields = cache_hash[key]
22
+ json = res.as_jsonapi(include: include, fields: fields).to_json
23
+
24
+ JSONString.new(json)
25
+ end
26
+
27
+ resources.replace(processed_resources.values)
28
+ end
29
+ end
30
+
31
+ def cache_key_map(resources)
32
+ resources.each_with_object({}) do |res, h|
33
+ ri = [res.jsonapi_type, res.jsonapi_id]
34
+ include_dir = @include_rels[ri]
35
+ fields = @fields[ri.first.to_sym]
36
+ h[res.jsonapi_cache_key(include: include_dir, fields: fields)] =
37
+ [res, include_dir, fields]
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,8 +1,10 @@
1
1
  require 'jsonapi/include_directive'
2
- require 'jsonapi/renderer/resources_processor'
2
+ require 'jsonapi/renderer/simple_resources_processor'
3
+ require 'jsonapi/renderer/cached_resources_processor'
3
4
 
4
5
  module JSONAPI
5
6
  class Renderer
7
+ # @private
6
8
  class Document
7
9
  def initialize(params = {})
8
10
  @data = params.fetch(:data, :no_data)
@@ -12,6 +14,8 @@ module JSONAPI
12
14
  @fields = _symbolize_fields(params[:fields] || {})
13
15
  @jsonapi = params[:jsonapi]
14
16
  @include = JSONAPI::IncludeDirective.new(params[:include] || {})
17
+ @relationship = params[:relationship]
18
+ @cache = params[:cache]
15
19
  end
16
20
 
17
21
  def to_hash
@@ -21,31 +25,69 @@ module JSONAPI
21
25
 
22
26
  private
23
27
 
28
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength
29
+ # rubocop:disable Metrics/CyclomaticComplexity
24
30
  def document_hash
25
31
  {}.tap do |hash|
26
- if @data != :no_data
32
+ if @relationship
33
+ hash.merge!(relationship_hash)
34
+ elsif @data != :no_data
27
35
  hash.merge!(data_hash)
28
36
  elsif @errors.any?
29
37
  hash.merge!(errors_hash)
30
38
  end
31
- hash[:links] = @links if @links.any?
32
- hash[:meta] = @meta unless @meta.nil?
33
- hash[:jsonapi] = @jsonapi unless @jsonapi.nil?
39
+ hash[:links] = @links if @links.any?
40
+ hash[:meta] = @meta unless @meta.nil?
41
+ hash[:jsonapi] = @jsonapi unless @jsonapi.nil?
34
42
  end
35
43
  end
44
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/MethodLength
45
+ # rubocop:enable Metrics/CyclomaticComplexity
36
46
 
37
47
  def data_hash
38
48
  primary, included =
39
- ResourcesProcessor.new(Array(@data), @include, @fields).process
49
+ resources_processor.process(Array(@data), @include, @fields)
40
50
  {}.tap do |hash|
41
51
  hash[:data] = @data.respond_to?(:to_ary) ? primary : primary[0]
42
52
  hash[:included] = included if included.any?
43
53
  end
44
54
  end
45
55
 
56
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
57
+ def relationship_hash
58
+ rel_name = @relationship.to_sym
59
+ data = @data.jsonapi_related([rel_name])[rel_name]
60
+ included =
61
+ if @include.key?(rel_name)
62
+ resources_processor.process(data, @include[rel_name], @fields)
63
+ .flatten!
64
+ else
65
+ []
66
+ end
67
+
68
+ res = @data.as_jsonapi(fields: [rel_name], include: [rel_name])
69
+ rel = res[:relationships][rel_name]
70
+ @links = rel[:links].merge!(@links)
71
+ @meta ||= rel[:meta]
72
+
73
+ {}.tap do |hash|
74
+ hash[:data] = rel[:data]
75
+ hash[:included] = included if included.any?
76
+ end
77
+ end
78
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
79
+
46
80
  def errors_hash
47
81
  {}.tap do |hash|
48
- hash[:errors] = @errors.map(&:as_jsonapi)
82
+ hash[:errors] = @errors.flat_map(&:as_jsonapi)
83
+ end
84
+ end
85
+
86
+ def resources_processor
87
+ if @cache
88
+ CachedResourcesProcessor.new(@cache)
89
+ else
90
+ SimpleResourcesProcessor.new
49
91
  end
50
92
  end
51
93
 
@@ -2,14 +2,13 @@ require 'set'
2
2
 
3
3
  module JSONAPI
4
4
  class Renderer
5
+ # @private
5
6
  class ResourcesProcessor
6
- def initialize(resources, include, fields)
7
+ def process(resources, include, fields)
7
8
  @resources = resources
8
9
  @include = include
9
10
  @fields = fields
10
- end
11
11
 
12
- def process
13
12
  traverse_resources
14
13
  process_resources
15
14
 
@@ -73,14 +72,7 @@ module JSONAPI
73
72
  end
74
73
 
75
74
  def process_resources
76
- [@primary, @included].each do |resources|
77
- resources.map! do |res|
78
- ri = [res.jsonapi_type, res.jsonapi_id]
79
- include_dir = @include_rels[ri]
80
- fields = @fields[res.jsonapi_type.to_sym]
81
- res.as_jsonapi(include: include_dir, fields: fields)
82
- end
83
- end
75
+ raise 'Not implemented'
84
76
  end
85
77
  end
86
78
  end
@@ -0,0 +1,19 @@
1
+ require 'jsonapi/renderer/resources_processor'
2
+
3
+ module JSONAPI
4
+ class Renderer
5
+ # @api private
6
+ class SimpleResourcesProcessor < ResourcesProcessor
7
+ def process_resources
8
+ [@primary, @included].each do |resources|
9
+ resources.map! do |res|
10
+ ri = [res.jsonapi_type, res.jsonapi_id]
11
+ include_dir = @include_rels[ri]
12
+ fields = @fields[res.jsonapi_type.to_sym]
13
+ res.as_jsonapi(include: include_dir, fields: fields)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Hosseini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-12 00:00:00.000000000 Z
11
+ date: 2017-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.5'
41
41
  - !ruby/object:Gem::Dependency
42
- name: codecov
42
+ name: simplecov
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0.1'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0.1'
54
+ version: '0'
55
55
  description: Efficiently render JSON API documents.
56
56
  email: lucas.hosseini@gmail.com
57
57
  executables: []
@@ -62,8 +62,10 @@ files:
62
62
  - lib/jsonapi/include_directive.rb
63
63
  - lib/jsonapi/include_directive/parser.rb
64
64
  - lib/jsonapi/renderer.rb
65
+ - lib/jsonapi/renderer/cached_resources_processor.rb
65
66
  - lib/jsonapi/renderer/document.rb
66
67
  - lib/jsonapi/renderer/resources_processor.rb
68
+ - lib/jsonapi/renderer/simple_resources_processor.rb
67
69
  homepage: https://github.com/jsonapi-rb/jsonapi-renderer
68
70
  licenses:
69
71
  - MIT
@@ -84,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
86
  version: '0'
85
87
  requirements: []
86
88
  rubyforge_project:
87
- rubygems_version: 2.6.12
89
+ rubygems_version: 2.6.13
88
90
  signing_key:
89
91
  specification_version: 4
90
92
  summary: Render JSONAPI documents.