graphiform 0.2.9 → 0.2.13
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/lib/graphiform.rb +30 -0
- data/lib/graphiform/association_source.rb +58 -0
- data/lib/graphiform/core.rb +52 -6
- data/lib/graphiform/fields.rb +20 -8
- data/lib/graphiform/helpers.rb +16 -17
- data/lib/graphiform/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24d0d05956c47d3c131958d9b273951c53d313f28dd622a5f841724ce18e1a4a
|
4
|
+
data.tar.gz: 82bd9b1ba24f07a5abc4cb164bd64ea8d217409d434613b543a2441edf5ba202
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5480858bde4de83a235a691ee1e7ec05f49f7348d44e0e8b3fd6e739ab17211f1f4ea7e0e651cd43edbe7b34b4227c429c7c87d542bea668a406cd679fff9b5
|
7
|
+
data.tar.gz: 96d29abd576caf4dfe334f10df9eddf89a32055c9677bcb600dccb07529a24d7531c5a2fb9e5a25595626164e9398bc900a0211b07537269a09472240480416a
|
data/lib/graphiform.rb
CHANGED
@@ -19,4 +19,34 @@ module Graphiform
|
|
19
19
|
include Graphiform::Fields
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
def self.configuration
|
24
|
+
@configuration ||= {
|
25
|
+
scalar_mappings: {
|
26
|
+
string: GraphQL::Types::String,
|
27
|
+
text: GraphQL::Types::String,
|
28
|
+
# nchar: GraphQL::Types::String,
|
29
|
+
|
30
|
+
date: GraphQL::Types::ISO8601Date,
|
31
|
+
|
32
|
+
time: GraphQL::Types::ISO8601DateTime,
|
33
|
+
datetime: GraphQL::Types::ISO8601DateTime,
|
34
|
+
timestamp: GraphQL::Types::ISO8601DateTime,
|
35
|
+
|
36
|
+
integer: GraphQL::Types::Int,
|
37
|
+
|
38
|
+
float: GraphQL::Types::Float,
|
39
|
+
decimal: GraphQL::Types::Float,
|
40
|
+
|
41
|
+
boolean: GraphQL::Types::Boolean,
|
42
|
+
|
43
|
+
json: GraphQL::Types::JSON,
|
44
|
+
jsonb: GraphQL::Types::JSON,
|
45
|
+
},
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.configure
|
50
|
+
yield(configuration)
|
51
|
+
end
|
22
52
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Graphiform
|
4
|
+
class AssociationSource < GraphQL::Dataloader::Source
|
5
|
+
def initialize(model, attribute, **options)
|
6
|
+
super()
|
7
|
+
|
8
|
+
@model = model
|
9
|
+
@attribute = attribute
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(values)
|
14
|
+
normalized_values = normalize_values(values)
|
15
|
+
records = query(normalized_values.uniq).to_a
|
16
|
+
results(normalized_values, records)
|
17
|
+
end
|
18
|
+
|
19
|
+
def query(values)
|
20
|
+
query = @model
|
21
|
+
query = query.merge(@model.instance_exec(&@options[:scope])) if @options[:scope].present?
|
22
|
+
query = query.where(@attribute => values)
|
23
|
+
|
24
|
+
query = query.includes(@options[:includes]) if @options[:includes].present? && query.respond_to?(:includes)
|
25
|
+
query = query.apply_filters(@options[:where].to_h) if @options[:where].present? && query.respond_to?(:apply_filters)
|
26
|
+
query = query.apply_sorts(@options[:sort].to_h) if @options[:sort].present? && query.respond_to?(:apply_sorts)
|
27
|
+
|
28
|
+
query
|
29
|
+
end
|
30
|
+
|
31
|
+
def normalize_value(value)
|
32
|
+
value = value.downcase if !@options[:case_sensitive] && value.is_a?(String)
|
33
|
+
|
34
|
+
value
|
35
|
+
end
|
36
|
+
|
37
|
+
def normalize_values(values)
|
38
|
+
type_for_attribute = @model.type_for_attribute(@attribute) if @model.respond_to?(:type_for_attribute)
|
39
|
+
values.map do |value|
|
40
|
+
value = type_for_attribute.cast(value) if type_for_attribute.present?
|
41
|
+
normalize_value(value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def results(values, records)
|
46
|
+
record_attributes = records.map { |record| normalize_value(record[@attribute]) }
|
47
|
+
values.map do |value|
|
48
|
+
if @options[:multi]
|
49
|
+
indexes = record_attributes.each_index.select { |index| record_attributes[index] == value }
|
50
|
+
indexes.map { |index| index && records[index] }
|
51
|
+
else
|
52
|
+
index = record_attributes.index(value)
|
53
|
+
index && records[index]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/graphiform/core.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'active_support/concern'
|
4
4
|
|
5
5
|
require 'graphiform/helpers'
|
6
|
+
require 'graphiform/association_source'
|
6
7
|
|
7
8
|
module Graphiform
|
8
9
|
module Core
|
@@ -37,6 +38,7 @@ module Graphiform
|
|
37
38
|
end
|
38
39
|
@filter.class_eval do
|
39
40
|
argument 'OR', [self], required: false
|
41
|
+
argument 'AND', [self], required: false
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
@@ -153,7 +155,7 @@ module Graphiform
|
|
153
155
|
def base_resolve(**args)
|
154
156
|
@value = model.all
|
155
157
|
apply_built_ins(**args)
|
156
|
-
@value.
|
158
|
+
@value.take
|
157
159
|
end
|
158
160
|
end
|
159
161
|
end
|
@@ -173,18 +175,62 @@ module Graphiform
|
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
176
|
-
def graphql_create_resolver(method_name, resolver_type = graphql_type, read_prepare: nil, read_resolve: nil, null: true, **)
|
178
|
+
def graphql_create_resolver(method_name, resolver_type = graphql_type, read_prepare: nil, read_resolve: nil, null: true, skip_dataloader: false, case_sensitive: Graphiform.configuration[:case_sensitive], **)
|
177
179
|
Class.new(graphql_base_resolver) do
|
178
180
|
type resolver_type, null: null
|
179
181
|
|
180
182
|
define_method :base_resolve do |**args|
|
181
183
|
@value = object
|
182
184
|
|
183
|
-
|
184
|
-
|
185
|
-
@value = instance_exec(@value, context, &read_prepare) if read_prepare
|
185
|
+
association_def = @value.association(method_name)&.reflection
|
186
|
+
join_keys = association_def&.join_keys
|
186
187
|
|
187
|
-
|
188
|
+
skip_dataloader ||=
|
189
|
+
!association_def ||
|
190
|
+
!Helpers.dataloader_support?(dataloader, association_def, join_keys.foreign_key) ||
|
191
|
+
read_resolve ||
|
192
|
+
read_prepare ||
|
193
|
+
args[:group]
|
194
|
+
|
195
|
+
if skip_dataloader
|
196
|
+
@value = instance_exec(@value, context, &read_resolve) if read_resolve
|
197
|
+
@value = @value.public_send(method_name) if !read_resolve && @value.respond_to?(method_name)
|
198
|
+
@value = instance_exec(@value, context, &read_prepare) if read_prepare
|
199
|
+
|
200
|
+
apply_built_ins(**args)
|
201
|
+
else
|
202
|
+
dataloader
|
203
|
+
.with(
|
204
|
+
AssociationSource,
|
205
|
+
association_def.klass,
|
206
|
+
join_keys.key,
|
207
|
+
scope: association_def.scope,
|
208
|
+
where: args[:where],
|
209
|
+
sort: args[:sort],
|
210
|
+
multi: true,
|
211
|
+
case_sensitive: case_sensitive,
|
212
|
+
)
|
213
|
+
.load(
|
214
|
+
@value.public_send(join_keys.foreign_key)
|
215
|
+
)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def graphql_create_association_resolver(association_def, resolver_type, null: true, skip_dataloader: false, case_sensitive: nil, **)
|
222
|
+
Class.new(::Resolvers::BaseResolver) do
|
223
|
+
type resolver_type, null: null
|
224
|
+
|
225
|
+
define_method :resolve do |*|
|
226
|
+
join_keys = association_def.join_keys
|
227
|
+
|
228
|
+
skip_dataloader ||= !Helpers.dataloader_support?(dataloader, association_def, join_keys.foreign_key)
|
229
|
+
|
230
|
+
return object.public_send(association_def.name) if skip_dataloader
|
231
|
+
|
232
|
+
value = object.public_send(join_keys.foreign_key)
|
233
|
+
dataloader.with(AssociationSource, association_def.klass, join_keys.key, scope: association_def.scope, case_sensitive: case_sensitive).load(value)
|
188
234
|
end
|
189
235
|
end
|
190
236
|
end
|
data/lib/graphiform/fields.rb
CHANGED
@@ -12,16 +12,17 @@ module Graphiform
|
|
12
12
|
as: nil,
|
13
13
|
**options
|
14
14
|
)
|
15
|
-
|
16
|
-
|
15
|
+
identifier = as || name
|
16
|
+
column_def = column(identifier)
|
17
|
+
association_def = association(identifier)
|
17
18
|
|
18
19
|
graphql_add_column_field(name, column_def, as: as, **options) if column_def.present?
|
19
20
|
graphql_add_association_field(name, association_def, as: as, **options) if association_def.present?
|
20
21
|
graphql_add_method_field(name, as: as, **options) unless column_def.present? || association_def.present?
|
21
22
|
|
22
|
-
graphql_add_scopes_to_filter(name,
|
23
|
-
graphql_field_to_sort(name,
|
24
|
-
graphql_field_to_grouping(name,
|
23
|
+
graphql_add_scopes_to_filter(name, identifier)
|
24
|
+
graphql_field_to_sort(name, identifier)
|
25
|
+
graphql_field_to_grouping(name, identifier)
|
25
26
|
end
|
26
27
|
|
27
28
|
def graphql_writable_field(
|
@@ -266,6 +267,8 @@ module Graphiform
|
|
266
267
|
include_connection: true,
|
267
268
|
read_prepare: nil,
|
268
269
|
read_resolve: nil,
|
270
|
+
skip_dataloader: false,
|
271
|
+
case_sensitive: Graphiform.configuration[:case_sensitive],
|
269
272
|
**options
|
270
273
|
)
|
271
274
|
unless association_def.klass.respond_to?(:graphql_type)
|
@@ -291,7 +294,9 @@ module Graphiform
|
|
291
294
|
klass.graphql_connection,
|
292
295
|
read_prepare: read_prepare,
|
293
296
|
read_resolve: read_resolve,
|
294
|
-
null: false
|
297
|
+
null: false,
|
298
|
+
skip_dataloader: true,
|
299
|
+
case_sensitive: case_sensitive
|
295
300
|
),
|
296
301
|
false,
|
297
302
|
**options
|
@@ -306,10 +311,17 @@ module Graphiform
|
|
306
311
|
[klass.graphql_type],
|
307
312
|
read_prepare: read_prepare,
|
308
313
|
read_resolve: read_resolve,
|
309
|
-
null: false
|
314
|
+
null: false,
|
315
|
+
skip_dataloader: skip_dataloader,
|
316
|
+
case_sensitive: case_sensitive
|
310
317
|
)
|
311
318
|
else
|
312
|
-
klass.
|
319
|
+
klass.graphql_create_association_resolver(
|
320
|
+
association_def,
|
321
|
+
klass.graphql_type,
|
322
|
+
skip_dataloader: skip_dataloader,
|
323
|
+
case_sensitive: case_sensitive
|
324
|
+
)
|
313
325
|
end
|
314
326
|
)
|
315
327
|
|
data/lib/graphiform/helpers.rb
CHANGED
@@ -5,7 +5,7 @@ module Graphiform
|
|
5
5
|
def self.logger
|
6
6
|
return Rails.logger if Rails.logger.present?
|
7
7
|
|
8
|
-
@logger ||= Logger.new(
|
8
|
+
@logger ||= Logger.new($stdout)
|
9
9
|
@logger
|
10
10
|
end
|
11
11
|
|
@@ -19,22 +19,7 @@ module Graphiform
|
|
19
19
|
def self.graphql_type_single(active_record_type)
|
20
20
|
return active_record_type unless active_record_type.respond_to?(:to_sym)
|
21
21
|
|
22
|
-
|
23
|
-
when :string, :text
|
24
|
-
GraphQL::Types::String
|
25
|
-
when :date
|
26
|
-
GraphQL::Types::ISO8601Date
|
27
|
-
when :time, :datetime, :timestamp
|
28
|
-
GraphQL::Types::ISO8601DateTime
|
29
|
-
when :integer
|
30
|
-
GraphQL::Types::Int
|
31
|
-
when :float, :decimal
|
32
|
-
GraphQL::Types::Float
|
33
|
-
when :boolean
|
34
|
-
GraphQL::Types::Boolean
|
35
|
-
else
|
36
|
-
active_record_type
|
37
|
-
end
|
22
|
+
Graphiform.configuration[:scalar_mappings][active_record_type.to_sym] || active_record_type
|
38
23
|
end
|
39
24
|
|
40
25
|
def self.resolver?(val)
|
@@ -70,5 +55,19 @@ module Graphiform
|
|
70
55
|
association_def.klass.send(method).respond_to?(:arguments) &&
|
71
56
|
!association_def.klass.send(method).arguments.empty?
|
72
57
|
end
|
58
|
+
|
59
|
+
def self.dataloader_support?(dataloader, association_def, keys)
|
60
|
+
(
|
61
|
+
association_def.present? &&
|
62
|
+
!association_def.polymorphic? &&
|
63
|
+
!association_def.through_reflection? &&
|
64
|
+
(
|
65
|
+
!association_def.scope ||
|
66
|
+
association_def.scope.arity.zero?
|
67
|
+
) &&
|
68
|
+
!keys.is_a?(Array) &&
|
69
|
+
!dataloader.is_a?(GraphQL::Dataloader::NullDataloader)
|
70
|
+
)
|
71
|
+
end
|
73
72
|
end
|
74
73
|
end
|
data/lib/graphiform/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphiform
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jayce.pulsipher
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03
|
11
|
+
date: 2021-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.2.
|
47
|
+
version: 0.2.9
|
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: 0.2.
|
54
|
+
version: 0.2.9
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: appraisal
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -120,6 +120,7 @@ files:
|
|
120
120
|
- Rakefile
|
121
121
|
- lib/graphiform.rb
|
122
122
|
- lib/graphiform/active_record_helpers.rb
|
123
|
+
- lib/graphiform/association_source.rb
|
123
124
|
- lib/graphiform/core.rb
|
124
125
|
- lib/graphiform/fields.rb
|
125
126
|
- lib/graphiform/helpers.rb
|