graphiti 1.0.3 → 1.1.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
  SHA256:
3
- metadata.gz: 501d03b06258694566979a6f54104d8da41a44ab6dadec078e7b84ef047de364
4
- data.tar.gz: cb85e65ffb73f9294cd0173eee9a0f2e8239697dac1a83adbe58a2faf9c6cbe9
3
+ metadata.gz: 292ab84397ae7ce761553abe89c12027aa9df8eaf42e19c746b3e15b483b129f
4
+ data.tar.gz: f0ed1abbace00c61d43821d8b8a8a59365e62f5fd2065d356391a8e391bd483b
5
5
  SHA512:
6
- metadata.gz: 917d60f26882a2efbcebcf80279aa624b795628d6ad6fdc201dd8c4511e3a7caf6979fbf24c870aa176827dfe7daeffef0a1b5e5e73cec8d83bec98761ad1a9f
7
- data.tar.gz: 1028dc0fe60eb8b4b54f119ccb12308390ff849c48047f6597e4149dbf6123aae296299d231fde9fa3469c023d7caa86b9e5ce334dc079547932ba886512e38e
6
+ metadata.gz: 707372b30ade3c299f8569de0e53351cbca316f93e0b04aa4a0fbcac165c164c12cf3ec6ca57e06e212f616765031cdb4643a33cd941871ae5fd5e590bf5a00d
7
+ data.tar.gz: 29b33d2e5667cc0ec0a48883e1138312756fd0b1bafa22007bb1dd3a0fafe1567a3c6f7b0709e60d4f09cd8bdb4c8abd8578cd987d50c3128295971be94035b1
data/.travis.yml CHANGED
@@ -37,9 +37,9 @@ matrix:
37
37
  rvm: 2.6
38
38
 
39
39
  script:
40
- - bundle exec $COMMAND
40
+ - bundle _1.17.3_ exec $COMMAND
41
41
 
42
- install: bundle install --retry=3 --jobs=3
42
+ install: bundle _1.17.3_ install --retry=3 --jobs=3
43
43
  before_install:
44
44
  - gem install bundler -v '1.17.3'
45
45
  deploy:
