jsonapi_spec_helpers 0.4.10 → 1.0.alpha.2

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: 7de8f729627057f5996f8455bc769caf8d0f5bbd
4
- data.tar.gz: 05436bab3f0d5377a8ecdffc549f10e475233d5e
3
+ metadata.gz: 17ecff418f690fa93ed1e4a44d139c46a9b00beb
4
+ data.tar.gz: 4e74adb0ea0593f7a28e7bc7485f20e6d55a1d08
5
5
  SHA512:
6
- metadata.gz: 9ec2ad279e5282fb83f7899d29af184e56efc37ee4aaa81eaa8020fbcbce920e0c3b49d66868219190c4c3a14a84f15fd9b78f10a22adf529b028550e4fc84f9
7
- data.tar.gz: da684de42e3c316343abcba437afcbc447a2fa6a44771778a75516feec6aba1be69d76cb25f50b248d853da0de319a9b235f13558b8efa5d7278fe2269f6d4b8
6
+ metadata.gz: 58f02d6265d70de7e97c544646698e71852421ae213f53e74f5e4bb187ffafb6fb29fabb63929906fbfea8a8d7f5a4cd6996a1514ee620a6e38e23e99903582c
7
+ data.tar.gz: c216961f4a62b64fb0a42058c1a3fcab986a9c1e4b43a2a7f1da61f8981b90bceb4eeb4b9f57263d902f62f78caae97f3ef529706893f6ed27d851a420237ecd
@@ -23,5 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "actionpack", "~> 5.0"
24
24
  spec.add_development_dependency "bundler", "~> 1.11"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "jsonapi_compliable", '>= 1.0.alpha.1'
26
27
  spec.add_dependency "rspec", "~> 3.0"
27
28
  end
@@ -1,16 +1,51 @@
1
1
  module JsonapiSpecHelpers
2
2
  module Errors
3
3
  class Base < StandardError; end
4
- class IncludedOutOfBounds < Base
5
- def initialize(type, index, array)
6
- @type = type; @index = index; @array = array
4
+
5
+ class LinksNotFound < Base
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def message
11
+ "Relationship with name '#{@name}' has no links!"
12
+ end
13
+ end
14
+
15
+ class SideloadNotFound < Base
16
+ def initialize(name)
17
+ @name = name
18
+ end
19
+
20
+ def message
21
+ "Relationship with name '#{@name}' not found!"
22
+ end
23
+ end
24
+
25
+ class NoResponse < Base
26
+ def message
27
+ "Cannot parse response - missing #response.body!"
28
+ end
29
+ end
30
+
31
+ class NoData < Base
32
+ def initialize(payload)
33
+ @payload = payload
34
+ end
35
+
36
+ def message
37
+ "Payload did not contain 'data'! Payload was:\n\n#{JSON.pretty_generate(@payload)}"
38
+ end
39
+ end
40
+
41
+ class NoSideloads < Base
42
+ def initialize(payload)
43
+ @payload = payload
7
44
  end
8
45
 
9
46
  def message
10
- "You attempted to get an item at index #{@index} of the type '#{@type}' " \
11
- "from the included property of your JSON payload. But it contained " \
12
- "#{@array.length} '#{@type}'"
47
+ "Tried to find sideload, but the payload did not contain 'included'! Payload was:\n\n#{JSON.pretty_generate(@payload)}"
13
48
  end
14
49
  end
15
50
  end
