graphiti_gql 0.2.4 → 0.2.7
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/.github/probots.yml +2 -0
- data/lib/graphiti_gql/active_resource.rb +66 -15
- data/lib/graphiti_gql/graphiti_hax.rb +28 -9
- data/lib/graphiti_gql/loaders/belongs_to.rb +1 -0
- data/lib/graphiti_gql/loaders/many_to_many.rb +4 -1
- data/lib/graphiti_gql/schema/fields/attribute.rb +1 -1
- data/lib/graphiti_gql/schema/fields/to_many.rb +28 -11
- data/lib/graphiti_gql/schema/resource_type.rb +8 -3
- data/lib/graphiti_gql/spec_helper.rb +40 -13
- data/lib/graphiti_gql/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d38c8d27dc214efd323ee98932bcb858bca8553e45c5e4428858b3b5503db44d
|
4
|
+
data.tar.gz: ae38e08ba55f6c38b464ed9a3cbd592394568c080aac2361d0549adea259b9fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d50257d774787869a18187e76e924503fb34dfad8c4d93fd73d99289fc203626d120585448bc646175cb9ff80e607df5c374a6207a95732aeccedb2d20ea9d39
|
7
|
+
data.tar.gz: e1f1ff11574682dd8946907f2e76e3b9279c08039e29e4bc1f53436f184c1e6bd0e04f2ef52f391526abd1d837ef6a9dbd3f1a8a617528ee90942857b66d9706
|
data/.github/probots.yml
ADDED
@@ -1,17 +1,26 @@
|
|
1
|
+
# TODO: Rushing here so tests are in app and code is gross
|
1
2
|
module GraphitiGql
|
2
3
|
module ActiveResource
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
5
6
|
class Node < OpenStruct
|
6
|
-
def initialize(
|
7
|
+
def initialize(hash, resource = nil)
|
7
8
|
@resource = resource
|
9
|
+
@edges = {}
|
10
|
+
@node_id = hash.delete(:node_id)
|
8
11
|
hash.each_pair do |key, value|
|
9
12
|
if value.is_a?(Hash)
|
10
13
|
if (sideload = resource.sideload(key))
|
11
14
|
if value.key?(:edges)
|
12
|
-
|
15
|
+
@edges[key] = value[:edges].map do |edge|
|
16
|
+
node_id = edge[:node][:id]
|
17
|
+
Node.new(edge.except(:node).merge(node_id: node_id))
|
18
|
+
end
|
19
|
+
hash[key] = value[:edges].map { |v| Node.new(v[:node], sideload.resource.class) }
|
20
|
+
elsif value.key?(:nodes)
|
21
|
+
hash[key] = value[:nodes].map { |n| Node.new(n, sideload.resource.class) }
|
13
22
|
else
|
14
|
-
hash[key] = Node.new(sideload.resource.class
|
23
|
+
hash[key] = Node.new(value, sideload.resource.class)
|
15
24
|
end
|
16
25
|
end
|
17
26
|
end
|
@@ -19,6 +28,15 @@ module GraphitiGql
|
|
19
28
|
super(hash)
|
20
29
|
end
|
21
30
|
|
31
|
+
def edge(name, node_id)
|
32
|
+
found = @edges[name].empty? ? nil : @edges[name]
|
33
|
+
if found && node_id
|
34
|
+
found.find { |f| f.instance_variable_get(:@node_id) == node_id.to_s }
|
35
|
+
else
|
36
|
+
found
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
22
40
|
def decoded_id
|
23
41
|
Base64.decode64(self.id)
|
24
42
|
end
|
@@ -29,7 +47,8 @@ module GraphitiGql
|
|
29
47
|
end
|
30
48
|
|
31
49
|
class Proxy
|
32
|
-
def initialize(resource, params, ctx)
|
50
|
+
def initialize(resource, params, ctx, query)
|
51
|
+
@query = query
|
33
52
|
@resource = resource
|
34
53
|
@ctx = ctx
|
35
54
|
@params = params.deep_transform_keys { |key| key.to_s.camelize(:lower).to_sym }
|
@@ -46,10 +65,18 @@ module GraphitiGql
|
|
46
65
|
result
|
47
66
|
end
|
48
67
|
|
68
|
+
def node(id)
|
69
|
+
nodes.find { |n| n.id == id.to_s }
|
70
|
+
end
|
71
|
+
|
49
72
|
def nodes
|
50
73
|
return [] unless data
|
51
|
-
|
52
|
-
|
74
|
+
elements = if edges
|
75
|
+
edges.map { |e| e[:node] }
|
76
|
+
else
|
77
|
+
data[data.keys.first][:nodes] || []
|
78
|
+
end
|
79
|
+
elements.map { |n| Node.new(underscore(n), @resource) }
|
53
80
|
end
|
54
81
|
alias :to_a :nodes
|
55
82
|
|
@@ -85,10 +112,14 @@ module GraphitiGql
|
|
85
112
|
underscore(data[data.keys.first][:pageInfo])
|
86
113
|
end
|
87
114
|
|
115
|
+
# barf
|
88
116
|
def query
|
117
|
+
return @query if @query
|
118
|
+
|
89
119
|
name = Schema.registry.key_for(@resource)
|
90
|
-
filter_bang = "!" if @resource.filters.values.any? { |f| f[:required] }
|
91
120
|
sortvar = "$sort: [#{name}Sort!]," if @resource.sorts.any?
|
121
|
+
filter_bang = "!" if @resource.filters.values.any? { |f| f[:required] }
|
122
|
+
filtervar = "$filter: #{name}Filter#{filter_bang}," if @resource.filters.any?
|
92
123
|
|
93
124
|
if !(fields = @params[:fields])
|
94
125
|
fields = []
|
@@ -99,7 +130,7 @@ module GraphitiGql
|
|
99
130
|
|
100
131
|
q = %|
|
101
132
|
query #{name} (
|
102
|
-
|
133
|
+
#{filtervar}
|
103
134
|
#{sortvar}
|
104
135
|
$first: Int,
|
105
136
|
$last: Int,
|
@@ -107,7 +138,7 @@ module GraphitiGql
|
|
107
138
|
$after: String,
|
108
139
|
) {
|
109
140
|
#{@resource.graphql_entrypoint} (
|
110
|
-
filter: $filter,
|
141
|
+
#{ 'filter: $filter,' if filtervar }
|
111
142
|
#{ 'sort: $sort,' if sortvar }
|
112
143
|
first: $first,
|
113
144
|
last: $last,
|
@@ -118,6 +149,7 @@ module GraphitiGql
|
|
118
149
|
node {|
|
119
150
|
|
120
151
|
fields.each do |name|
|
152
|
+
next if name.is_a?(Hash)
|
121
153
|
q << %|
|
122
154
|
#{name.to_s.camelize(:lower)}|
|
123
155
|
end
|
@@ -129,17 +161,36 @@ module GraphitiGql
|
|
129
161
|
sideload = @resource.sideload(inc.to_sym)
|
130
162
|
to_one = [:belongs_to, :has_one, :polymorphic_belongs_to].include?(sideload.type)
|
131
163
|
indent = " " if !to_one
|
164
|
+
|
165
|
+
edge_fields = []
|
166
|
+
runtime_sideload_fields = @params[:fields].find { |f| f.is_a?(Hash) && f.key?(inc.to_sym) }
|
167
|
+
if runtime_sideload_fields
|
168
|
+
runtime_sideload_fields = runtime_sideload_fields.values
|
169
|
+
edge_fields = runtime_sideload_fields.find { |f| f.is_a?(Hash) && f.key?(:edge) }
|
170
|
+
runtime_sideload_fields = runtime_sideload_fields.reject { |f| f.is_a?(Hash) }
|
171
|
+
edge_fields = edge_fields[:edge] if edge_fields
|
172
|
+
end
|
173
|
+
|
132
174
|
q << %|
|
133
175
|
#{inc.to_s.camelize(:lower)} {|
|
134
176
|
if !to_one
|
135
177
|
q << %|
|
136
|
-
edges {
|
178
|
+
edges {|
|
179
|
+
|
180
|
+
edge_fields.each do |ef|
|
181
|
+
q << %|
|
182
|
+
#{ef.to_s.camelize(:lower)}|
|
183
|
+
end
|
184
|
+
|
185
|
+
q << %|
|
137
186
|
node {|
|
138
187
|
end
|
139
188
|
|
140
|
-
|
141
|
-
|
142
|
-
|
189
|
+
sideload_fields = runtime_sideload_fields
|
190
|
+
if sideload_fields.blank?
|
191
|
+
sideload_fields = @resource.sideload(inc.to_sym).resource.attributes.select { |_, config| config[:readable] }.map(&:first)
|
192
|
+
end
|
193
|
+
sideload_fields.each do |name|
|
143
194
|
q << %|
|
144
195
|
#{indent}#{name.to_s.camelize(:lower)}|
|
145
196
|
end
|
@@ -200,8 +251,8 @@ module GraphitiGql
|
|
200
251
|
end
|
201
252
|
|
202
253
|
class_methods do
|
203
|
-
def gql(params = {}, ctx = {})
|
204
|
-
Proxy.new(self, params, ctx)
|
254
|
+
def gql(params = {}, ctx = {}, query = nil)
|
255
|
+
Proxy.new(self, params, ctx, query)
|
205
256
|
end
|
206
257
|
end
|
207
258
|
end
|
@@ -143,22 +143,41 @@ module GraphitiGql
|
|
143
143
|
Graphiti::Scoping::Paginate.send(:prepend, PaginateExtras)
|
144
144
|
|
145
145
|
module ManyToManyExtras
|
146
|
-
|
146
|
+
def self.prepended(klass)
|
147
|
+
klass.class_eval do
|
148
|
+
class << self
|
149
|
+
attr_accessor :edge_resource
|
147
150
|
|
148
|
-
|
149
|
-
|
151
|
+
def attribute(*args, &blk)
|
152
|
+
@edge_resource ||= Class.new(Graphiti::Resource) do
|
153
|
+
def self.abstract_class?
|
154
|
+
true
|
155
|
+
end
|
156
|
+
end
|
157
|
+
@edge_resource.attribute(*args, &blk)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def apply_belongs_to_many_filter
|
164
|
+
super
|
165
|
+
self_ref = self
|
166
|
+
fk_type = parent_resource_class.attributes[:id][:type]
|
167
|
+
fk_type = :hash if polymorphic?
|
168
|
+
filters = resource_class.config[:filters]
|
150
169
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
170
|
+
# Keep the options, apply the eq proc
|
171
|
+
if (filter = filters[inverse_filter.to_sym])
|
172
|
+
if filter[:operators][:eq].nil?
|
173
|
+
filter[:operators][:eq] = proc do |scope, value|
|
174
|
+
self_ref.belongs_to_many_filter(scope, value)
|
155
175
|
end
|
156
176
|
end
|
157
|
-
@edge_resource.attribute(*args, &blk)
|
158
177
|
end
|
159
178
|
end
|
160
179
|
end
|
161
|
-
Graphiti::Sideload::ManyToMany.send(:
|
180
|
+
Graphiti::Sideload::ManyToMany.send(:prepend, ManyToManyExtras)
|
162
181
|
|
163
182
|
module StatsExtras
|
164
183
|
def calculate_stat(name, function)
|
@@ -19,8 +19,11 @@ module GraphitiGql
|
|
19
19
|
def add_join_table_magic(proxy)
|
20
20
|
if defined?(ActiveRecord) && proxy.resource.model.ancestors.include?(ActiveRecord::Base)
|
21
21
|
thru = @sideload.foreign_key.keys.first
|
22
|
-
|
22
|
+
reflection = @sideload.parent_resource.model.reflect_on_association(thru)
|
23
|
+
thru_model = reflection.klass
|
24
|
+
|
23
25
|
names = thru_model.column_names.map do |n|
|
26
|
+
next if n == :id
|
24
27
|
"#{thru_model.table_name}.#{n} as _edge_#{n}"
|
25
28
|
end
|
26
29
|
scope = proxy.scope.object
|
@@ -42,24 +42,41 @@ module GraphitiGql
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def build_customized_edge_type(sideload_type)
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
edge_type_class = build_edge_type_class(sideload_type)
|
46
|
+
|
47
|
+
# Build the sideload type with new edge class applied
|
48
|
+
if sideload_type.is_a?(Module)
|
49
|
+
klass = sideload_type
|
50
|
+
# There's some magic that happens when subclassing, but modules
|
51
|
+
# don't subclass. This is the kind of resetting we need to happen.
|
52
|
+
# Might be a graphql-ruby issue.
|
53
|
+
klass.instance_variable_set(:@connection_type, nil)
|
54
|
+
klass.instance_variable_set(:@edge_type, nil)
|
55
|
+
klass.edge_type_class(edge_type_class)
|
56
|
+
klass
|
57
|
+
else
|
58
|
+
klass = Class.new(sideload_type)
|
59
|
+
klass.edge_type_class(edge_class)
|
60
|
+
klass
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_edge_type_class(sideload_type)
|
65
|
+
prior_edge_type_class = sideload_type.edge_type_class
|
66
|
+
edge_type_class = Class.new(prior_edge_type_class)
|
48
67
|
edge_resource = @sideload.class.edge_resource
|
49
68
|
edge_resource.attributes.each_pair do |name, config|
|
50
69
|
next if name == :id
|
51
|
-
Schema::Fields::Attribute.new(name, config, @sideload).apply(
|
70
|
+
Schema::Fields::Attribute.new(name, config, @sideload).apply(edge_type_class)
|
52
71
|
end
|
53
72
|
registered_parent = Schema.registry.get(@sideload.parent_resource.class)
|
54
73
|
parent_name = registered_parent[:type].graphql_name
|
55
|
-
|
56
|
-
|
74
|
+
edge_type_class_name = "#{parent_name}To#{sideload_type.graphql_name}Edge"
|
75
|
+
edge_type_class.define_method :graphql_name do
|
76
|
+
edge_type_class_name
|
57
77
|
end
|
58
|
-
|
59
|
-
|
60
|
-
klass = Class.new(sideload_type)
|
61
|
-
klass.edge_type_class(edge_class)
|
62
|
-
klass
|
78
|
+
edge_type_class.graphql_name(edge_type_class_name)
|
79
|
+
edge_type_class
|
63
80
|
end
|
64
81
|
end
|
65
82
|
end
|
@@ -34,14 +34,19 @@ module GraphitiGql
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
def process_polymorphic_parent(
|
37
|
+
def process_polymorphic_parent(interface_type)
|
38
|
+
registry_name = registry.key_for(@resource, interface: false)
|
39
|
+
type = Class.new(Schema.base_object)
|
40
|
+
type.graphql_name(registry_name)
|
41
|
+
type.implements(interface_type)
|
42
|
+
|
38
43
|
# Define the actual class that implements the interface
|
39
44
|
registry.set(@resource, type, interface: false)
|
40
45
|
@resource.children.each do |child|
|
41
46
|
if (registered = registry.get(child))
|
42
|
-
registered[:type].implements(
|
47
|
+
registered[:type].implements(interface_type)
|
43
48
|
else
|
44
|
-
self.class.new(child, implements:
|
49
|
+
self.class.new(child, implements: interface_type).build
|
45
50
|
end
|
46
51
|
end
|
47
52
|
end
|
@@ -2,6 +2,21 @@ module GraphitiGql
|
|
2
2
|
module SpecHelper
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
+
module ScopeTrackable
|
6
|
+
def self.prepended(klass)
|
7
|
+
klass.class_eval do
|
8
|
+
class << self
|
9
|
+
attr_accessor :resolved_scope
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def resolve(scope)
|
15
|
+
self.class.resolved_scope = scope
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
5
20
|
included do
|
6
21
|
extend Forwardable
|
7
22
|
def_delegators :result,
|
@@ -9,29 +24,37 @@ module GraphitiGql
|
|
9
24
|
:errors,
|
10
25
|
:error_messages,
|
11
26
|
:nodes,
|
27
|
+
:node,
|
12
28
|
:stats
|
13
29
|
|
30
|
+
Graphiti::Resource.send(:prepend, ScopeTrackable)
|
31
|
+
|
14
32
|
if defined?(RSpec)
|
15
|
-
let(:params)
|
16
|
-
fields = []
|
17
|
-
resource.attributes.each_pair do |name, config|
|
18
|
-
(fields << name) if config[:readable]
|
19
|
-
end
|
20
|
-
{ fields: fields }
|
21
|
-
end
|
33
|
+
let(:params) { {} }
|
22
34
|
let(:resource) { described_class }
|
23
35
|
let(:ctx) { {} }
|
36
|
+
let(:only_fields) { [] }
|
37
|
+
let(:except_fields) { [] }
|
24
38
|
|
25
39
|
def self.only_fields(*fields)
|
26
|
-
|
27
|
-
fields.each { |f| params[:fields].select! { |p| p == f } }
|
28
|
-
end
|
40
|
+
let(:only_fields) { fields }
|
29
41
|
end
|
30
42
|
|
31
43
|
def self.except_fields(*fields)
|
32
|
-
|
33
|
-
|
44
|
+
let(:except_fields) { fields }
|
45
|
+
end
|
46
|
+
|
47
|
+
let(:fields) do
|
48
|
+
fields = []
|
49
|
+
resource.attributes.each_pair do |name, config|
|
50
|
+
(fields << name) if config[:readable]
|
51
|
+
end
|
52
|
+
if respond_to?(:only_fields) && only_fields.present?
|
53
|
+
fields.select! { |f| only_fields.include?(f) }
|
54
|
+
elsif respond_to?(:except_fields) && except_fields.present?
|
55
|
+
fields.reject! { |f| except_fields.include?(f) }
|
34
56
|
end
|
57
|
+
fields
|
35
58
|
end
|
36
59
|
end
|
37
60
|
end
|
@@ -44,9 +67,13 @@ module GraphitiGql
|
|
44
67
|
end
|
45
68
|
end
|
46
69
|
|
70
|
+
def proxy
|
71
|
+
q = defined?(query) ? query : nil
|
72
|
+
resource.gql(params.merge(fields: fields), ctx, q)
|
73
|
+
end
|
74
|
+
|
47
75
|
def run
|
48
76
|
lambda do
|
49
|
-
proxy = resource.gql(params, ctx)
|
50
77
|
proxy.to_h
|
51
78
|
proxy
|
52
79
|
end
|
data/lib/graphiti_gql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphiti_gql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Richmond
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -115,6 +115,7 @@ executables: []
|
|
115
115
|
extensions: []
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
|
+
- ".github/probots.yml"
|
118
119
|
- ".gitignore"
|
119
120
|
- ".rspec"
|
120
121
|
- ".travis.yml"
|