data/CHANGELOG.md CHANGED
@@ -1,9 +1,25 @@
1
+ ## 1.1.0
2
+
3
+ Features:
4
+
5
+ - [#126](https://github.com/graphiti-api/graphiti/pull/126) Render helpful user-facing errors when a write payload is invalid (@wadetandy)
6
+
7
+ Fixes:
8
+
9
+ - [#136](https://github.com/graphiti-api/graphiti/pull/136) Fix remote
10
+ belongs_to links (@richmolj)
11
+
12
+ Misc:
13
+
14
+ - [#123](https://github.com/graphiti-api/graphiti/pull/123) Throw
15
+ better error when polymorphic type not found.
16
+
1
17
  ## 1.0.3
2
18
 
3
19
  Fixes:
4
20
 
5
21
  - [#130](https://github.com/graphiti-api/graphiti/pull/130) Run query
6
- blocks in resource context.
22
+ blocks in resource context (@richmolj)
7
23
 
8
24
  ## 1.0.2
9
25
 
@@ -20,11 +36,6 @@ Fixes:
20
36
 
21
37
  ### master (unreleased)
22
38
 
23
- Misc:
24
-
25
- - [#123](https://github.com/graphiti-api/graphiti/pull/123) Throw
26
- better error when polymorphic type not found.
27
-
28
39
  <!-- ### [version (YYYY-MM-DD)](diff_link) -->
29
40
  <!-- Breaking changes:-->
30
41
  <!-- Features:-->
data/graphiti.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency "jsonapi-serializable", "~> 0.3.0"
22
22
  spec.add_dependency "dry-types", "~> 0.15"
23
- spec.add_dependency "graphiti_errors", "~> 1.0.beta.1"
23
+ spec.add_dependency "graphiti_errors", "~> 1.1.0"
24
24
  spec.add_dependency "concurrent-ruby", "~> 1.0"
25
25
  spec.add_dependency "activesupport", [">= 4.1", "< 6"]
26
26
 
@@ -8,8 +8,7 @@ RSpec.describe "<%= type %>#create", type: :request do
8
8
  describe 'basic create' do
9
9
  let(:params) do
10
10
  <%- if defined?(FactoryBot) -%>
11
- attributes_for(:<%= type.to_s.singularize %>).
12
- except("created_at", "updated_at")
11
+ attributes_for(:<%= type.to_s.singularize %>)
13
12
  <%- else -%>
14
13
  {
15
14
  # ... your attrs here
@@ -7,8 +7,7 @@ RSpec.describe <%= resource_class %>, type: :resource do
7
7
  data: {
8
8
  type: '<%= type %>',
9
9
  <%- if defined?(FactoryBot) -%>
10
- attributes: attributes_for(:<%= type.to_s.singularize %>).
11
- except("created_at", "updated_at")
10
+ attributes: attributes_for(:<%= type.to_s.singularize %>)
12
11
  <%- else -%>
13
12
  attributes: { }
14
13
  <%- end -%>
data/lib/graphiti.rb CHANGED
@@ -38,6 +38,7 @@ require "graphiti/sideload/many_to_many"
38
38
  require "graphiti/sideload/polymorphic_belongs_to"
39
39
  require "graphiti/resource"
40
40
  require "graphiti/resource_proxy"
41
+ require "graphiti/request_validator"
41
42
  require "graphiti/query"
42
43
  require "graphiti/scope"
43
44
  require "graphiti/deserializer"
@@ -61,6 +62,7 @@ require "graphiti/util/relationship_payload"
61
62
  require "graphiti/util/persistence"
62
63
  require "graphiti/util/validation_response"
63
64
  require "graphiti/util/sideload"
65
+ require "graphiti/util/simple_errors"
64
66
  require "graphiti/util/transaction_hooks_recorder"
65
67
  require "graphiti/util/attribute_check"
66
68
  require "graphiti/util/serializer_attributes"
@@ -88,14 +90,6 @@ if defined?(Rails)
88
90
  end
89
91
 
90
92
  module Graphiti
91
- autoload :Base, "graphiti/base"
92
-
93
- def self.included(klass)
94
- klass.instance_eval do
95
- include Base
96
- end
97
- end
98
-
99
93
  # @api private
100
94
  def self.context
101
95
  Thread.current[:context] ||= {}
@@ -87,6 +87,7 @@ class Graphiti::Deserializer
87
87
  type: data[:type],
88
88
  temp_id: data[:'temp-id'],
89
89
  method: action,
90
+ payload_path: ["data"],
90
91
  }
91
92
  end
92
93
 
@@ -168,6 +169,8 @@ class Graphiti::Deserializer
168
169
  (i[:id] && i[:id] == datum[:id]) ||
169
170
  (i[:'temp-id'] && i[:'temp-id'] == temp_id)
170
171
  }
172
+ included_idx = included.index(included_object)
173
+
171
174
  included_object ||= {}
172
175
  included_object[:relationships] ||= {}
173
176
 
@@ -182,6 +185,7 @@ class Graphiti::Deserializer
182
185
  jsonapi_type: datum[:type],
183
186
  temp_id: temp_id,
184
187
  method: method,
188
+ payload_path: ["included", included_idx],
185
189
  },
186
190
  attributes: attributes,
187
191
  relationships: relationships,
@@ -320,9 +320,7 @@ module Graphiti
320
320
  @resource = resource
321
321
  @name = name
322
322
  @flag = flag
323
- @exists = opts[:exists] || false
324
323
  @request = opts[:request] || false
325
- @guard = opts[:guard]
326
324
  end
327
325
 
328
326
  def action
@@ -353,20 +351,35 @@ module Graphiti
353
351
  end
354
352
 
355
353
  def message
356
- msg = "#{resource_name}: Tried to #{action} attribute #{@name.inspect}"
357
- msg << if @exists
358
- if @guard
359
- ", but the guard #{@guard.inspect} did not pass."
360
- else
361
- ", but the attribute was marked #{@flag.inspect} => false."
362
- end
354
+ "#{resource_name}: Tried to #{action} attribute #{@name.inspect}"
355
+ end
356
+ end
357
+
358
+ class InvalidAttributeAccess < AttributeError
359
+ def initialize(resource, name, flag, **opts)
360
+ super
361
+ @guard = opts[:guard]
362
+ end
363
+
364
+ def message
365
+ msg = super
366
+
367
+ msg << if @guard
368
+ ", but the guard #{@guard.inspect} did not pass."
363
369
  else
364
- ", but could not find an attribute with that name."
370
+ ", but the attribute was marked #{@flag.inspect} => false."
365
371
  end
372
+
366
373
  msg
367
374
  end
368
375
  end
369
376
 
377
+ class UnknownAttribute < AttributeError
378
+ def message
379
+ "#{super}, but could not find an attribute with that name."
380
+ end
381
+ end
382
+
370
383
  class InvalidJSONArray < Base
371
384
  def initialize(resource, value)
372
385
  @resource = resource
@@ -397,7 +410,7 @@ module Graphiti
397
410
 
398
411
  Or whitelist a secondary endpoint:
399
412
 
400
- secondary_endoint '/my_url', [:index, :update]
413
+ secondary_endpoint '/my_url', [:index, :update]
401
414
 
402
415
  The current endpoints allowed for this resource are: #{@resource_class.endpoints.inspect}
403
416
  MSG
@@ -513,11 +526,14 @@ module Graphiti
513
526
  end
514
527
 
515
528
  class TypecastFailed < Base
516
- def initialize(resource, name, value, error)
529
+ attr_reader :name, :type_name
530
+
531
+ def initialize(resource, name, value, error, type_name)
517
532
  @resource = resource
518
533
  @name = name
519
534
  @value = value
520
535
  @error = error
536
+ @type_name = type_name
521
537
  end
522
538
 
523
539
  def message
@@ -735,5 +751,21 @@ module Graphiti
735
751
  end
736
752
  end
737
753
  end
754
+
755
+ class InvalidRequest < Base
756
+ attr_reader :errors
757
+
758
+ def initialize(errors)
759
+ @errors = errors
760
+ end
761
+
762
+ def message
763
+ <<-MSG
764
+ There were one or more errors with your request:
765
+
766
+ #{errors.full_messages.join("\n")}
767
+ MSG
768
+ end
769
+ end
738
770
  end
739
771
  end
@@ -73,7 +73,7 @@ module Graphiti
73
73
  ::ActionController::Renderers.add(:jsonapi_errors) do |proxy, options|
74
74
  self.content_type ||= Mime[:jsonapi]
75
75
 
76
- validation = GraphitiErrors::Serializers::Validation.new \
76
+ validation = GraphitiErrors::Validation::Serializer.new \
77
77
  proxy.data, proxy.payload.relationships
78
78
 
79
79
  render \
@@ -0,0 +1,94 @@
1
+ module Graphiti
2
+ class RequestValidator
3
+ attr_reader :errors
4
+
5
+ def initialize(root_resource, raw_params)
6
+ @root_resource = root_resource
7
+ @raw_params = raw_params
8
+ @errors = Graphiti::Util::SimpleErrors.new(raw_params)
9
+ end
10
+
11
+ def validate
12
+ resource = @root_resource
13
+ if (meta_type = deserialized_payload.meta[:type].try(:to_sym))
14
+ if @root_resource.type != meta_type && @root_resource.polymorphic?
15
+ resource = @root_resource.class.resource_for_type(meta_type).new
16
+ end
17
+ end
18
+
19
+ typecast_attributes(resource, deserialized_payload.attributes, deserialized_payload.meta[:payload_path])
20
+ process_relationships(resource, deserialized_payload.relationships, deserialized_payload.meta[:payload_path])
21
+
22
+ errors.blank?
23
+ end
24
+
25
+ def validate!
26
+ unless validate
27
+ raise Graphiti::Errors::InvalidRequest, self.errors
28
+ end
29
+
30
+ true
31
+ end
32
+
33
+ def deserialized_payload
34
+ @deserialized_payload ||= begin
35
+ payload = normalized_params
36
+ if payload[:data] && payload[:data][:type]
37
+ Graphiti::Deserializer.new(payload)
38
+ else
39
+ Graphiti::Deserializer.new({})
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def process_relationships(resource, relationships, payload_path)
47
+ opts = {
48
+ resource: resource,
49
+ relationships: relationships,
50
+ }
51
+
52
+ Graphiti::Util::RelationshipPayload.iterate(opts) do |x|
53
+ sideload_def = x[:sideload]
54
+
55
+ unless sideload_def.writable?
56
+ full_key = fully_qualified_key(sideload_def.name, payload_path, :relationships)
57
+ unless @errors.added?(full_key, :unwritable_relationship)
58
+ @errors.add(full_key, :unwritable_relationship)
59
+ end
60
+ next
61
+ end
62
+
63
+ typecast_attributes(x[:resource], x[:attributes], x[:meta][:payload_path])
64
+ process_relationships(x[:resource], x[:relationships], x[:meta][:payload_path])
65
+ end
66
+ end
67
+
68
+ def typecast_attributes(resource, attributes, payload_path)
69
+ attributes.each_pair do |key, value|
70
+ begin
71
+ attributes[key] = resource.typecast(key, value, :writable)
72
+ rescue Graphiti::Errors::UnknownAttribute
73
+ @errors.add(fully_qualified_key(key, payload_path), :unknown_attribute, message: "is an unknown attribute")
74
+ rescue Graphiti::Errors::InvalidAttributeAccess
75
+ @errors.add(fully_qualified_key(key, payload_path), :unwritable_attribute, message: "cannot be written")
76
+ rescue Graphiti::Errors::TypecastFailed => e
77
+ @errors.add(fully_qualified_key(key, payload_path), :type_error, message: "should be type #{e.type_name}")
78
+ end
79
+ end
80
+ end
81
+
82
+ def normalized_params
83
+ normalized = @raw_params
84
+ if normalized.respond_to?(:to_unsafe_h)
85
+ normalized = normalized.to_unsafe_h.deep_symbolize_keys
86
+ end
87
+ normalized
88
+ end
89
+
90
+ def fully_qualified_key(key, path, attributes_or_relationships = :attributes)
91
+ (path + [attributes_or_relationships, key]).join(".")
92
+ end
93
+ end
94
+ end
@@ -76,7 +76,7 @@ module Graphiti
76
76
  flag = :params if [:sortable, :filterable].include?(flag)
77
77
  type[flag][value]
78
78
  rescue => e
79
- raise Errors::TypecastFailed.new(self, name, value, e)
79
+ raise Errors::TypecastFailed.new(self, name, value, e, type_name)
80
80
  end
81
81
  end
82
82
 
@@ -1,12 +1,18 @@
1
1
  module Graphiti
2
2
  class Runner
3
3
  attr_reader :params
4
- include Graphiti::Base
4
+ attr_reader :deserialized_payload
5
5
 
6
6
  def initialize(resource_class, params, query = nil)
7
7
  @resource_class = resource_class
8
8
  @params = params
9
9
  @query = query
10
+
11
+ validator = RequestValidator.new(jsonapi_resource, params)
12
+
13
+ validator.validate!
14
+
15
+ @deserialized_payload = validator.deserialized_payload
10
16
  end
11
17
 
12
18
  def jsonapi_resource
@@ -22,5 +28,49 @@ module Graphiti
22
28
  def jsonapi_context
23
29
  Graphiti.context[:object]
24
30
  end
31
+
32
+ def query
33
+ @query ||= Query.new(jsonapi_resource, params)
34
+ end
35
+
36
+ def query_hash
37
+ @query_hash ||= query.hash
38
+ end
39
+
40
+ def wrap_context
41
+ Graphiti.with_context(jsonapi_context, action_name.to_sym) do
42
+ yield
43
+ end
44
+ end
45
+
46
+ def jsonapi_scope(scope, opts = {})
47
+ jsonapi_resource.build_scope(scope, query, opts)
48
+ end
49
+
50
+ def jsonapi_render_options
51
+ options = {}
52
+ options.merge!(default_jsonapi_render_options)
53
+ options[:meta] ||= {}
54
+ options[:expose] ||= {}
55
+ options[:expose][:context] = jsonapi_context
56
+ options
57
+ end
58
+
59
+ def proxy(base = nil, opts = {})
60
+ base ||= jsonapi_resource.base_scope
61
+ scope_opts = opts.slice :sideload_parent_length,
62
+ :default_paginate,
63
+ :after_resolve,
64
+ :sideload,
65
+ :parent,
66
+ :params
67
+ scope = jsonapi_scope(base, scope_opts)
68
+ ResourceProxy.new jsonapi_resource,
69
+ scope,
70
+ query,
71
+ payload: deserialized_payload,
72
+ single: opts[:single],
73
+ raise_on_missing: opts[:raise_on_missing]
74
+ end
25
75
  end
26
76
  end
@@ -39,6 +39,10 @@ module Graphiti
39
39
  def maybe_raise(opts = {})
40
40
  default = {request: request, exists: true}
41
41
  opts = default.merge(opts)
42
+ error_class = opts[:exists] ?
43
+ Graphiti::Errors::InvalidAttributeAccess :
44
+ Graphiti::Errors::UnknownAttribute
45
+
42
46
  if raise_error?(opts[:exists])
43
47
  raise error_class.new(resource, name, flag, opts)
44
48
  else
@@ -56,10 +60,6 @@ module Graphiti
56
60
  attribute[flag] != :required
57
61
  end
58
62
 
59
- def error_class
60
- Errors::AttributeError
61
- end
62
-
63
63
  def supported?
64
64
  attribute[flag] != false
65
65
  end
@@ -59,7 +59,7 @@ module Graphiti
59
59
 
60
60
  def params
61
61
  @params ||= {}.tap do |params|
62
- if @sideload.type != :belongs_to
62
+ if @sideload.type != :belongs_to || @sideload.remote?
63
63
  params[:filter] = @sideload.base_filter([@model])
64
64
  end
65
65
 
@@ -70,7 +70,7 @@ module Graphiti
70
70
  def path
71
71
  @path ||=
72
72
  path = @sideload.resource.endpoint[:url].to_s
73
- if @sideload.type == :belongs_to
73
+ if @sideload.type == :belongs_to && !@sideload.remote?
74
74
  path = "#{path}/#{@model.send(@sideload.foreign_key)}"
75
75
  end
76
76
  path
@@ -21,8 +21,6 @@ class Graphiti::Util::Persistence
21
21
  @resource = @resource.class.resource_for_type(meta_type).new
22
22
  end
23
23
  end
24
-
25
- typecast_attributes
26
24
  end
27
25
 
28
26
  # Perform the actual save logic.
@@ -71,20 +69,6 @@ class Graphiti::Util::Persistence
71
69
 
72
70
  private
73
71
 
74
- # In the case where we're sideposting in order to associate 2 nodes
75
- # in the graph, the foreign key gets merged into the child's attributes
76
- # This attribute should *not* need to be marked writable, as that
77
- # would allow writing as a straight attribute instead of just an association
78
- def typecast_attributes
79
- @attributes.each_pair do |key, value|
80
- @attributes[key] = if @foreign_key == key
81
- value
82
- else
83
- @resource.typecast(key, value, :writable)
84
- end
85
- end
86
- end
87
-
88
72
  def add_hook(prc, lifecycle_event)
89
73
  ::Graphiti::Util::TransactionHooksRecorder.add(prc, lifecycle_event)
90
74
  end
@@ -180,12 +164,8 @@ class Graphiti::Util::Persistence
180
164
  iterate(except: [:polymorphic_belongs_to, :belongs_to]) do |x|
181
165
  yield x
182
166
 
183
- if x[:sideload].writable?
184
- x[:object] = x[:resource]
185
- .persist_with_relationships(x[:meta], x[:attributes], x[:relationships], caller_model, x[:foreign_key])
186
- else
187
- raise Graphiti::Errors::UnwritableRelationship.new(@resource, x[:sideload])
188
- end
167
+ x[:object] = x[:resource]
168
+ .persist_with_relationships(x[:meta], x[:attributes], x[:relationships], caller_model, x[:foreign_key])
189
169
 
190
170
  processed << x
191
171
  end
@@ -195,12 +175,8 @@ class Graphiti::Util::Persistence
195
175
  def process_belongs_to(relationships)
196
176
  [].tap do |processed|
197
177
  iterate(only: [:polymorphic_belongs_to, :belongs_to]) do |x|
198
- if x[:sideload].writable?
199
- x[:object] = x[:resource]
200
- .persist_with_relationships(x[:meta], x[:attributes], x[:relationships])
201
- else
202
- raise Graphiti::Errors::UnwritableRelationship.new(@resource, x[:sideload])
203
- end
178
+ x[:object] = x[:resource]
179
+ .persist_with_relationships(x[:meta], x[:attributes], x[:relationships])
204
180
  processed << x
205
181
  end
206
182
  end
@@ -38,7 +38,8 @@ module Graphiti
38
38
  private
39
39
 
40
40
  def should_yield?(type)
41
- (@only.length > 0 && @only.include?(type)) ||
41
+ (@only.length == 0 && @except.length == 0) ||
42
+ (@only.length > 0 && @only.include?(type)) ||
42
43
  (@except.length > 0 && !@except.include?(type))
43
44
  end
44
45
 
@@ -84,7 +84,7 @@ module Graphiti
84
84
  begin
85
85
  type_ref[value] unless value.nil?
86
86
  rescue => e
87
- raise Errors::TypecastFailed.new(resource_ref, name_ref, value, e)
87
+ raise Errors::TypecastFailed.new(resource_ref, name_ref, value, e, type_ref)
88
88
  end
89
89
  }
90
90
  end
@@ -0,0 +1,87 @@
1
+ # A minimal implementation of an errors object similar to `ActiveModel::Errors`.
2
+ # Designed to support internal Graphiti classes like the `RequestValidator` so
3
+ # that there does not need to be a dependency on activemodel.
4
+ module Graphiti
5
+ module Util
6
+ class SimpleErrors
7
+ include Enumerable
8
+
9
+ attr_reader :messages, :details
10
+
11
+ def initialize(validation_target)
12
+ @target = validation_target
13
+ @messages = apply_default_array({})
14
+ @details = apply_default_array({})
15
+ @errors = apply_default_array({})
16
+ end
17
+
18
+ def clear
19
+ messages.clear
20
+ details.clear
21
+ end
22
+
23
+ def [](attribute)
24
+ messages[attribute.to_sym]
25
+ end
26
+
27
+ def each
28
+ messages.each_key do |attribute|
29
+ messages[attribute].each { |error| yield attribute, error }
30
+ end
31
+ end
32
+
33
+ def size
34
+ values.flatten.size
35
+ end
36
+ alias count size
37
+
38
+ def values
39
+ messages.values.reject(&:empty?)
40
+ end
41
+
42
+ def keys
43
+ messages.select { |key, value|
44
+ !value.empty?
45
+ }.keys
46
+ end
47
+
48
+ def empty?
49
+ size.zero?
50
+ end
51
+ alias blank? empty?
52
+
53
+ def add(attribute, code, message: nil)
54
+ message ||= "is #{code.to_s.humanize.downcase}"
55
+
56
+ details[attribute.to_sym] << {error: code}
57
+ messages[attribute.to_sym] << message
58
+ end
59
+
60
+ def added?(attribute, code)
61
+ details[attribute.to_sym].include?({error: code})
62
+ end
63
+
64
+ def full_messages
65
+ map { |attribute, message| full_message(attribute, message) }
66
+ end
67
+ alias to_a full_messages
68
+
69
+ def full_messages_for(attribute)
70
+ attribute = attribute.to_sym
71
+ messages[attribute].map { |message| full_message(attribute, message) }
72
+ end
73
+
74
+ def full_message(attribute, message)
75
+ return message if attribute == :base
76
+ "#{attribute} #{message}"
77
+ end
78
+
79
+ private
80
+
81
+ def apply_default_array(hash)
82
+ hash.default_proc = proc { |h, key| h[key] = [] }
83
+ hash
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,3 +1,3 @@
1
1
  module Graphiti
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiti
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Richmond
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-25 00:00:00.000000000 Z
11
+ date: 2019-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jsonapi-serializable
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.beta.1
47
+ version: 1.1.0
48
48
  type: :runtime
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: 1.0.beta.1
54
+ version: 1.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: concurrent-ruby
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -246,7 +246,6 @@ files:
246
246
  - lib/graphiti/adapters/active_record/many_to_many_sideload.rb
247
247
  - lib/graphiti/adapters/graphiti_api.rb
248
248
  - lib/graphiti/adapters/null.rb
249
- - lib/graphiti/base.rb
250
249
  - lib/graphiti/cli.rb
251
250
  - lib/graphiti/configuration.rb
252
251
  - lib/graphiti/context.rb
@@ -264,6 +263,7 @@ files:
264
263
  - lib/graphiti/rails.rb
265
264
  - lib/graphiti/railtie.rb
266
265
  - lib/graphiti/renderer.rb
266
+ - lib/graphiti/request_validator.rb
267
267
  - lib/graphiti/resource.rb
268
268
  - lib/graphiti/resource/configuration.rb
269
269
  - lib/graphiti/resource/documentation.rb
@@ -311,6 +311,7 @@ files:
311
311
  - lib/graphiti/util/serializer_attributes.rb
312
312
  - lib/graphiti/util/serializer_relationships.rb
313
313
  - lib/graphiti/util/sideload.rb
314
+ - lib/graphiti/util/simple_errors.rb
314
315
  - lib/graphiti/util/transaction_hooks_recorder.rb
315
316
  - lib/graphiti/util/validation_response.rb
316
317
  - lib/graphiti/version.rb
@@ -334,7 +335,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
334
335
  version: '0'
335
336
  requirements: []
336
337
  rubyforge_project:
337
- rubygems_version: 2.7.6
338
+ rubygems_version: 2.7.9
338
339
  signing_key:
339
340
  specification_version: 4
340
341
  summary: Easily build jsonapi.org-compatible APIs
data/lib/graphiti/base.rb DELETED
@@ -1,76 +0,0 @@
1
- module Graphiti
2
- module Base
3
- extend ActiveSupport::Concern
4
-
5
- def jsonapi_resource
6
- @jsonapi_resource
7
- end
8
-
9
- def query
10
- @query ||= Query.new(jsonapi_resource, params)
11
- end
12
-
13
- def query_hash
14
- @query_hash ||= query.hash
15
- end
16
-
17
- def wrap_context
18
- Graphiti.with_context(jsonapi_context, action_name.to_sym) do
19
- yield
20
- end
21
- end
22
-
23
- def jsonapi_context
24
- self
25
- end
26
-
27
- def jsonapi_scope(scope, opts = {})
28
- jsonapi_resource.build_scope(scope, query, opts)
29
- end
30
-
31
- def normalized_params
32
- normalized = params
33
- if normalized.respond_to?(:to_unsafe_h)
34
- normalized = normalized.to_unsafe_h.deep_symbolize_keys
35
- end
36
- normalized
37
- end
38
-
39
- def deserialized_params
40
- @deserialized_params ||= begin
41
- payload = normalized_params
42
- if payload[:data] && payload[:data][:type]
43
- Graphiti::Deserializer.new(payload)
44
- else
45
- Graphiti::Deserializer.new
46
- end
47
- end
48
- end
49
-
50
- def jsonapi_render_options
51
- options = {}
52
- options.merge!(default_jsonapi_render_options)
53
- options[:meta] ||= {}
54
- options[:expose] ||= {}
55
- options[:expose][:context] = jsonapi_context
56
- options
57
- end
58
-
59
- def proxy(base = nil, opts = {})
60
- base ||= jsonapi_resource.base_scope
61
- scope_opts = opts.slice :sideload_parent_length,
62
- :default_paginate,
63
- :after_resolve,
64
- :sideload,
65
- :parent,
66
- :params
67
- scope = jsonapi_scope(base, scope_opts)
68
- ResourceProxy.new jsonapi_resource,
69
- scope,
70
- query,
71
- payload: deserialized_params,
72
- single: opts[:single],
73
- raise_on_missing: opts[:raise_on_missing]
74
- end
75
- end
76
- end