graphiti 1.2.31 → 1.2.32
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/CHANGELOG.md +1 -0
- data/deprecated_generators/graphiti/generator_mixin.rb +1 -0
- data/lib/graphiti/adapters/graphiti_api.rb +1 -1
- data/lib/graphiti/adapters/persistence/associations.rb +10 -2
- data/lib/graphiti/configuration.rb +3 -1
- data/lib/graphiti/delegates/pagination.rb +1 -0
- data/lib/graphiti/errors.rb +26 -0
- data/lib/graphiti/hash_renderer.rb +121 -14
- data/lib/graphiti/query.rb +12 -1
- data/lib/graphiti/renderer.rb +18 -1
- data/lib/graphiti/resource/configuration.rb +4 -1
- data/lib/graphiti/resource/interface.rb +1 -1
- data/lib/graphiti/resource/polymorphism.rb +6 -1
- data/lib/graphiti/resource/remote.rb +1 -1
- data/lib/graphiti/resource_proxy.rb +12 -0
- data/lib/graphiti/schema.rb +8 -2
- data/lib/graphiti/serializer.rb +23 -6
- data/lib/graphiti/sideload.rb +3 -1
- data/lib/graphiti/util/class.rb +6 -0
- data/lib/graphiti/util/remote_params.rb +9 -4
- data/lib/graphiti/util/remote_serializer.rb +1 -0
- data/lib/graphiti/util/serializer_attributes.rb +21 -6
- data/lib/graphiti/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ec84a0ed1957831fa1ae6bec24a6470d5bb16189681e096b5d59a468b95b49a
|
4
|
+
data.tar.gz: 145633f22cad8f867ce295337a0b3bc5adfc45da6695b481abb092d0f7b17ed8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a841e2eceebba1e495608ec2037a1c7deffa408fc7e408756a6edbfed0cfaded42d82abf55899724ec201a427a6f8226bbe554142739ff1067133d9d499835bd
|
7
|
+
data.tar.gz: 3e6b741c6942c8b5ae89b08c7d5fdc6eb71b4c1b82794788207813bc914f0f245c43f196d603e2478c7dba61145403c507e1d7937028f8e217e71144beb2c128
|
data/CHANGELOG.md
CHANGED
@@ -34,7 +34,7 @@ module Graphiti
|
|
34
34
|
|
35
35
|
def build_url(scope)
|
36
36
|
url = resource.remote_url
|
37
|
-
params = scope[:params].merge(scope.except(:params))
|
37
|
+
params = scope[:params].merge(scope.except(:params, :foreign_key))
|
38
38
|
params[:page] ||= {}
|
39
39
|
params[:page][:size] ||= 999
|
40
40
|
params = CGI.unescape(params.to_query)
|
@@ -11,8 +11,16 @@ module Graphiti
|
|
11
11
|
.persist_with_relationships(x[:meta], x[:attributes], x[:relationships])
|
12
12
|
processed << x
|
13
13
|
rescue Graphiti::Errors::RecordNotFound
|
14
|
-
|
15
|
-
|
14
|
+
if Graphiti.config.raise_on_missing_sidepost
|
15
|
+
path = "relationships/#{x.dig(:meta, :jsonapi_type)}"
|
16
|
+
raise Graphiti::Errors::RecordNotFound.new(x[:sideload].name, id, path)
|
17
|
+
else
|
18
|
+
pointer = "data/relationships/#{x.dig(:meta, :jsonapi_type)}"
|
19
|
+
object = Graphiti::Errors::NullRelation.new(id.to_s, pointer)
|
20
|
+
object.errors.add(:base, :not_found, message: "could not be found")
|
21
|
+
x[:object] = object
|
22
|
+
processed << x
|
23
|
+
end
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
@@ -14,6 +14,7 @@ module Graphiti
|
|
14
14
|
attr_accessor :pagination_links_on_demand
|
15
15
|
attr_accessor :pagination_links
|
16
16
|
attr_accessor :typecast_reads
|
17
|
+
attr_accessor :raise_on_missing_sidepost
|
17
18
|
|
18
19
|
attr_reader :debug, :debug_models
|
19
20
|
|
@@ -29,6 +30,7 @@ module Graphiti
|
|
29
30
|
@pagination_links_on_demand = false
|
30
31
|
@pagination_links = false
|
31
32
|
@typecast_reads = true
|
33
|
+
@raise_on_missing_sidepost = true
|
32
34
|
self.debug = ENV.fetch("GRAPHITI_DEBUG", true)
|
33
35
|
self.debug_models = ENV.fetch("GRAPHITI_DEBUG_MODELS", false)
|
34
36
|
|
@@ -43,7 +45,7 @@ module Graphiti
|
|
43
45
|
end
|
44
46
|
|
45
47
|
if (logger = ::Rails.logger)
|
46
|
-
self.debug = logger.
|
48
|
+
self.debug = logger.debug? && debug
|
47
49
|
Graphiti.logger = logger
|
48
50
|
end
|
49
51
|
end
|
@@ -11,6 +11,7 @@ module Graphiti
|
|
11
11
|
|
12
12
|
def links
|
13
13
|
@links ||= {}.tap do |links|
|
14
|
+
links[:self] = pagination_link(current_page)
|
14
15
|
links[:first] = pagination_link(1)
|
15
16
|
links[:last] = pagination_link(last_page)
|
16
17
|
links[:prev] = pagination_link(current_page - 1) unless current_page == 1
|
data/lib/graphiti/errors.rb
CHANGED
@@ -2,6 +2,32 @@ module Graphiti
|
|
2
2
|
module Errors
|
3
3
|
class Base < StandardError; end
|
4
4
|
|
5
|
+
class UnreadableAttribute < Base
|
6
|
+
def initialize(resource_class, name)
|
7
|
+
@resource_class = resource_class
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def message
|
12
|
+
"#{@resource_class}: Requested field #{@name}, but not authorized to read it"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class NullRelation
|
17
|
+
extend ActiveModel::Naming
|
18
|
+
attr_accessor :id, :errors, :pointer
|
19
|
+
|
20
|
+
def initialize(id, pointer)
|
21
|
+
@id = id
|
22
|
+
@pointer = pointer
|
23
|
+
@errors = ActiveModel::Errors.new(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.human_attribute_name(attr, options = {})
|
27
|
+
attr
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
5
31
|
class AdapterNotImplemented < Base
|
6
32
|
def initialize(adapter, attribute, method)
|
7
33
|
@adapter = adapter
|
@@ -1,39 +1,138 @@
|
|
1
1
|
module Graphiti
|
2
2
|
module SerializableHash
|
3
|
-
def to_hash(fields: nil, include: {})
|
3
|
+
def to_hash(fields: nil, include: {}, name_chain: [], graphql: false)
|
4
4
|
{}.tap do |hash|
|
5
|
-
|
5
|
+
if fields
|
6
|
+
fields_list = nil
|
7
|
+
|
8
|
+
# Dot syntax wins over jsonapi type
|
9
|
+
if name_chain.length > 0
|
10
|
+
fields_list = fields[name_chain.join(".").to_sym]
|
11
|
+
end
|
12
|
+
|
13
|
+
if fields_list.nil?
|
14
|
+
fields_list = fields[jsonapi_type]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# polymorphic resources - merge the PARENT type
|
19
|
+
if polymorphic_subclass?
|
20
|
+
if fields[@resource.type]
|
21
|
+
fields_list ||= []
|
22
|
+
fields_list |= fields[@resource.type]
|
23
|
+
end
|
24
|
+
|
25
|
+
if fields[jsonapi_type]
|
26
|
+
fields_list ||= []
|
27
|
+
fields_list |= fields[jsonapi_type]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
6
31
|
attrs = requested_attributes(fields_list).each_with_object({}) { |(k, v), h|
|
7
|
-
|
32
|
+
name = graphql ? k.to_s.camelize(:lower).to_sym : k
|
33
|
+
h[name] = instance_eval(&v)
|
8
34
|
}
|
9
|
-
|
35
|
+
|
36
|
+
# The main logic here is just !!include[k]
|
37
|
+
# But we also have special on__<type>--<name> includes
|
38
|
+
# Where we only include when matching the polymorphic type
|
39
|
+
rels = @_relationships.select { |k, v|
|
40
|
+
if include[k]
|
41
|
+
true
|
42
|
+
else
|
43
|
+
included = false
|
44
|
+
include.keys.each do |key|
|
45
|
+
split = key.to_s.split(/^on__/)
|
46
|
+
if split.length > 1
|
47
|
+
requested_type, key = split[1].split("--")
|
48
|
+
if requested_type.to_sym == jsonapi_type
|
49
|
+
included = k == key.to_sym
|
50
|
+
break
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
included
|
55
|
+
end
|
56
|
+
}
|
57
|
+
|
10
58
|
rels.each_with_object({}) do |(k, v), h|
|
59
|
+
nested_include = include[k]
|
60
|
+
|
61
|
+
# This logic only fires if it's a special on__<type>--<name> include
|
62
|
+
unless include.has_key?(k)
|
63
|
+
include.keys.each do |include_key|
|
64
|
+
if k == include_key.to_s.split("--")[1].to_sym
|
65
|
+
nested_include = include[include_key]
|
66
|
+
break
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
11
71
|
serializers = v.send(:resources)
|
12
|
-
|
13
|
-
|
14
|
-
|
72
|
+
name = graphql ? k.to_s.camelize(:lower) : k
|
73
|
+
name_chain = name_chain.dup
|
74
|
+
name_chain << k unless name_chain.last == k
|
75
|
+
|
76
|
+
unless remote_resource? && serializers.nil?
|
77
|
+
attrs[name.to_sym] = if serializers.is_a?(Array)
|
78
|
+
serializers.map do |rr|
|
79
|
+
rr.to_hash(fields: fields, include: nested_include, graphql: graphql, name_chain: name_chain)
|
80
|
+
end
|
81
|
+
elsif serializers.nil?
|
82
|
+
if @resource.class.respond_to?(:sideload)
|
83
|
+
if @resource.class.sideload(k).type.to_s.include?("_many")
|
84
|
+
[]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
serializers.to_hash(fields: fields, include: nested_include, graphql: graphql, name_chain: name_chain)
|
15
89
|
end
|
16
|
-
elsif serializers.nil?
|
17
|
-
nil
|
18
|
-
else
|
19
|
-
serializers.to_hash(fields: fields, include: include[k])
|
20
90
|
end
|
21
91
|
end
|
22
92
|
|
23
|
-
|
93
|
+
if !graphql || (fields_list || []).include?(:id)
|
94
|
+
hash[:id] = jsonapi_id
|
95
|
+
end
|
96
|
+
|
97
|
+
if (fields_list || []).include?(:_type)
|
98
|
+
hash[:_type] = jsonapi_type.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
if (fields_list || []).include?(:__typename)
|
102
|
+
resource_class = @resource.class
|
103
|
+
if polymorphic_subclass?
|
104
|
+
resource_class = @resource.class.resource_for_type(jsonapi_type)
|
105
|
+
end
|
106
|
+
hash[:__typename] = ::Graphiti::Util::Class
|
107
|
+
.graphql_type_name(resource_class.name)
|
108
|
+
end
|
109
|
+
|
24
110
|
hash.merge!(attrs) if attrs.any?
|
25
111
|
end
|
26
112
|
end
|
113
|
+
|
114
|
+
def polymorphic_subclass?
|
115
|
+
!remote_resource? &&
|
116
|
+
@resource.polymorphic? &&
|
117
|
+
@resource.type != jsonapi_type
|
118
|
+
end
|
119
|
+
|
120
|
+
# See hack in util/remote_serializer.rb
|
121
|
+
def remote_resource?
|
122
|
+
@resource == 1
|
123
|
+
end
|
27
124
|
end
|
28
125
|
|
29
126
|
class HashRenderer
|
30
|
-
def initialize(resource)
|
127
|
+
def initialize(resource, graphql: false)
|
31
128
|
@resource = resource
|
129
|
+
@graphql = graphql
|
32
130
|
end
|
33
131
|
|
34
132
|
def render(options)
|
35
133
|
serializers = options[:data]
|
36
134
|
opts = options.slice(:fields, :include)
|
135
|
+
opts[:graphql] = @graphql
|
37
136
|
to_hash(serializers, opts).tap do |hash|
|
38
137
|
hash.merge!(options.slice(:meta)) unless options[:meta].empty?
|
39
138
|
end
|
@@ -43,7 +142,15 @@ module Graphiti
|
|
43
142
|
|
44
143
|
def to_hash(serializers, opts)
|
45
144
|
{}.tap do |hash|
|
46
|
-
|
145
|
+
top_level_key = :data
|
146
|
+
if @graphql
|
147
|
+
top_level_key = @resource.graphql_entrypoint
|
148
|
+
unless serializers.is_a?(Array)
|
149
|
+
top_level_key = top_level_key.to_s.singularize.to_sym
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
hash[top_level_key] = if serializers.is_a?(Array)
|
47
154
|
serializers.map do |s|
|
48
155
|
s.to_hash(**opts)
|
49
156
|
end
|
data/lib/graphiti/query.rb
CHANGED
@@ -96,7 +96,18 @@ module Graphiti
|
|
96
96
|
sl_resource = resource_for_sideload(sideload)
|
97
97
|
query_parents = parents + [self]
|
98
98
|
sub_hash = sub_hash[:include] if sub_hash.key?(:include)
|
99
|
-
|
99
|
+
|
100
|
+
# NB: To handle on__<type>--<name>
|
101
|
+
# A) relationship_name == :positions
|
102
|
+
# B) key == on__employees.positions
|
103
|
+
# This way A) ensures sideloads are resolved
|
104
|
+
# And B) ensures nested filters, sorts etc still work
|
105
|
+
relationship_name = sideload ? sideload.name : key
|
106
|
+
hash[relationship_name] = Query.new sl_resource,
|
107
|
+
@params,
|
108
|
+
key,
|
109
|
+
sub_hash,
|
110
|
+
query_parents, :all
|
100
111
|
else
|
101
112
|
handle_missing_sideload(key)
|
102
113
|
end
|
data/lib/graphiti/renderer.rb
CHANGED
@@ -17,8 +17,20 @@ module Graphiti
|
|
17
17
|
render(self.class.jsonapi_renderer).to_json
|
18
18
|
end
|
19
19
|
|
20
|
+
def as_graphql
|
21
|
+
render(self.class.graphql_renderer(@proxy))
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_graphql
|
25
|
+
as_graphql.to_json
|
26
|
+
end
|
27
|
+
|
20
28
|
def to_json
|
21
|
-
|
29
|
+
as_json.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
def as_json
|
33
|
+
render(self.class.hash_renderer(@proxy))
|
22
34
|
end
|
23
35
|
|
24
36
|
def to_xml
|
@@ -35,6 +47,11 @@ module Graphiti
|
|
35
47
|
JSONAPI::Serializable::Renderer.new(implementation)
|
36
48
|
end
|
37
49
|
|
50
|
+
def self.graphql_renderer(proxy)
|
51
|
+
implementation = Graphiti::HashRenderer.new(proxy.resource, graphql: true)
|
52
|
+
JSONAPI::Serializable::Renderer.new(implementation)
|
53
|
+
end
|
54
|
+
|
38
55
|
private
|
39
56
|
|
40
57
|
def render(renderer)
|
@@ -83,7 +83,8 @@ module Graphiti
|
|
83
83
|
:relationships_readable_by_default,
|
84
84
|
:relationships_writable_by_default,
|
85
85
|
:filters_accept_nil_by_default,
|
86
|
-
:filters_deny_empty_by_default
|
86
|
+
:filters_deny_empty_by_default,
|
87
|
+
:graphql_entrypoint
|
87
88
|
|
88
89
|
class << self
|
89
90
|
prepend Overrides
|
@@ -97,6 +98,7 @@ module Graphiti
|
|
97
98
|
# re-assigning causes a new Class.new
|
98
99
|
klass.serializer = (klass.serializer || klass.infer_serializer_superclass)
|
99
100
|
klass.type ||= klass.infer_type
|
101
|
+
klass.graphql_entrypoint = klass.type.to_s.pluralize.to_sym
|
100
102
|
default(klass, :attributes_readable_by_default, true)
|
101
103
|
default(klass, :attributes_writable_by_default, true)
|
102
104
|
default(klass, :attributes_sortable_by_default, true)
|
@@ -144,6 +146,7 @@ module Graphiti
|
|
144
146
|
if (@abstract_class = val)
|
145
147
|
self.serializer = nil
|
146
148
|
self.type = nil
|
149
|
+
self.graphql_entrypoint = nil
|
147
150
|
end
|
148
151
|
end
|
149
152
|
|
@@ -42,9 +42,14 @@ module Graphiti
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def sideload(name)
|
45
|
-
|
45
|
+
if (split_on = name.to_s.split(/^on__/)).length > 1
|
46
|
+
on_type, name = split_on[1].split("--").map(&:to_sym)
|
47
|
+
end
|
48
|
+
|
49
|
+
sl = super(name)
|
46
50
|
if !polymorphic_child? && sl.nil?
|
47
51
|
children.each do |c|
|
52
|
+
next if on_type && c.type != on_type
|
48
53
|
break if (sl = c.sideloads[name])
|
49
54
|
end
|
50
55
|
end
|
@@ -47,10 +47,22 @@ module Graphiti
|
|
47
47
|
Renderer.new(self, options).to_json
|
48
48
|
end
|
49
49
|
|
50
|
+
def as_json(options = {})
|
51
|
+
Renderer.new(self, options).as_json
|
52
|
+
end
|
53
|
+
|
50
54
|
def to_xml(options = {})
|
51
55
|
Renderer.new(self, options).to_xml
|
52
56
|
end
|
53
57
|
|
58
|
+
def to_graphql(options = {})
|
59
|
+
Renderer.new(self, options).to_graphql
|
60
|
+
end
|
61
|
+
|
62
|
+
def as_graphql(options = {})
|
63
|
+
Renderer.new(self, options).as_graphql
|
64
|
+
end
|
65
|
+
|
54
66
|
def data
|
55
67
|
@data ||= begin
|
56
68
|
records = @scope.resolve
|
data/lib/graphiti/schema.rb
CHANGED
@@ -7,6 +7,7 @@ module Graphiti
|
|
7
7
|
::Rails.application.eager_load! if defined?(::Rails)
|
8
8
|
resources ||= Graphiti.resources.reject(&:abstract_class?)
|
9
9
|
resources.reject! { |r| r.name.nil? }
|
10
|
+
|
10
11
|
new(resources).generate
|
11
12
|
end
|
12
13
|
|
@@ -25,7 +26,7 @@ module Graphiti
|
|
25
26
|
|
26
27
|
def initialize(resources)
|
27
28
|
@resources = resources.sort_by(&:name)
|
28
|
-
@remote_resources = resources.select(&:remote?)
|
29
|
+
@remote_resources = @resources.select(&:remote?)
|
29
30
|
@local_resources = @resources - @remote_resources
|
30
31
|
end
|
31
32
|
|
@@ -89,6 +90,7 @@ module Graphiti
|
|
89
90
|
config = {
|
90
91
|
name: r.name,
|
91
92
|
type: r.type.to_s,
|
93
|
+
graphql_entrypoint: r.graphql_entrypoint.to_s,
|
92
94
|
description: r.description,
|
93
95
|
attributes: attributes(r),
|
94
96
|
extra_attributes: extra_attributes(r),
|
@@ -108,7 +110,7 @@ module Graphiti
|
|
108
110
|
config[:default_page_size] = r.default_page_size
|
109
111
|
end
|
110
112
|
|
111
|
-
if r.polymorphic?
|
113
|
+
if r.polymorphic? && !r.polymorphic_child?
|
112
114
|
config[:polymorphic] = true
|
113
115
|
config[:children] = r.children.map(&:name)
|
114
116
|
end
|
@@ -202,6 +204,9 @@ module Graphiti
|
|
202
204
|
config[:guard] = true
|
203
205
|
end
|
204
206
|
end
|
207
|
+
if filter[:required] # one-off filter, not attribute
|
208
|
+
config[:required] = true
|
209
|
+
end
|
205
210
|
f[name] = config
|
206
211
|
end
|
207
212
|
end
|
@@ -214,6 +219,7 @@ module Graphiti
|
|
214
219
|
if config.type == :polymorphic_belongs_to
|
215
220
|
schema[:resources] = config.children.values
|
216
221
|
.map(&:resource).map(&:class).map(&:name)
|
222
|
+
schema[:parent_resource] = config.parent_resource.class.name
|
217
223
|
else
|
218
224
|
schema[:resource] = config.resource.class.name
|
219
225
|
end
|
data/lib/graphiti/serializer.rb
CHANGED
@@ -12,13 +12,36 @@ module Graphiti
|
|
12
12
|
# go through type checking/coercion
|
13
13
|
class_attribute :attributes_applied_via_resource
|
14
14
|
class_attribute :extra_attributes_applied_via_resource
|
15
|
+
class_attribute :relationship_condition_blocks
|
15
16
|
self.attributes_applied_via_resource = []
|
16
17
|
self.extra_attributes_applied_via_resource = []
|
18
|
+
# See #requested_relationships
|
19
|
+
self.relationship_condition_blocks ||= {}
|
17
20
|
|
18
21
|
def self.inherited(klass)
|
19
22
|
super
|
20
23
|
klass.class_eval do
|
21
24
|
extend JSONAPI::Serializable::Resource::ConditionalFields
|
25
|
+
|
26
|
+
# See #requested_relationships
|
27
|
+
def self.relationship(name, options = {}, &block)
|
28
|
+
super
|
29
|
+
field_condition_blocks.delete(name)
|
30
|
+
_register_condition(relationship_condition_blocks, name, options)
|
31
|
+
end
|
32
|
+
|
33
|
+
# NB - avoid clobbering includes when sparse fieldset
|
34
|
+
# https://github.com/jsonapi-rb/jsonapi-serializable/pull/102
|
35
|
+
#
|
36
|
+
# We also override this method to ensure attributes and relationships
|
37
|
+
# have separate condition blocks. This way an attribute and
|
38
|
+
# relationship can have the same name, and the attribute can be
|
39
|
+
# conditional without affecting the relationship.
|
40
|
+
def requested_relationships(fields)
|
41
|
+
@_relationships.select do |k, _|
|
42
|
+
_conditionally_included?(self.class.relationship_condition_blocks, k)
|
43
|
+
end
|
44
|
+
end
|
22
45
|
end
|
23
46
|
end
|
24
47
|
|
@@ -29,12 +52,6 @@ module Graphiti
|
|
29
52
|
end
|
30
53
|
end
|
31
54
|
|
32
|
-
# Temporary fix until fixed upstream
|
33
|
-
# https://github.com/jsonapi-rb/jsonapi-serializable/pull/102
|
34
|
-
def requested_relationships(fields)
|
35
|
-
@_relationships
|
36
|
-
end
|
37
|
-
|
38
55
|
# Allow access to resource methods
|
39
56
|
def method_missing(id, *args, &blk)
|
40
57
|
if @resource.respond_to?(id, true)
|
data/lib/graphiti/sideload.rb
CHANGED
@@ -209,7 +209,9 @@ module Graphiti
|
|
209
209
|
end
|
210
210
|
|
211
211
|
with_error_handling(Errors::SideloadQueryBuildingError) do
|
212
|
-
|
212
|
+
scope = base_scope
|
213
|
+
scope[:foreign_key] = foreign_key if remote?
|
214
|
+
proxy = resource.class._all(params, opts, scope)
|
213
215
|
pre_load_proc&.call(proxy, parents)
|
214
216
|
end
|
215
217
|
|
data/lib/graphiti/util/class.rb
CHANGED
@@ -20,6 +20,12 @@ module Graphiti
|
|
20
20
|
split = namespace.split("::")
|
21
21
|
split[0, split.length - 1].join("::")
|
22
22
|
end
|
23
|
+
|
24
|
+
def self.graphql_type_name(name)
|
25
|
+
name.gsub("Resource", "")
|
26
|
+
.gsub("::", "") # remove modules
|
27
|
+
.gsub(".", "__") # remove remote resource .
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
@@ -2,13 +2,14 @@
|
|
2
2
|
module Graphiti
|
3
3
|
module Util
|
4
4
|
class RemoteParams
|
5
|
-
def self.generate(resource, query)
|
6
|
-
new(resource, query).generate
|
5
|
+
def self.generate(resource, query, foreign_key)
|
6
|
+
new(resource, query, foreign_key).generate
|
7
7
|
end
|
8
8
|
|
9
|
-
def initialize(resource, query)
|
9
|
+
def initialize(resource, query, foreign_key)
|
10
10
|
@resource = resource
|
11
11
|
@query = query
|
12
|
+
@foreign_key = foreign_key
|
12
13
|
@sorts = []
|
13
14
|
@filters = {}
|
14
15
|
@fields = {}
|
@@ -97,7 +98,11 @@ module Graphiti
|
|
97
98
|
return unless fields
|
98
99
|
|
99
100
|
fields.each_pair do |type, attrs|
|
100
|
-
|
101
|
+
all_attrs = attrs
|
102
|
+
if @foreign_key
|
103
|
+
all_attrs |= [@foreign_key]
|
104
|
+
end
|
105
|
+
@fields[type] = all_attrs.join(",")
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
@@ -44,6 +44,7 @@ module Graphiti
|
|
44
44
|
model.delete_field(:_relationships)
|
45
45
|
# If this isn't set, Array(resources) will return []
|
46
46
|
# This is important, because jsonapi-serializable makes this call
|
47
|
+
# To see the test failure, remote resource position > department
|
47
48
|
model.instance_variable_set(:@__graphiti_resource, 1)
|
48
49
|
model.instance_variable_set(:@__graphiti_serializer, serializer)
|
49
50
|
end
|
@@ -12,18 +12,20 @@ module Graphiti
|
|
12
12
|
def apply
|
13
13
|
return unless readable?
|
14
14
|
|
15
|
+
remove_guard if previously_guarded?
|
16
|
+
|
15
17
|
if @name == :id
|
16
18
|
@serializer.id(&proc)
|
17
19
|
elsif @attr[:proc]
|
18
20
|
@serializer.send(_method, @name, serializer_options, &proc)
|
19
21
|
elsif @serializer.attribute_blocks[@name].nil?
|
20
22
|
@serializer.send(_method, @name, serializer_options, &proc)
|
23
|
+
elsif @serializer.send(applied_method).include?(@name)
|
24
|
+
@serializer.field_condition_blocks[@name] = guard if guard?
|
21
25
|
else
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@serializer.send(_method, @name, serializer_options, &wrapped)
|
26
|
-
end
|
26
|
+
inner = @serializer.attribute_blocks.delete(@name)
|
27
|
+
wrapped = wrap_proc(inner)
|
28
|
+
@serializer.send(_method, @name, serializer_options, &wrapped)
|
27
29
|
end
|
28
30
|
|
29
31
|
existing = @serializer.send(applied_method)
|
@@ -32,6 +34,14 @@ module Graphiti
|
|
32
34
|
|
33
35
|
private
|
34
36
|
|
37
|
+
def previously_guarded?
|
38
|
+
@serializer.field_condition_blocks[@name]
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_guard
|
42
|
+
@serializer.field_condition_blocks.delete(@name)
|
43
|
+
end
|
44
|
+
|
35
45
|
def applied_method
|
36
46
|
if extra?
|
37
47
|
:extra_attributes_applied_via_resource
|
@@ -56,16 +66,21 @@ module Graphiti
|
|
56
66
|
method_name = @attr[:readable]
|
57
67
|
instance = @resource.new
|
58
68
|
attribute = @name.to_s
|
69
|
+
resource_class = @resource
|
59
70
|
|
60
71
|
-> {
|
61
72
|
method = instance.method(method_name)
|
62
|
-
if method.arity.zero?
|
73
|
+
result = if method.arity.zero?
|
63
74
|
instance.instance_eval(&method_name)
|
64
75
|
elsif method.arity == 1
|
65
76
|
instance.instance_exec(@object, &method)
|
66
77
|
else
|
67
78
|
instance.instance_exec(@object, attribute, &method)
|
68
79
|
end
|
80
|
+
if Graphiti.context[:graphql] && !result
|
81
|
+
raise ::Graphiti::Errors::UnreadableAttribute.new(resource_class, attribute)
|
82
|
+
end
|
83
|
+
result
|
69
84
|
}
|
70
85
|
end
|
71
86
|
|
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.32
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Richmond
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jsonapi-serializable
|