graphiti_gql 0.2.1 → 0.2.4
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.lock +2 -2
- data/lib/graphiti_gql/active_resource.rb +210 -0
- data/lib/graphiti_gql/engine.rb +16 -1
- data/lib/graphiti_gql/graphiti_hax.rb +26 -1
- data/lib/graphiti_gql/loaders/belongs_to.rb +2 -1
- data/lib/graphiti_gql/loaders/has_many.rb +4 -4
- data/lib/graphiti_gql/loaders/has_one.rb +15 -0
- data/lib/graphiti_gql/loaders/many.rb +26 -7
- data/lib/graphiti_gql/loaders/many_to_many.rb +4 -4
- data/lib/graphiti_gql/loaders/polymorphic_has_many.rb +8 -5
- data/lib/graphiti_gql/schema/fields/stats.rb +2 -2
- data/lib/graphiti_gql/schema/fields/to_many.rb +13 -14
- data/lib/graphiti_gql/schema/fields/to_one.rb +3 -1
- data/lib/graphiti_gql/schema/query.rb +2 -3
- data/lib/graphiti_gql/schema/resource_type.rb +1 -1
- data/lib/graphiti_gql/schema.rb +15 -0
- data/lib/graphiti_gql/spec_helper.rb +40 -127
- data/lib/graphiti_gql/version.rb +1 -1
- data/lib/graphiti_gql.rb +5 -0
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84a7ebf615007ac087b7bab32e53b78fc1bbdb7abcd9d65e38beac1ec7e578fc
|
4
|
+
data.tar.gz: d5c625d0e34f750d8fc3bc8c71f39ccabb70aa1c87340978620e965137e15feb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8ea8defdb4712239187bcbb14a0d5dbeee9e52bf11a7c32dd747da2eae62247ef66fda15dd63b57886920a895f8215fe7a33b8eb3dc156194b3b2e3fd2f75c6
|
7
|
+
data.tar.gz: 42f885befb9c54a6b915642e40f2d2bb8704571c901c392f2a6fe11196d805113ca7af546ff15db7b336fdceff172ba2c27e9f443381462db26b4b44461eab6b
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
graphiti_gql (0.2.
|
4
|
+
graphiti_gql (0.2.2)
|
5
5
|
graphiti (~> 1.3.9)
|
6
6
|
graphql (~> 2.0)
|
7
7
|
graphql-batch (~> 0.5)
|
@@ -47,7 +47,7 @@ GEM
|
|
47
47
|
jsonapi-serializable (~> 0.3.0)
|
48
48
|
graphiti_errors (1.1.2)
|
49
49
|
jsonapi-serializable (~> 0.1)
|
50
|
-
graphql (2.0.
|
50
|
+
graphql (2.0.11)
|
51
51
|
graphql-batch (0.5.1)
|
52
52
|
graphql (>= 1.10, < 3)
|
53
53
|
promise.rb (~> 0.7.2)
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
module ActiveResource
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
class Node < OpenStruct
|
6
|
+
def initialize(resource, hash)
|
7
|
+
@resource = resource
|
8
|
+
hash.each_pair do |key, value|
|
9
|
+
if value.is_a?(Hash)
|
10
|
+
if (sideload = resource.sideload(key))
|
11
|
+
if value.key?(:edges)
|
12
|
+
hash[key] = value[:edges].map { |v| Node.new(sideload.resource.class, v[:node]) }
|
13
|
+
else
|
14
|
+
hash[key] = Node.new(sideload.resource.class, value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
super(hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
def decoded_id
|
23
|
+
Base64.decode64(self.id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def int_id
|
27
|
+
decoded_id.to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Proxy
|
32
|
+
def initialize(resource, params, ctx)
|
33
|
+
@resource = resource
|
34
|
+
@ctx = ctx
|
35
|
+
@params = params.deep_transform_keys { |key| key.to_s.camelize(:lower).to_sym }
|
36
|
+
(@params[:sort] || []).each do |sort|
|
37
|
+
sort[:att] = sort[:att].to_s.camelize(:lower)
|
38
|
+
sort[:dir] = sort[:dir].to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_h(symbolize_keys: true)
|
43
|
+
result = GraphitiGql.run(query, @params, @ctx)
|
44
|
+
result = result.deep_symbolize_keys if symbolize_keys
|
45
|
+
@response = result
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def nodes
|
50
|
+
return [] unless data
|
51
|
+
nodes = edges.map { |e| underscore(e[:node]) }
|
52
|
+
nodes.map { |n| Node.new(@resource, n) }
|
53
|
+
end
|
54
|
+
alias :to_a :nodes
|
55
|
+
|
56
|
+
def response
|
57
|
+
@response ||= to_h
|
58
|
+
end
|
59
|
+
|
60
|
+
def data
|
61
|
+
if response.key?(:data)
|
62
|
+
response[:data]
|
63
|
+
else
|
64
|
+
raise "Tried to access 'data', but these errors were returned instead: #{error_messages.join(". ")}."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def errors
|
69
|
+
response[:errors]
|
70
|
+
end
|
71
|
+
|
72
|
+
def error_messages
|
73
|
+
response[:errors].map { |e| e[:message] }
|
74
|
+
end
|
75
|
+
|
76
|
+
def edges
|
77
|
+
data[data.keys.first][:edges]
|
78
|
+
end
|
79
|
+
|
80
|
+
def stats
|
81
|
+
underscore(data[data.keys.first][:stats])
|
82
|
+
end
|
83
|
+
|
84
|
+
def page_info
|
85
|
+
underscore(data[data.keys.first][:pageInfo])
|
86
|
+
end
|
87
|
+
|
88
|
+
def query
|
89
|
+
name = Schema.registry.key_for(@resource)
|
90
|
+
filter_bang = "!" if @resource.filters.values.any? { |f| f[:required] }
|
91
|
+
sortvar = "$sort: [#{name}Sort!]," if @resource.sorts.any?
|
92
|
+
|
93
|
+
if !(fields = @params[:fields])
|
94
|
+
fields = []
|
95
|
+
@resource.attributes.each_pair do |name, config|
|
96
|
+
(fields << name) if config[:readable]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
q = %|
|
101
|
+
query #{name} (
|
102
|
+
$filter: #{name}Filter#{filter_bang},
|
103
|
+
#{sortvar}
|
104
|
+
$first: Int,
|
105
|
+
$last: Int,
|
106
|
+
$before: String,
|
107
|
+
$after: String,
|
108
|
+
) {
|
109
|
+
#{@resource.graphql_entrypoint} (
|
110
|
+
filter: $filter,
|
111
|
+
#{ 'sort: $sort,' if sortvar }
|
112
|
+
first: $first,
|
113
|
+
last: $last,
|
114
|
+
before: $before,
|
115
|
+
after: $after,
|
116
|
+
) {
|
117
|
+
edges {
|
118
|
+
node {|
|
119
|
+
|
120
|
+
fields.each do |name|
|
121
|
+
q << %|
|
122
|
+
#{name.to_s.camelize(:lower)}|
|
123
|
+
end
|
124
|
+
|
125
|
+
if @params[:include]
|
126
|
+
includes = Array(@params[:include])
|
127
|
+
# NB HASH (?)
|
128
|
+
includes.each do |inc|
|
129
|
+
sideload = @resource.sideload(inc.to_sym)
|
130
|
+
to_one = [:belongs_to, :has_one, :polymorphic_belongs_to].include?(sideload.type)
|
131
|
+
indent = " " if !to_one
|
132
|
+
q << %|
|
133
|
+
#{inc.to_s.camelize(:lower)} {|
|
134
|
+
if !to_one
|
135
|
+
q << %|
|
136
|
+
edges {
|
137
|
+
node {|
|
138
|
+
end
|
139
|
+
|
140
|
+
r = @resource.sideload(inc.to_sym).resource
|
141
|
+
r.attributes.each_pair do |name, config|
|
142
|
+
next unless config[:readable]
|
143
|
+
q << %|
|
144
|
+
#{indent}#{name.to_s.camelize(:lower)}|
|
145
|
+
end
|
146
|
+
|
147
|
+
if to_one
|
148
|
+
q << %|
|
149
|
+
}|
|
150
|
+
else
|
151
|
+
q << %|
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}|
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
q << %|
|
160
|
+
}
|
161
|
+
}
|
162
|
+
pageInfo {
|
163
|
+
startCursor
|
164
|
+
endCursor
|
165
|
+
hasNextPage
|
166
|
+
hasPreviousPage
|
167
|
+
}|
|
168
|
+
|
169
|
+
if @params[:stats]
|
170
|
+
q << %|
|
171
|
+
stats {|
|
172
|
+
@params[:stats].each_pair do |name, calculations|
|
173
|
+
q << %|
|
174
|
+
#{name.to_s.camelize(:lower)} {|
|
175
|
+
Array(calculations).each do |calc|
|
176
|
+
q << %|
|
177
|
+
#{calc.to_s.camelize(:lower)}|
|
178
|
+
end
|
179
|
+
|
180
|
+
q << %|
|
181
|
+
}|
|
182
|
+
end
|
183
|
+
q << %|
|
184
|
+
}|
|
185
|
+
end
|
186
|
+
|
187
|
+
q << %|
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
|
191
|
+
|
192
|
+
q
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
|
197
|
+
def underscore(hash)
|
198
|
+
hash.deep_transform_keys { |k| k.to_s.underscore.to_sym }
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class_methods do
|
203
|
+
def gql(params = {}, ctx = {})
|
204
|
+
Proxy.new(self, params, ctx)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
Graphiti::Resource.send(:include, GraphitiGql::ActiveResource)
|
data/lib/graphiti_gql/engine.rb
CHANGED
@@ -9,9 +9,18 @@ module GraphitiGql
|
|
9
9
|
GraphitiGql.schema!
|
10
10
|
end
|
11
11
|
|
12
|
+
module ControllerContext
|
13
|
+
def graphql_context
|
14
|
+
ctx = { controller: self }
|
15
|
+
ctx[:current_user] = current_user if respond_to?(:current_user)
|
16
|
+
ctx
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
initializer "graphiti_gql.define_controller" do
|
13
21
|
require "#{Rails.root}/app/controllers/application_controller"
|
14
22
|
app_controller = GraphitiGql.config.application_controller || ::ApplicationController
|
23
|
+
app_controller.send(:include, ControllerContext)
|
15
24
|
|
16
25
|
# rubocop:disable Lint/ConstantDefinitionInBlock(Standard)
|
17
26
|
class GraphitiGql::ExecutionController < app_controller
|
@@ -20,9 +29,15 @@ module GraphitiGql
|
|
20
29
|
variables = params[:variables] || {}
|
21
30
|
result = GraphitiGql.run params[:query],
|
22
31
|
params[:variables],
|
23
|
-
|
32
|
+
graphql_context
|
24
33
|
render json: result
|
25
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def default_context
|
39
|
+
defined?(:current_user)
|
40
|
+
end
|
26
41
|
end
|
27
42
|
end
|
28
43
|
end
|
@@ -11,6 +11,27 @@ module GraphitiGql
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def selections
|
15
|
+
return @selections if @selections
|
16
|
+
lookahead = context[:current_arguments]
|
17
|
+
.keyword_arguments[:lookahead]
|
18
|
+
nodes = lookahead.selection(:nodes)
|
19
|
+
if !nodes.selected?
|
20
|
+
nodes = lookahead
|
21
|
+
.selection(:edges)
|
22
|
+
.selection(:node)
|
23
|
+
end
|
24
|
+
|
25
|
+
if !nodes.selected?
|
26
|
+
nodes = lookahead
|
27
|
+
end
|
28
|
+
|
29
|
+
@selections = nodes
|
30
|
+
.selections
|
31
|
+
.map(&:name).map { |name| name.to_s.underscore.to_sym }
|
32
|
+
@selections
|
33
|
+
end
|
34
|
+
|
14
35
|
class_methods do
|
15
36
|
def attribute(*args)
|
16
37
|
super(*args).tap do
|
@@ -159,7 +180,11 @@ module GraphitiGql
|
|
159
180
|
end
|
160
181
|
|
161
182
|
_in = definition.constructor do |input|
|
162
|
-
|
183
|
+
if input.is_a?(ActiveSupport::TimeWithZone)
|
184
|
+
input = input.utc.round(10).iso8601(6)
|
185
|
+
else
|
186
|
+
Time.zone.parse(input)
|
187
|
+
end
|
163
188
|
end
|
164
189
|
|
165
190
|
# Register it with Graphiti
|
@@ -53,7 +53,8 @@ module GraphitiGql
|
|
53
53
|
end
|
54
54
|
else
|
55
55
|
params = {filter: {id: {eq: ids.join(",")}}}
|
56
|
-
|
56
|
+
resource = Schema.registry.get(@sideload.resource.class)[:resource]
|
57
|
+
records = resource.all(params).data
|
57
58
|
map = records.index_by { |record| record.id }
|
58
59
|
ids.each { |id| fulfill(id, map[id]) }
|
59
60
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module GraphitiGql
|
2
2
|
module Loaders
|
3
3
|
class HasMany < Many
|
4
|
-
def assign(
|
4
|
+
def assign(parent_records, proxy)
|
5
5
|
records = proxy.data
|
6
6
|
map = records.group_by { |record| record.send(@sideload.foreign_key) }
|
7
|
-
|
8
|
-
data = [map[
|
9
|
-
fulfill(
|
7
|
+
parent_records.each do |pr|
|
8
|
+
data = [map[pr.send(@sideload.primary_key)] || [], proxy]
|
9
|
+
fulfill(pr, data)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module GraphitiGql
|
2
|
+
module Loaders
|
3
|
+
class HasOne < Many
|
4
|
+
def assign(parent_records, proxy)
|
5
|
+
records = proxy.data
|
6
|
+
parent_records.each do |pr|
|
7
|
+
corresponding = records.find do |r|
|
8
|
+
r.send(@sideload.foreign_key) == pr.send(@sideload.primary_key)
|
9
|
+
end
|
10
|
+
fulfill(pr, corresponding)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,6 +6,8 @@ module GraphitiGql
|
|
6
6
|
PolymorphicHasMany.for(sideload, params)
|
7
7
|
elsif sideload.type == :many_to_many
|
8
8
|
ManyToMany.for(sideload, params)
|
9
|
+
elsif sideload.type == :has_one
|
10
|
+
HasOne.for(sideload, params)
|
9
11
|
else
|
10
12
|
HasMany.for(sideload, params)
|
11
13
|
end
|
@@ -16,13 +18,26 @@ module GraphitiGql
|
|
16
18
|
@params = params
|
17
19
|
end
|
18
20
|
|
19
|
-
def perform(
|
20
|
-
raise ::Graphiti::Errors::UnsupportedPagination if paginating? &&
|
21
|
-
raise Errors::UnsupportedStats if requesting_stats? &&
|
21
|
+
def perform(parent_records)
|
22
|
+
raise ::Graphiti::Errors::UnsupportedPagination if paginating? && parent_records.length > 1
|
23
|
+
raise Errors::UnsupportedStats if requesting_stats? && parent_records.length > 1 && !can_group?
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
ids = parent_records.map do |pr|
|
26
|
+
pk = pr.send(@sideload.primary_key)
|
27
|
+
if @sideload.polymorphic_as
|
28
|
+
hash = {}
|
29
|
+
hash[@sideload.foreign_key] = pk
|
30
|
+
hash[:"#{@sideload.polymorphic_as}_type"] = pr.class.name
|
31
|
+
hash
|
32
|
+
else
|
33
|
+
pk
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
build_params(ids, parent_records)
|
38
|
+
resource = Schema.registry.get(@sideload.resource.class)[:resource]
|
39
|
+
proxy = resource.all(@params)
|
40
|
+
assign(parent_records, proxy)
|
26
41
|
end
|
27
42
|
|
28
43
|
def assign(ids, proxy)
|
@@ -31,7 +46,7 @@ module GraphitiGql
|
|
31
46
|
|
32
47
|
private
|
33
48
|
|
34
|
-
def build_params(ids)
|
49
|
+
def build_params(ids, parent_records)
|
35
50
|
@params[:filter] ||= {}
|
36
51
|
|
37
52
|
if @sideload.polymorphic_as
|
@@ -59,6 +74,10 @@ module GraphitiGql
|
|
59
74
|
@params[:page] ||= {}
|
60
75
|
@params[:page][:size] = 999
|
61
76
|
end
|
77
|
+
|
78
|
+
if @sideload.params_proc
|
79
|
+
@sideload.params_proc.call(@params, parent_records)
|
80
|
+
end
|
62
81
|
end
|
63
82
|
|
64
83
|
def paginating?
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module GraphitiGql
|
2
2
|
module Loaders
|
3
3
|
class ManyToMany < Many
|
4
|
-
def assign(
|
4
|
+
def assign(parent_records, proxy)
|
5
5
|
thru = @sideload.foreign_key.keys.first
|
6
6
|
fk = @sideload.foreign_key[thru]
|
7
7
|
add_join_table_magic(proxy)
|
8
8
|
records = proxy.data
|
9
|
-
|
9
|
+
parent_records.each do |pr|
|
10
10
|
corresponding = records.select do |record|
|
11
|
-
record.send(:"_edge_#{fk}") ==
|
11
|
+
record.send(:"_edge_#{fk}") == pr.send(@sideload.primary_key)
|
12
12
|
end
|
13
|
-
fulfill(
|
13
|
+
fulfill(pr, [corresponding, proxy])
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -1,15 +1,18 @@
|
|
1
1
|
module GraphitiGql
|
2
2
|
module Loaders
|
3
3
|
class PolymorphicHasMany < Many
|
4
|
-
def assign(
|
4
|
+
def assign(parent_records, proxy)
|
5
5
|
records = proxy.data
|
6
|
-
|
6
|
+
parent_records.each do |pr|
|
7
7
|
corresponding = records.select do |record|
|
8
|
-
record.send("#{@sideload.polymorphic_as}_type")
|
9
|
-
|
8
|
+
child_ft = record.send("#{@sideload.polymorphic_as}_type")
|
9
|
+
child_fk = record.send(@sideload.foreign_key)
|
10
|
+
parent_ft = pr.class.name
|
11
|
+
parent_fk = pr.send(@sideload.primary_key)
|
12
|
+
child_ft == parent_ft && child_fk == parent_fk
|
10
13
|
end
|
11
14
|
data = [corresponding || [], proxy]
|
12
|
-
fulfill(
|
15
|
+
fulfill(pr, data)
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -29,7 +29,7 @@ module GraphitiGql
|
|
29
29
|
name = Registry.instance.key_for(@resource)
|
30
30
|
stat_graphql_name = "#{name}Stats"
|
31
31
|
return Registry.instance[stat_graphql_name][:type] if Registry.instance[stat_graphql_name]
|
32
|
-
klass = Class.new(
|
32
|
+
klass = Class.new(Schema.base_object)
|
33
33
|
klass.graphql_name(stat_graphql_name)
|
34
34
|
@resource.stats.each_pair do |name, config|
|
35
35
|
calc_class = build_calc_class(stat_graphql_name, name, config.calculations.keys)
|
@@ -41,7 +41,7 @@ module GraphitiGql
|
|
41
41
|
|
42
42
|
def build_calc_class(stat_graphql_name, stat_name, calculations)
|
43
43
|
name = "#{stat_graphql_name}#{stat_name}Calculations"
|
44
|
-
klass = Class.new(
|
44
|
+
klass = Class.new(Schema.base_object)
|
45
45
|
klass.graphql_name(name)
|
46
46
|
calculations.each do |calc|
|
47
47
|
klass.field calc, Float, null: false
|
@@ -12,32 +12,31 @@ module GraphitiGql
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def apply(type)
|
15
|
-
|
16
|
-
|
17
|
-
null: false,
|
15
|
+
opts = {
|
16
|
+
null: has_one?,
|
18
17
|
connection: false,
|
19
|
-
extensions: [RelayConnectionExtension],
|
20
18
|
extras: [:lookahead]
|
19
|
+
}
|
20
|
+
opts[:extensions] = [RelayConnectionExtension] unless has_one?
|
21
|
+
field_type = has_one? ? @sideload_type : @sideload_type.connection_type
|
22
|
+
field = type.field @sideload.name,
|
23
|
+
field_type,
|
24
|
+
**opts
|
21
25
|
ListArguments.new(@sideload.resource.class, @sideload).apply(field)
|
22
26
|
_sideload = @sideload
|
23
27
|
type.define_method(@sideload.name) do |**arguments|
|
24
28
|
Util.is_readable_sideload!(_sideload)
|
25
29
|
params = Util.params_from_args(arguments)
|
26
|
-
|
27
|
-
id = if _sideload.polymorphic_as
|
28
|
-
hash = {}
|
29
|
-
hash[_sideload.foreign_key] = pk
|
30
|
-
hash[:"#{_sideload.polymorphic_as}_type"] = object.class.name
|
31
|
-
id = hash
|
32
|
-
else
|
33
|
-
id = pk
|
34
|
-
end
|
35
|
-
Loaders::Many.factory(_sideload, params).load(id)
|
30
|
+
Loaders::Many.factory(_sideload, params).load(object)
|
36
31
|
end
|
37
32
|
end
|
38
33
|
|
39
34
|
private
|
40
35
|
|
36
|
+
def has_one?
|
37
|
+
@sideload.type == :has_one
|
38
|
+
end
|
39
|
+
|
41
40
|
def customized_edge?
|
42
41
|
@sideload.type == :many_to_many && @sideload.class.edge_resource
|
43
42
|
end
|
@@ -19,7 +19,9 @@ module GraphitiGql
|
|
19
19
|
if _sideload.type == :has_one
|
20
20
|
id = object.send(_sideload.primary_key)
|
21
21
|
params = { filter: { _sideload.foreign_key => { eq: id } } }
|
22
|
-
|
22
|
+
|
23
|
+
resource = Schema.registry.get(@sideload.resource.class)[:resource]
|
24
|
+
return resource.all(params).data[0]
|
23
25
|
end
|
24
26
|
|
25
27
|
lookahead = arguments[:lookahead]
|
@@ -3,9 +3,8 @@ module GraphitiGql
|
|
3
3
|
class Query
|
4
4
|
def initialize(resources, existing_query: nil)
|
5
5
|
@resources = resources
|
6
|
-
@query_class = Class.new(existing_query ||
|
6
|
+
@query_class = Class.new(existing_query || Schema.base_object)
|
7
7
|
@query_class.graphql_name "Query"
|
8
|
-
@query_class.field_class ::GraphQL::Schema::Field
|
9
8
|
end
|
10
9
|
|
11
10
|
def build
|
@@ -32,7 +31,7 @@ module GraphitiGql
|
|
32
31
|
|
33
32
|
def add_relationships
|
34
33
|
each_relationship do |type, sideload_type, sideload|
|
35
|
-
if [:has_many, :many_to_many].include?(sideload.type)
|
34
|
+
if [:has_many, :many_to_many, :has_one].include?(sideload.type)
|
36
35
|
Fields::ToMany.new(sideload, sideload_type).apply(type)
|
37
36
|
else
|
38
37
|
Fields::ToOne.new(sideload, sideload_type).apply(type)
|
data/lib/graphiti_gql/schema.rb
CHANGED
@@ -32,6 +32,21 @@ module GraphitiGql
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.base_object
|
36
|
+
klass = Class.new(GraphQL::Schema::Object)
|
37
|
+
# TODO make this config maybe
|
38
|
+
if defined?(ActionView)
|
39
|
+
klass.send(:include, ActionView::Helpers::TranslationHelper)
|
40
|
+
klass.class_eval do
|
41
|
+
def initialize(*)
|
42
|
+
super
|
43
|
+
@virtual_path = "."
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
klass
|
48
|
+
end
|
49
|
+
|
35
50
|
def self.registry
|
36
51
|
Registry.instance
|
37
52
|
end
|
@@ -2,149 +2,62 @@ module GraphitiGql
|
|
2
2
|
module SpecHelper
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
query #{name} (
|
25
|
-
$filter: #{name}Filter,
|
26
|
-
$sort: [#{name}Sort!],
|
27
|
-
$first: Int,
|
28
|
-
$last: Int,
|
29
|
-
$before: String,
|
30
|
-
$after: String,
|
31
|
-
) {
|
32
|
-
#{resource.graphql_entrypoint} (
|
33
|
-
filter: $filter,
|
34
|
-
sort: $sort,
|
35
|
-
first: $first,
|
36
|
-
last: $last,
|
37
|
-
before: $before,
|
38
|
-
after: $after,
|
39
|
-
) {
|
40
|
-
edges {
|
41
|
-
node {|
|
42
|
-
|
43
|
-
fields.each do |name|
|
44
|
-
q << %|
|
45
|
-
#{name.to_s.camelize(:lower)}|
|
46
|
-
end
|
5
|
+
included do
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :result,
|
8
|
+
:page_info,
|
9
|
+
:errors,
|
10
|
+
:error_messages,
|
11
|
+
:nodes,
|
12
|
+
:stats
|
13
|
+
|
14
|
+
if defined?(RSpec)
|
15
|
+
let(:params) do
|
16
|
+
fields = []
|
17
|
+
resource.attributes.each_pair do |name, config|
|
18
|
+
(fields << name) if config[:readable]
|
19
|
+
end
|
20
|
+
{ fields: fields }
|
21
|
+
end
|
22
|
+
let(:resource) { described_class }
|
23
|
+
let(:ctx) { {} }
|
47
24
|
|
48
|
-
|
49
|
-
|
50
|
-
}
|
51
|
-
pageInfo {
|
52
|
-
startCursor
|
53
|
-
endCursor
|
54
|
-
hasNextPage
|
55
|
-
hasPreviousPage
|
56
|
-
}|
|
57
|
-
|
58
|
-
if params[:stats]
|
59
|
-
q << %|
|
60
|
-
stats {|
|
61
|
-
params[:stats].each_pair do |name, calculations|
|
62
|
-
q << %|
|
63
|
-
#{name.to_s.camelize(:lower)} {|
|
64
|
-
Array(calculations).each do |calc|
|
65
|
-
q << %|
|
66
|
-
#{calc.to_s.camelize(:lower)}|
|
25
|
+
def self.only_fields(*fields)
|
26
|
+
before do
|
27
|
+
fields.each { |f| params[:fields].select! { |p| p == f } }
|
67
28
|
end
|
68
|
-
|
69
|
-
q << %|
|
70
|
-
}|
|
71
29
|
end
|
72
|
-
q << %|
|
73
|
-
}|
|
74
|
-
end
|
75
|
-
|
76
|
-
q << %|
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
|
80
|
-
|
81
|
-
q
|
82
|
-
end
|
83
30
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
sort[:att] = sort[:att].to_s.camelize(:lower)
|
89
|
-
sort[:dir] = sort[:dir].to_s
|
31
|
+
def self.except_fields(*fields)
|
32
|
+
before do
|
33
|
+
fields.each { |f| params[:fields].reject! { |p| p == f } }
|
34
|
+
end
|
90
35
|
end
|
91
|
-
GraphitiGql.run(query, gql_params, ctx).deep_symbolize_keys
|
92
36
|
end
|
93
37
|
end
|
94
38
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
def response
|
100
|
-
@response ||= run!
|
101
|
-
end
|
102
|
-
|
103
|
-
def errors
|
104
|
-
response[:errors]
|
105
|
-
end
|
106
|
-
|
107
|
-
def error_messages
|
108
|
-
response[:errors].map { |e| e[:message] }
|
109
|
-
end
|
110
|
-
|
111
|
-
def nodes
|
112
|
-
return [] unless data
|
113
|
-
nodes = edges.map { |e| Util.underscore(e[:node]) }
|
114
|
-
nodes.map { |n| ::GraphitiGql::SpecHelper::Node.new(n) }
|
115
|
-
end
|
116
|
-
|
117
|
-
def data
|
118
|
-
if response.key?(:data)
|
119
|
-
response[:data]
|
39
|
+
def gql_datetime(timestamp, precise = false)
|
40
|
+
if precise
|
41
|
+
timestamp.utc.round(10).iso8601(6)
|
120
42
|
else
|
121
|
-
|
43
|
+
DateTime.parse(timestamp.to_s).iso8601
|
122
44
|
end
|
123
45
|
end
|
124
46
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
47
|
+
def run
|
48
|
+
lambda do
|
49
|
+
proxy = resource.gql(params, ctx)
|
50
|
+
proxy.to_h
|
51
|
+
proxy
|
52
|
+
end
|
131
53
|
end
|
132
54
|
|
133
|
-
def
|
134
|
-
|
55
|
+
def run!
|
56
|
+
@result = run.call
|
135
57
|
end
|
136
58
|
|
137
|
-
|
138
|
-
|
139
|
-
let(:resource) { described_class }
|
140
|
-
let(:ctx) { {} }
|
141
|
-
let(:fields) do
|
142
|
-
fields = []
|
143
|
-
resource.attributes.each_pair do |name, config|
|
144
|
-
(fields << name) if config[:readable]
|
145
|
-
end
|
146
|
-
fields
|
147
|
-
end
|
59
|
+
def result
|
60
|
+
@result ||= run!
|
148
61
|
end
|
149
62
|
end
|
150
63
|
end
|
data/lib/graphiti_gql/version.rb
CHANGED
data/lib/graphiti_gql.rb
CHANGED
@@ -9,6 +9,7 @@ require "graphiti_gql/loaders/has_many"
|
|
9
9
|
require "graphiti_gql/loaders/many_to_many"
|
10
10
|
require "graphiti_gql/loaders/polymorphic_has_many"
|
11
11
|
require "graphiti_gql/loaders/belongs_to"
|
12
|
+
require "graphiti_gql/loaders/has_one"
|
12
13
|
require "graphiti_gql/response_shim"
|
13
14
|
require "graphiti_gql/schema"
|
14
15
|
require "graphiti_gql/schema/connection"
|
@@ -24,6 +25,7 @@ require "graphiti_gql/schema/fields/to_many"
|
|
24
25
|
require "graphiti_gql/schema/fields/to_one"
|
25
26
|
require "graphiti_gql/schema/fields/attribute"
|
26
27
|
require "graphiti_gql/schema/fields/stats"
|
28
|
+
require "graphiti_gql/active_resource"
|
27
29
|
require "graphiti_gql/engine" if defined?(Rails)
|
28
30
|
|
29
31
|
module GraphitiGql
|
@@ -64,6 +66,9 @@ module GraphitiGql
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def self.run(query_string, variables = {}, context = {})
|
69
|
+
if context.empty? && Graphiti.context[:object]
|
70
|
+
context = Graphiti.context[:object]
|
71
|
+
end
|
67
72
|
Graphiti.with_context(context) do
|
68
73
|
result = schema.execute query_string,
|
69
74
|
variables: variables,
|
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.4
|
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: 2022-06-
|
11
|
+
date: 2022-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -108,7 +108,7 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '7.0'
|
111
|
-
description:
|
111
|
+
description:
|
112
112
|
email:
|
113
113
|
- richmolj@gmail.com
|
114
114
|
executables: []
|
@@ -137,11 +137,13 @@ files:
|
|
137
137
|
- config/routes.rb
|
138
138
|
- graphiti_gql.gemspec
|
139
139
|
- lib/graphiti_gql.rb
|
140
|
+
- lib/graphiti_gql/active_resource.rb
|
140
141
|
- lib/graphiti_gql/engine.rb
|
141
142
|
- lib/graphiti_gql/errors.rb
|
142
143
|
- lib/graphiti_gql/graphiti_hax.rb
|
143
144
|
- lib/graphiti_gql/loaders/belongs_to.rb
|
144
145
|
- lib/graphiti_gql/loaders/has_many.rb
|
146
|
+
- lib/graphiti_gql/loaders/has_one.rb
|
145
147
|
- lib/graphiti_gql/loaders/many.rb
|
146
148
|
- lib/graphiti_gql/loaders/many_to_many.rb
|
147
149
|
- lib/graphiti_gql/loaders/polymorphic_has_many.rb
|
@@ -167,7 +169,7 @@ licenses:
|
|
167
169
|
- MIT
|
168
170
|
metadata:
|
169
171
|
homepage_uri: https://www.graphiti.dev
|
170
|
-
post_install_message:
|
172
|
+
post_install_message:
|
171
173
|
rdoc_options: []
|
172
174
|
require_paths:
|
173
175
|
- lib
|
@@ -182,8 +184,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
184
|
- !ruby/object:Gem::Version
|
183
185
|
version: '0'
|
184
186
|
requirements: []
|
185
|
-
rubygems_version: 3.3.
|
186
|
-
signing_key:
|
187
|
+
rubygems_version: 3.0.3.1
|
188
|
+
signing_key:
|
187
189
|
specification_version: 4
|
188
190
|
summary: GraphQL support for Graphiti
|
189
191
|
test_files: []
|