16
- end
51
+ end
@@ -0,0 +1,70 @@
1
+ module JsonapiSpecHelpers
2
+ class ErrorsProxy
3
+ class Error
4
+ attr_reader :json
5
+
6
+ def initialize(json)
7
+ @json = json
8
+ end
9
+
10
+ def attribute
11
+ @json[:meta][:attribute]
12
+ end
13
+
14
+ # TODO: move to top-level code in errorable
15
+ def code
16
+ @json[:meta][:code]
17
+ end
18
+
19
+ def message
20
+ @json[:meta][:message]
21
+ end
22
+
23
+ def title
24
+ @json[:title]
25
+ end
26
+
27
+ def detail
28
+ @json[:detail]
29
+ end
30
+
31
+ def status
32
+ @json[:status]
33
+ end
34
+ end
35
+
36
+ include Enumerable
37
+
38
+ def initialize(array)
39
+ @errors = array.map { |e| Error.new(e) }
40
+ end
41
+
42
+ def [](key)
43
+ @errors[key]
44
+ end
45
+
46
+ def each(&blk)
47
+ @errors.each(&blk)
48
+ end
49
+
50
+ def length
51
+ count
52
+ end
53
+
54
+ def to_h
55
+ {}.tap do |hash|
56
+ @errors.each do |e|
57
+ hash[e.attribute] = e.message
58
+ end
59
+ end
60
+ end
61
+
62
+ def method_missing(id, *args, &blk)
63
+ if error = @errors.find { |e| e.attribute == id }
64
+ return error
65
+ else
66
+ super
67
+ end
68
+ end
69
+ end
70
+ end
@@ -1,77 +1,40 @@
1
1
  module JsonapiSpecHelpers
2
2
  module Helpers
3
- def json
4
- JSON.parse(response.body)
5
- end
6
-
7
- def json_item(from: nil)
8
- from = json if from.nil?
9
- data = from.has_key?('data') ? from['data'] : from
10
-
11
- {}.tap do |item|
12
- item['id'] = data['id']
13
- item['jsonapi_type'] = data['type']
14
- item.merge!(data['attributes']) if data.has_key?('attributes')
15
- end
16
- end
3
+ extend ActiveSupport::Concern
17
4
 
18
- def json_items(*indices)
19
- items = []
20
- json['data'].each_with_index do |datum, index|
21
- included = indices.empty? || indices.include?(index)
22
- items << json_item(from: datum) if included
5
+ def json
6
+ if response && response.body
7
+ JSON.parse(response.body).with_indifferent_access
8
+ else
9
+ raise Errors::NoResponse.new
23
10
  end
24
- indices.length == 1 ? items[0] : items
25
- end
26
-
27
- def json_related_link(payload, assn_name)
28
- link = payload['relationships'][assn_name]['links']['related']['href']
29
- fail "link for #{assn_name} not found" unless link
30
- URI.decode(link)
31
11
  end
32
12
 
33
- def json_included_types
34
- (json['included'] || []).map { |i| i['type'] }.uniq
35
- end
36
-
37
- def json_includes(type, *indices)
38
- included = (json['included'] || []).select { |data| data['type'] == type }
39
- indices = (0...included.length).to_a if indices.empty?
40
- includes = []
41
- indices.each do |index|
42
- single_included = included.at(index)
43
- if single_included.nil?
44
- raise Errors::IncludedOutOfBounds.new(type, index, included)
13
+ def jsonapi_data
14
+ @jsonapi_data ||= begin
15
+ if _jsonapi_data.is_a?(Hash)
16
+ node(from: _jsonapi_data)
17
+ else
18
+ _jsonapi_data.map { |datum| node(from: datum) }
45
19
  end
46
- includes << json_item(from: single_included)
47
20
  end
48
- includes
49
21
  end
50
22
 
51
- def json_include(type, index = 0)
52
- json_includes(type, index)[0]
53
- end
23
+ def jsonapi_included(type = nil)
24
+ variable = :"@jsonapi_included#{type}"
25
+ memo = instance_variable_get(variable)
26
+ return memo if memo
54
27
 
55
- def json_ids(integers = false)
56
- ids = json['data'].map { |d| d['id'] }
57
- ids.map! { |id| Integer(id) } if integers
58
- ids
28
+ nodes = _jsonapi_included.map { |i| node(from: i) }
29
+ if type
30
+ nodes.select! { |n| n.jsonapi_type == type }
31
+ end
32
+ instance_variable_set(variable, nodes)
33
+ nodes
59
34
  end
60
35
 
61
- def validation_errors
62
- @validation_errors ||= {}.tap do |errors|
63
- return errors if json['errors'].nil?
64
- json['errors'].each do |e|
65
- attr = e['meta']['attribute'].to_sym
66
- message = e['meta']['message']
67
-
68
- if errors[attr]
69
- errors[attr] = Array(errors[attr]).push(message)
70
- else
71
- errors[attr] = message
72
- end
73
- end
74
- end
36
+ def jsonapi_errors
37
+ @jsonapi_errors ||= ErrorsProxy.new(json['errors'] || [])
75
38
  end
