graphiti 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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