graphiti 1.2.20 → 1.2.28
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/Gemfile +0 -2
- data/gemfiles/rails_4.gemfile +1 -1
- data/graphiti.gemspec +1 -0
- data/lib/graphiti/adapters/active_record.rb +1 -1
- data/lib/graphiti/adapters/active_record/belongs_to_sideload.rb +1 -1
- data/lib/graphiti/adapters/active_record/has_many_sideload.rb +1 -1
- data/lib/graphiti/adapters/active_record/has_one_sideload.rb +1 -1
- data/lib/graphiti/adapters/active_record/{inferrence.rb → inference.rb} +2 -2
- data/lib/graphiti/adapters/active_record/many_to_many_sideload.rb +20 -2
- data/lib/graphiti/debugger.rb +8 -4
- data/lib/graphiti/errors.rb +14 -0
- data/lib/graphiti/request_validator.rb +6 -6
- data/lib/graphiti/request_validators/validator.rb +7 -1
- data/lib/graphiti/resource/dsl.rb +1 -0
- data/lib/graphiti/resource/interface.rb +10 -0
- data/lib/graphiti/resource_proxy.rb +3 -1
- data/lib/graphiti/runner.rb +1 -2
- data/lib/graphiti/sideload.rb +3 -2
- data/lib/graphiti/version.rb +1 -1
- metadata +21 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 62001af4fe0f26688b07d4f9e0565b2f2cd1e875fa299c982ef5986e9db66836
|
|
4
|
+
data.tar.gz: 28ba11c786c4e7eb7be0612c2bd678434156e667110623046438d6e1a1c9b67d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5ed46d521816170aec5448ee816a5ea336faf791034c63c19a8bce64982d42ed9e19420b3d9e4f4782a78b20f8ba475636d920574b360d947991201eeb50bc8
|
|
7
|
+
data.tar.gz: f8578aa1f893d531146204cc43c142ddc58b4cc98a272e08c33ab13fd308530f04d4bdd273ef638ff88017f88051c44a9c76b0e1335a47c80ec9eee6b412d87b
|
data/Gemfile
CHANGED
data/gemfiles/rails_4.gemfile
CHANGED
data/graphiti.gemspec
CHANGED
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.add_development_dependency "kaminari", "~> 0.17"
|
|
30
30
|
spec.add_development_dependency "bundler"
|
|
31
31
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
32
|
+
spec.add_development_dependency "standard", "0.4.7"
|
|
32
33
|
spec.add_development_dependency "activemodel", ">= 4.1"
|
|
33
34
|
spec.add_development_dependency "graphiti_spec_helpers", "1.0.beta.4"
|
|
34
35
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Graphiti
|
|
2
2
|
module Adapters
|
|
3
3
|
class ActiveRecord < ::Graphiti::Adapters::Abstract
|
|
4
|
-
require "graphiti/adapters/active_record/
|
|
4
|
+
require "graphiti/adapters/active_record/inference"
|
|
5
5
|
require "graphiti/adapters/active_record/has_many_sideload"
|
|
6
6
|
require "graphiti/adapters/active_record/belongs_to_sideload"
|
|
7
7
|
require "graphiti/adapters/active_record/has_one_sideload"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module Graphiti::Adapters::ActiveRecord::
|
|
1
|
+
module Graphiti::Adapters::ActiveRecord::Inference
|
|
2
2
|
# If going AR to AR, use AR introspection
|
|
3
|
-
# If going AR to PORO, fall back to normal
|
|
3
|
+
# If going AR to PORO, fall back to normal inference
|
|
4
4
|
def infer_foreign_key
|
|
5
5
|
parent_model = parent_resource_class.model
|
|
6
6
|
reflection = parent_model.reflections[association_name.to_s]
|
|
@@ -8,6 +8,18 @@ class Graphiti::Adapters::ActiveRecord::ManyToManySideload < Graphiti::Sideload:
|
|
|
8
8
|
foreign_key.keys.first
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def inverse_filter
|
|
12
|
+
return @inverse_filter if @inverse_filter
|
|
13
|
+
|
|
14
|
+
inferred_name = infer_inverse_association
|
|
15
|
+
|
|
16
|
+
if inferred_name
|
|
17
|
+
"#{inferred_name.to_s.singularize}_id"
|
|
18
|
+
else
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
11
23
|
def belongs_to_many_filter(scope, value)
|
|
12
24
|
if polymorphic?
|
|
13
25
|
clauses = value.group_by { |v| v["type"] }.map { |group|
|
|
@@ -36,8 +48,7 @@ class Graphiti::Adapters::ActiveRecord::ManyToManySideload < Graphiti::Sideload:
|
|
|
36
48
|
|
|
37
49
|
def filter_for(scope, value, type = nil)
|
|
38
50
|
scope
|
|
39
|
-
.
|
|
40
|
-
.joins(through_relationship_name)
|
|
51
|
+
.includes(through_relationship_name)
|
|
41
52
|
.where(belongs_to_many_clause(value, type))
|
|
42
53
|
end
|
|
43
54
|
|
|
@@ -76,4 +87,11 @@ class Graphiti::Adapters::ActiveRecord::ManyToManySideload < Graphiti::Sideload:
|
|
|
76
87
|
value = through_reflection.foreign_key.to_sym
|
|
77
88
|
{key => value}
|
|
78
89
|
end
|
|
90
|
+
|
|
91
|
+
def infer_inverse_association
|
|
92
|
+
through_class = through_reflection.klass
|
|
93
|
+
|
|
94
|
+
foreign_reflection = through_class.reflections[name.to_s.singularize]
|
|
95
|
+
foreign_reflection && foreign_reflection.options[:inverse_of]
|
|
96
|
+
end
|
|
79
97
|
end
|
data/lib/graphiti/debugger.rb
CHANGED
|
@@ -10,6 +10,8 @@ module Graphiti
|
|
|
10
10
|
|
|
11
11
|
class << self
|
|
12
12
|
def on_data(name, start, stop, id, payload)
|
|
13
|
+
return [] unless enabled
|
|
14
|
+
|
|
13
15
|
took = ((stop - start) * 1000.0).round(2)
|
|
14
16
|
params = scrub_params(payload[:params])
|
|
15
17
|
|
|
@@ -24,7 +26,7 @@ module Graphiti
|
|
|
24
26
|
end
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
def on_data_exception(payload, params)
|
|
29
|
+
private def on_data_exception(payload, params)
|
|
28
30
|
unless payload[:exception_object].instance_variable_get(:@__graphiti_debug)
|
|
29
31
|
add_chunk do |logs, json|
|
|
30
32
|
logs << ["\n=== Graphiti Debug ERROR", :red, true]
|
|
@@ -49,11 +51,11 @@ module Graphiti
|
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
|
|
52
|
-
def results(raw_results)
|
|
54
|
+
private def results(raw_results)
|
|
53
55
|
raw_results.map { |r| "[#{r.class.name}, #{r.id.inspect}]" }.join(", ")
|
|
54
56
|
end
|
|
55
57
|
|
|
56
|
-
def on_sideload_data(payload, params, took)
|
|
58
|
+
private def on_sideload_data(payload, params, took)
|
|
57
59
|
sideload = payload[:sideload]
|
|
58
60
|
results = results(payload[:results])
|
|
59
61
|
add_chunk(payload[:resource], payload[:parent]) do |logs, json|
|
|
@@ -72,7 +74,7 @@ module Graphiti
|
|
|
72
74
|
end
|
|
73
75
|
end
|
|
74
76
|
|
|
75
|
-
def on_primary_data(payload, params, took)
|
|
77
|
+
private def on_primary_data(payload, params, took)
|
|
76
78
|
results = results(payload[:results])
|
|
77
79
|
add_chunk(payload[:resource], payload[:parent]) do |logs, json|
|
|
78
80
|
logs << [""]
|
|
@@ -90,6 +92,8 @@ module Graphiti
|
|
|
90
92
|
end
|
|
91
93
|
|
|
92
94
|
def on_render(name, start, stop, id, payload)
|
|
95
|
+
return [] unless enabled
|
|
96
|
+
|
|
93
97
|
add_chunk do |logs|
|
|
94
98
|
took = ((stop - start) * 1000.0).round(2)
|
|
95
99
|
logs << [""]
|
data/lib/graphiti/errors.rb
CHANGED
|
@@ -366,6 +366,20 @@ module Graphiti
|
|
|
366
366
|
end
|
|
367
367
|
end
|
|
368
368
|
|
|
369
|
+
class UndefinedIDLookup < Base
|
|
370
|
+
def initialize(resource_class)
|
|
371
|
+
@resource_class = resource_class
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def message
|
|
375
|
+
<<~MSG
|
|
376
|
+
Tried to resolve #{@resource_class} with an :id filter, but the filter was nil.
|
|
377
|
+
This can result in unscoping a query, which can cause incorrect values to be
|
|
378
|
+
returned which may or may not bypass standard access controls.
|
|
379
|
+
MSG
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
369
383
|
class UnknownAttribute < AttributeError
|
|
370
384
|
def message
|
|
371
385
|
"#{super}, but could not find an attribute with that name."
|
|
@@ -6,18 +6,18 @@ module Graphiti
|
|
|
6
6
|
:deserialized_payload,
|
|
7
7
|
to: :@validator
|
|
8
8
|
|
|
9
|
-
def initialize(root_resource, raw_params)
|
|
10
|
-
@validator = ValidatorFactory.create(root_resource, raw_params)
|
|
9
|
+
def initialize(root_resource, raw_params, action)
|
|
10
|
+
@validator = ValidatorFactory.create(root_resource, raw_params, action)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
class ValidatorFactory
|
|
14
|
-
def self.create(root_resource, raw_params)
|
|
15
|
-
case
|
|
16
|
-
when
|
|
14
|
+
def self.create(root_resource, raw_params, action)
|
|
15
|
+
case action
|
|
16
|
+
when :update then
|
|
17
17
|
RequestValidators::UpdateValidator
|
|
18
18
|
else
|
|
19
19
|
RequestValidators::Validator
|
|
20
|
-
end.new(root_resource, raw_params)
|
|
20
|
+
end.new(root_resource, raw_params, action)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -3,10 +3,11 @@ module Graphiti
|
|
|
3
3
|
class Validator
|
|
4
4
|
attr_reader :errors
|
|
5
5
|
|
|
6
|
-
def initialize(root_resource, raw_params)
|
|
6
|
+
def initialize(root_resource, raw_params, action)
|
|
7
7
|
@root_resource = root_resource
|
|
8
8
|
@raw_params = raw_params
|
|
9
9
|
@errors = Graphiti::Util::SimpleErrors.new(raw_params)
|
|
10
|
+
@action = action
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def validate
|
|
@@ -68,6 +69,11 @@ module Graphiti
|
|
|
68
69
|
|
|
69
70
|
def typecast_attributes(resource, attributes, payload_path)
|
|
70
71
|
attributes.each_pair do |key, value|
|
|
72
|
+
# Only validate id if create action, otherwise it's only used for lookup
|
|
73
|
+
next if @action != :create &&
|
|
74
|
+
key == :id &&
|
|
75
|
+
resource.class.config[:attributes][:id][:writable] == false
|
|
76
|
+
|
|
71
77
|
begin
|
|
72
78
|
attributes[key] = resource.typecast(key, value, :writable)
|
|
73
79
|
rescue Graphiti::Errors::UnknownAttribute
|
|
@@ -23,6 +23,9 @@ module Graphiti
|
|
|
23
23
|
|
|
24
24
|
# @api private
|
|
25
25
|
def _find(params = {}, base_scope = nil)
|
|
26
|
+
guard_nil_id!(params[:data])
|
|
27
|
+
guard_nil_id!(params)
|
|
28
|
+
|
|
26
29
|
id = params[:data].try(:[], :id) || params.delete(:id)
|
|
27
30
|
params[:filter] ||= {}
|
|
28
31
|
params[:filter][:id] = id if id
|
|
@@ -52,6 +55,13 @@ module Graphiti
|
|
|
52
55
|
end
|
|
53
56
|
end
|
|
54
57
|
end
|
|
58
|
+
|
|
59
|
+
def guard_nil_id!(params)
|
|
60
|
+
return unless params
|
|
61
|
+
if params.key?(:id) && params[:id].nil?
|
|
62
|
+
raise Errors::UndefinedIDLookup.new(self)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
55
65
|
end
|
|
56
66
|
end
|
|
57
67
|
end
|
|
@@ -93,7 +93,7 @@ module Graphiti
|
|
|
93
93
|
original = Graphiti.context[:namespace]
|
|
94
94
|
begin
|
|
95
95
|
Graphiti.context[:namespace] = action
|
|
96
|
-
::Graphiti::RequestValidator.new(@resource, @payload.params).validate!
|
|
96
|
+
::Graphiti::RequestValidator.new(@resource, @payload.params, action).validate!
|
|
97
97
|
validator = persist {
|
|
98
98
|
@resource.persist_with_relationships \
|
|
99
99
|
@payload.meta(action: action),
|
|
@@ -118,6 +118,7 @@ module Graphiti
|
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
def destroy
|
|
121
|
+
data
|
|
121
122
|
transaction_response = @resource.transaction do
|
|
122
123
|
metadata = {method: :destroy}
|
|
123
124
|
model = @resource.destroy(@query.filters[:id], metadata)
|
|
@@ -135,6 +136,7 @@ module Graphiti
|
|
|
135
136
|
end
|
|
136
137
|
|
|
137
138
|
def update_attributes
|
|
139
|
+
data
|
|
138
140
|
save(action: :update)
|
|
139
141
|
end
|
|
140
142
|
|
data/lib/graphiti/runner.rb
CHANGED
|
@@ -9,8 +9,7 @@ module Graphiti
|
|
|
9
9
|
@query = query
|
|
10
10
|
@action = action
|
|
11
11
|
|
|
12
|
-
validator = RequestValidator.new(jsonapi_resource, params)
|
|
13
|
-
|
|
12
|
+
validator = RequestValidator.new(jsonapi_resource, params, action)
|
|
14
13
|
validator.validate!
|
|
15
14
|
|
|
16
15
|
@deserialized_payload = validator.deserialized_payload
|
data/lib/graphiti/sideload.rb
CHANGED
|
@@ -26,8 +26,8 @@ module Graphiti
|
|
|
26
26
|
@foreign_key = opts[:foreign_key]
|
|
27
27
|
@type = opts[:type]
|
|
28
28
|
@base_scope = opts[:base_scope]
|
|
29
|
-
@readable =
|
|
30
|
-
@writable =
|
|
29
|
+
@readable = opts[:readable]
|
|
30
|
+
@writable = opts[:writable]
|
|
31
31
|
@as = opts[:as]
|
|
32
32
|
@link = opts[:link]
|
|
33
33
|
@single = opts[:single]
|
|
@@ -426,6 +426,7 @@ module Graphiti
|
|
|
426
426
|
Util::Class.namespace_for(klass)
|
|
427
427
|
end
|
|
428
428
|
|
|
429
|
+
# TODO: call this at runtime to support procs
|
|
429
430
|
def evaluate_flag(flag)
|
|
430
431
|
return false if flag.blank?
|
|
431
432
|
|
data/lib/graphiti/version.rb
CHANGED
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.2.
|
|
4
|
+
version: 1.2.28
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lee Richmond
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jsonapi-serializable
|
|
@@ -162,6 +162,20 @@ dependencies:
|
|
|
162
162
|
- - "~>"
|
|
163
163
|
- !ruby/object:Gem::Version
|
|
164
164
|
version: '10.0'
|
|
165
|
+
- !ruby/object:Gem::Dependency
|
|
166
|
+
name: standard
|
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
|
168
|
+
requirements:
|
|
169
|
+
- - '='
|
|
170
|
+
- !ruby/object:Gem::Version
|
|
171
|
+
version: 0.4.7
|
|
172
|
+
type: :development
|
|
173
|
+
prerelease: false
|
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
175
|
+
requirements:
|
|
176
|
+
- - '='
|
|
177
|
+
- !ruby/object:Gem::Version
|
|
178
|
+
version: 0.4.7
|
|
165
179
|
- !ruby/object:Gem::Dependency
|
|
166
180
|
name: activemodel
|
|
167
181
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -190,7 +204,7 @@ dependencies:
|
|
|
190
204
|
- - '='
|
|
191
205
|
- !ruby/object:Gem::Version
|
|
192
206
|
version: 1.0.beta.4
|
|
193
|
-
description:
|
|
207
|
+
description:
|
|
194
208
|
email:
|
|
195
209
|
- richmolj@gmail.com
|
|
196
210
|
executables:
|
|
@@ -248,7 +262,7 @@ files:
|
|
|
248
262
|
- lib/graphiti/adapters/active_record/belongs_to_sideload.rb
|
|
249
263
|
- lib/graphiti/adapters/active_record/has_many_sideload.rb
|
|
250
264
|
- lib/graphiti/adapters/active_record/has_one_sideload.rb
|
|
251
|
-
- lib/graphiti/adapters/active_record/
|
|
265
|
+
- lib/graphiti/adapters/active_record/inference.rb
|
|
252
266
|
- lib/graphiti/adapters/active_record/many_to_many_sideload.rb
|
|
253
267
|
- lib/graphiti/adapters/graphiti_api.rb
|
|
254
268
|
- lib/graphiti/adapters/null.rb
|
|
@@ -327,7 +341,7 @@ homepage: https://github.com/graphiti-api/graphiti
|
|
|
327
341
|
licenses:
|
|
328
342
|
- MIT
|
|
329
343
|
metadata: {}
|
|
330
|
-
post_install_message:
|
|
344
|
+
post_install_message:
|
|
331
345
|
rdoc_options: []
|
|
332
346
|
require_paths:
|
|
333
347
|
- lib
|
|
@@ -343,7 +357,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
343
357
|
version: '0'
|
|
344
358
|
requirements: []
|
|
345
359
|
rubygems_version: 3.0.6
|
|
346
|
-
signing_key:
|
|
360
|
+
signing_key:
|
|
347
361
|
specification_version: 4
|
|
348
362
|
summary: Easily build jsonapi.org-compatible APIs
|
|
349
363
|
test_files: []
|