76
39
 
77
40
  def jsonapi_headers
@@ -100,8 +63,35 @@ module JsonapiSpecHelpers
100
63
  delete url, headers: jsonapi_headers
101
64
  end
102
65
 
103
- def jsonapi_payload(input)
104
- PayloadSanitizer.new(input).sanitize
66
+ def datetime(value)
67
+ JsonapiCompliable::Types[:datetime][:read][value]
68
+ end
69
+
70
+ # @api private
71
+ def node(from: nil)
72
+ from = json if from.nil?
73
+ data = from.has_key?('data') ? from['data'] : from
74
+ hash = {}
75
+ hash['id'] = data['id']
76
+ hash['jsonapi_type'] = data['type']
77
+ hash.merge!(data['attributes']) if data.has_key?('attributes')
78
+ Node.new(hash, data['relationships'], self)
79
+ end
80
+
81
+ private
82
+
83
+ # @api private
84
+ def _jsonapi_data
85
+ json['data'] || raise(Errors::NoData.new(json))
86
+ end
87
+
88
+ # @api private
89
+ def _jsonapi_included
90
+ if json.has_key?('included')
91
+ json['included']
92
+ else
93
+ raise Errors::NoSideloads.new(json)
94
+ end
105
95
  end
106
96
  end
107
97
  end
@@ -0,0 +1,81 @@
1
+ module JsonapiSpecHelpers
2
+ class Node
3
+ attr_reader :attributes, :relationships
4
+
5
+ def initialize(attributes, relationships, context)
6
+ @attributes = attributes.with_indifferent_access
7
+ @relationships = relationships
8
+ @context = context
9
+ end
10
+
11
+ def id
12
+ rawid.to_i
13
+ end
14
+
15
+ def rawid
16
+ @attributes['id']
17
+ end
18
+
19
+ def jsonapi_type
20
+ @attributes['jsonapi_type']
21
+ end
22
+
23
+ def has_key?(key)
24
+ @attributes.has_key?(key)
25
+ end
26
+
27
+ def [](key)
28
+ @attributes[key] || @attributes[key.to_s]
29
+ end
30
+
31
+ def []=(key, val)
32
+ @attributes[key] = val
33
+ end
34
+
35
+ def attributes
36
+ @attributes
37
+ end
38
+
39
+ def method_missing(id, *args, &blk)
40
+ if @attributes.has_key?(id)
41
+ @attributes[id]
42
+ else
43
+ super
44
+ end
45
+ end
46
+
47
+ def link(relationship_name, name)
48
+ if @relationships.has_key?(relationship_name)
49
+ links = @relationships[relationship_name][:links]
50
+ raise Errors::LinksNotFound.new(relationship_name) unless links
51
+ links[name]
52
+ else
53
+ raise Errors::SideloadNotFound.new(relationship_name)
54
+ end
55
+ end
56
+
57
+ def sideload(relationship_name)
58
+ unless @relationships.has_key?(relationship_name)
59
+ raise Errors::SideloadNotFound.new(relationship_name)
60
+ end
61
+ rel = @relationships[relationship_name]
62
+ rel = rel[:data]
63
+ return if rel.nil?
64
+ if rel.is_a?(Hash)
65
+ include_for(rel[:type], rel[:id])
66
+ else
67
+ rel.map { |r| include_for(r[:type], r[:id]) }
68
+ end
69
+ end
70
+ alias :sideloads :sideload
71
+
72
+ private
73
+
74
+ def include_for(type, id)
75
+ data = @context.json[:included].find do |i|
76
+ i[:type] == type && i[:id] == id
77
+ end
78
+ @context.node(from: data)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,44 @@
1
+ require 'jsonapi_spec_helpers'
2
+
3
+ ::RSpec.shared_context 'resource testing', type: :resource do |parameter|
4
+ let(:resource) { described_class }
5
+ let(:params) { {} }
6
+
7
+ # If you need to set context:
8
+ #
9
+ # JsonapiCompliable.with_context my_context, {} do
10
+ # render
11
+ # end
12
+ def render(runtime_options = {})
13
+ json = proxy.to_jsonapi(runtime_options)
14
+ response.body = json
15
+ json
16
+ end
17
+
18
+ def proxy
19
+ @proxy ||= begin
20
+ ctx = ::JsonapiSpecHelpers::TestRunner.new(resource, params)
21
+ defined?(base_scope) ? ctx.proxy(base_scope) : ctx.proxy
22
+ end
23
+ end
24
+
25
+ def records
26
+ proxy.data
27
+ end
28
+
29
+ def response
30
+ @response ||= OpenStruct.new
31
+ end
32
+ end
33
+
34
+ module JsonapiSpecHelpers
35
+ module RSpec
36
+ def self.included(klass)
37
+ klass.send(:include, JsonapiSpecHelpers)
38
+
39
+ ::RSpec.configure do |rspec|
40
+ rspec.include_context "resource testing", type: :resource
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module JsonapiSpecHelpers
2
- VERSION = "0.4.10"
2
+ VERSION = "1.0.alpha.2"
3
3
  end
@@ -1,58 +1,37 @@
1
1
  require 'json'
2
+ require 'pp'
3
+ require 'active_support/core_ext/string'
4
+ require 'active_support/core_ext/hash'
5
+ require 'jsonapi_compliable'
6
+
2
7
  require 'jsonapi_spec_helpers/version'
3
8
  require 'jsonapi_spec_helpers/helpers'
4
- require 'jsonapi_spec_helpers/payload'
5
- require 'jsonapi_spec_helpers/payload_sanitizer'
9
+ require 'jsonapi_spec_helpers/node'
10
+ require 'jsonapi_spec_helpers/errors_proxy'
6
11
  require 'jsonapi_spec_helpers/errors'
7
12
 
8
13
  module JsonapiSpecHelpers
9
14
  def self.included(klass)
10
- # don't load RSpec until included
11
- require 'jsonapi_spec_helpers/matchers'
12
15
  klass.send(:include, Helpers)
13
- if defined?(Rails)
14
- load_payloads!
15
- end
16
16
  end
17
17
 
18
- def self.load_payloads!
19
- Dir[Rails.root.join('spec/payloads/**/*.rb')].each { |f| require f }
18
+ class TestRunner < ::JsonapiCompliable::Runner
19
+ def current_user
20
+ nil
21
+ end
20
22
  end
21
23
 
22
- def assert_payload(name, record, json, &blk)
23
- unless payload = JsonapiSpecHelpers::Payload.registry[name]
24
- raise "No payloads registered for '#{name}'"
24
+ module Sugar
25
+ def d
26
+ jsonapi_data
25
27
  end
26
28
 
27
- if blk
28
- payload = payload.fork
29
- payload.instance_eval(&blk)
29
+ def included(type = nil)
30
+ jsonapi_included(type)
30
31
  end
31
32
 
32
- aggregate_failures "payload has correct key/values" do
33
- payload.keys.each_pair do |attribute, options|
34
- prc = options[:proc]
35
- if (expect(json).to have_payload_key(attribute, options[:allow_nil])) == true
36
- unless options[:allow_nil]
37
- output = instance_exec(record, &prc)
38
- expect(json[attribute.to_s]).to match_payload(attribute, output)
39
-
40
- if options[:type]
41
- expect(json[attribute.to_s]).to match_type(attribute, options[:type])
42
- end
43
- end
44
- end
45
- end
46
-
47
- payload.no_keys.each do |no_key|
48
- expect(json).to_not have_payload_key(no_key, {})
49
- end
50
-
51
- unexpected_keys = json.keys - payload.keys.keys.map(&:to_s)
52
- unexpected_keys.reject! { |k| %w(id jsonapi_type).include?(k) }
53
- unexpected_keys.each do |key|
54
- expect(key).to be_not_in_payload
55
- end
33
+ def errors
34
+ jsonapi_errors
56
35
  end
57
36
  end
58
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi_spec_helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.10
4
+ version: 1.0.alpha.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Richmond
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-28 00:00:00.000000000 Z
11
+ date: 2018-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: jsonapi_compliable
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.0.alpha.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.0.alpha.1
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -114,10 +128,10 @@ files:
114
128
  - jsonapi_spec_helpers.gemspec
115
129
  - lib/jsonapi_spec_helpers.rb
116
130
  - lib/jsonapi_spec_helpers/errors.rb
131
+ - lib/jsonapi_spec_helpers/errors_proxy.rb
117
132
  - lib/jsonapi_spec_helpers/helpers.rb
118
- - lib/jsonapi_spec_helpers/matchers.rb
119
- - lib/jsonapi_spec_helpers/payload.rb
120
- - lib/jsonapi_spec_helpers/payload_sanitizer.rb
133
+ - lib/jsonapi_spec_helpers/node.rb
134
+ - lib/jsonapi_spec_helpers/rspec.rb
121
135
  - lib/jsonapi_spec_helpers/version.rb
122
136
  homepage:
123
137
  licenses:
@@ -134,12 +148,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
134
148
  version: '0'
135
149
  required_rubygems_version: !ruby/object:Gem::Requirement
136
150
  requirements:
137
- - - ">="
151
+ - - ">"
138
152
  - !ruby/object:Gem::Version
139
- version: '0'
153
+ version: 1.3.1
140
154
  requirements: []
141
155
  rubyforge_project:
142
- rubygems_version: 2.6.12
156
+ rubygems_version: 2.6.13
143
157
  signing_key:
144
158
  specification_version: 4
145
159
  summary: Spec helpers for jsonapi
@@ -1,61 +0,0 @@
1
- require 'rspec/matchers'
2
-
3
- RSpec::Matchers.define :match_payload do |attribute, expected|
4
- match do |actual|
5
- if expected.respond_to?(:as_json)
6
- expected = expected.as_json
7
- end
8
-
9
- actual == expected
10
- end
11
-
12
- failure_message do |actual|
13
- "Expected JSON payload to have key '#{attribute}' == #{expected.inspect} but was #{actual.inspect}"
14
- end
15
- end
16
-
17
- RSpec::Matchers.define :match_type do |attribute, type|
18
- match do |actual|
19
- if type.is_a?(Array)
20
- type.any? { |t| actual.is_a?(t) }
21
- else
22
- actual.is_a?(type)
23
- end
24
- end
25
-
26
- failure_message do |actual|
27
- "Expected JSON payload key '#{attribute}' to have type #{type} but was #{actual.class}"
28
- end
29
- end
30
-
31
- RSpec::Matchers.define :have_payload_key do |expected, allow_nil|
32
- match do |json|
33
- @has_key = json.has_key?(expected.to_s)
34
- @has_value = !json[expected.to_s].nil?
35
-
36
- if allow_nil
37
- @has_key
38
- else
39
- @has_key && @has_value
40
- end
41
- end
42
-
43
- failure_message do |actual|
44
- msg = !allow_nil && @has_key ? "nil. Use 'key(:foo, allow_nil: true)' to allow nils" : "not present"
45
- "Expected JSON payload to have key '#{expected}' but was #{msg}"
46
- end
47
-
48
- failure_message_when_negated do |actual|
49
- "Expected JSON payload to NOT have key '#{expected}' but was present"
50
- end
51
- end
52
-
53
- RSpec::Matchers.define :be_not_in_payload do |expected|
54
- match do |json|
55
- false
56
- end
57
-
58
- failure_message do |actual|
59
- "JSON payload contained unexpected key '#{actual}'"
60
- end
61
- end
@@ -1,66 +0,0 @@
1
- module JsonapiSpecHelpers
2
- class Payload
3
- class << self
4
- attr_accessor :registry
5
- end
6
- self.registry = {}
7
-
8
- attr_accessor :name, :type, :keys, :no_keys
9
-
10
- def self.register(name, &blk)
11
- instance = new
12
- instance.instance_eval(&blk)
13
- instance.name = name
14
- registry[name] = instance
15
- end
16
-
17
- def self.by_type(type)
18
- found = nil
19
- registry.each_pair do |name, payload|
20
- found = payload if payload.type == type
21
- end
22
- raise "Could not find payload for type #{type}" unless found
23
- found
24
- end
25
-
26
- def fork
27
- instance = self.class.new
28
- instance.keys = keys.dup
29
- instance.no_keys = no_keys.dup
30
- instance
31
- end
32
-
33
- def initialize
34
- @keys = {}
35
- @no_keys = []
36
- end
37
-
38
- def no_key(name)
39
- @keys.delete(name)
40
- @no_keys << name
41
- end
42
-
43
- def type(val = nil)
44
- if val
45
- @type = val
46
- else
47
- @type || name.to_s.pluralize.to_sym
48
- end
49
- end
50
-
51
- def key(name, *args, &blk)
52
- options = args.last.is_a?(Hash) ? args.pop : {}
53
- options[:type] = args.first
54
- options[:allow_nil] ||= false
55
- @no_keys.reject! { |k| k == name }
56
- prc = blk
57
- prc = ->(record) { record.send(name) } if prc.nil?
58
- @keys[name] = options.merge(proc: prc)
59
- end
60
-
61
- def timestamps!
62
- @keys[:created_at] = key(:created_at, String)
63
- @keys[:updated_at] = key(:updated_at, String)
64
- end
65
- end
66
- end
@@ -1,93 +0,0 @@
1
- module JsonapiSpecHelpers
2
- class PayloadSanitizer
3
- def initialize(payload)
4
- @payload = payload
5
- @included = []
6
- end
7
-
8
- def resource
9
- @resource ||= sane_resource(@payload)
10
- end
11
-
12
- def sanitize
13
- resource[:relationships].each_pair do |key, relationship_payload|
14
- set_default_relationship_payload(key, relationship_payload)
15
-
16
- if relationship_payload.is_a?(Array)
17
- relationship_payload.each do |p|
18
- process_relationship(key, p)
19
- end
20
- else
21
- process_relationship(key, relationship_payload)
22
- end
23
- end
24
-
25
- payload = { data: data }
26
- payload[:included] = @included
27
- payload
28
- end
29
-
30
- def included
31
- @included
32
- end
33
-
34
- def add_include(incl)
35
- @included.push(incl) if @included.index(incl).nil?
36
- end
37
-
38
- def resource_identifier
39
- {}.tap do |ri|
40
- ri[:id] = resource[:id] if resource[:id]
41
- ri[:type] = resource[:type]
42
- end
43
- end
44
-
45
- def data
46
- @data ||= {}.tap do |d|
47
- d[:id] = resource[:id] if resource[:id]
48
- d[:type] = resource[:type]
49
- d[:attributes] = resource[:attributes]
50
- end
51
- end
52
-
53
- private
54
-
55
- def set_default_relationship_payload(key, payload)
56
- data[:relationships] ||= {}
57
- if payload.is_a?(Array)
58
- data[:relationships][key] ||= { data: [] }
59
- else
60
- data[:relationships][key] ||= { data: nil }
61
- end
62
- end
63
-
64
- def process_relationship(name, relationship_payload)
65
- sanitizer = self.class.new(relationship_payload)
66
-
67
- if data[:relationships][name][:data].is_a?(Array)
68
- data[:relationships][name][:data] << sanitizer.resource_identifier
69
- else
70
- data[:relationships][name] = { data: sanitizer.resource_identifier }
71
- end
72
-
73
- sanitized = sanitizer.sanitize
74
- add_include(sanitized[:data])
75
- sanitized[:included].each do |incl|
76
- add_include(incl)
77
- end
78
- end
79
-
80
- def sane_resource(payload)
81
- id, type = payload.delete(:id), payload.delete(:type)
82
- relationships = payload.delete(:relationships) || {}
83
- raise 'jsonapi payloads must specify a "type"' if type.nil?
84
-
85
- {
86
- id: id,
87
- type: type,
88
- attributes: payload,
89
- relationships: relationships
90
- }
91
- end
92
- end
93
- end