graphql-activerecord 0.9.1 → 0.10.0.pre.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graphql/activerecord.rb +28 -4
- data/lib/graphql/models/active_record_extension.rb +1 -1
- data/lib/graphql/models/backed_by_model.rb +77 -19
- data/lib/graphql/models/database_types.rb +39 -0
- data/lib/graphql/models/definition_helpers/associations.rb +70 -38
- data/lib/graphql/models/definition_helpers/attributes.rb +21 -75
- data/lib/graphql/models/definition_helpers.rb +0 -26
- data/lib/graphql/models/mutation_field_map.rb +10 -18
- data/lib/graphql/models/reflection.rb +57 -0
- data/lib/graphql/models/version.rb +1 -1
- metadata +6 -7
- data/lib/graphql/models/object_type.rb +0 -120
- data/lib/graphql/models/proxy_block.rb +0 -52
- data/lib/graphql/models/scalar_types.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 492bdd93511565f485130b3faa32d9af36eed176
|
4
|
+
data.tar.gz: bafa803ca1452a1f7ceefe66362cf4c063e06a49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e5652bd12e1b46d9bb1834aa8eebe149f5e484d79d29fa7d25297121e626f0962729199dc135e532d348344f4105ca35b3f2b6be5d5c3c02aaca938f0b37edf
|
7
|
+
data.tar.gz: ada3b96ec9bcdbfbdf0dee07ed79ccce4b603a7ac353a99f0b2acc65cec877f081d496e4e39a688f6d1e2a27bec5696424fd1ae6eb25efca36fefc1157c895a5
|
data/lib/graphql/activerecord.rb
CHANGED
@@ -19,7 +19,8 @@ require 'graphql/models/relation_loader'
|
|
19
19
|
# Order matters...
|
20
20
|
require 'graphql/models/promise_relation_connection'
|
21
21
|
require 'graphql/models/relation_load_request'
|
22
|
-
require 'graphql/models/
|
22
|
+
require 'graphql/models/database_types'
|
23
|
+
require 'graphql/models/reflection'
|
23
24
|
require 'graphql/models/definition_helpers'
|
24
25
|
require 'graphql/models/definition_helpers/associations'
|
25
26
|
require 'graphql/models/definition_helpers/attributes'
|
@@ -30,16 +31,14 @@ require 'graphql/models/mutation_helpers/validation_error'
|
|
30
31
|
require 'graphql/models/mutation_helpers/validation'
|
31
32
|
require 'graphql/models/mutation_field_map'
|
32
33
|
|
33
|
-
require 'graphql/models/proxy_block'
|
34
34
|
require 'graphql/models/backed_by_model'
|
35
|
-
require 'graphql/models/object_type'
|
36
35
|
require 'graphql/models/mutator'
|
37
36
|
|
38
37
|
|
39
38
|
module GraphQL
|
40
39
|
module Models
|
41
40
|
class << self
|
42
|
-
attr_accessor :
|
41
|
+
attr_accessor :model_from_id, :authorize, :id_for_model, :model_to_graphql_type
|
43
42
|
end
|
44
43
|
|
45
44
|
# Returns a promise that will traverse the associations and resolve to the model at the end of the path.
|
@@ -82,5 +81,30 @@ module GraphQL
|
|
82
81
|
MutationHelpers.print_input_fields(mutator_definition.field_map, definer, "#{prefix}Input")
|
83
82
|
mutator_definition
|
84
83
|
end
|
84
|
+
|
85
|
+
def self.get_graphql_type(model_class)
|
86
|
+
model_class = model_class.constantize if model_class.is_a?(String)
|
87
|
+
|
88
|
+
if model_to_graphql_type
|
89
|
+
model_to_graphql_type[model_class]
|
90
|
+
else
|
91
|
+
"#{model_class.name}Type".safe_constantize
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.get_graphql_type!(model_class)
|
96
|
+
type = get_graphql_type(model_class)
|
97
|
+
fail RuntimeError, "Could not locate GraphQL type for model #{model_class}" if type.nil?
|
98
|
+
type
|
99
|
+
end
|
85
100
|
end
|
86
101
|
end
|
102
|
+
|
103
|
+
GraphQL::ObjectType.accepts_definitions(
|
104
|
+
backed_by_model: -> (graph_type, model_type, &block) do
|
105
|
+
model_type = model_type.to_s.classify.constantize unless model_type.is_a?(Class)
|
106
|
+
|
107
|
+
backer = GraphQL::Models::BackedByModel.new(graph_type, model_type)
|
108
|
+
backer.instance_exec(&block)
|
109
|
+
end
|
110
|
+
)
|
@@ -41,7 +41,7 @@ module GraphQL
|
|
41
41
|
if defined_enums.include?(attribute.to_s)
|
42
42
|
values = defined_enums[attribute.to_s].keys
|
43
43
|
else
|
44
|
-
values =
|
44
|
+
values = Reflection.possible_values(self, attribute)
|
45
45
|
end
|
46
46
|
|
47
47
|
if values.nil?
|
@@ -1,14 +1,18 @@
|
|
1
1
|
module GraphQL
|
2
2
|
module Models
|
3
3
|
class BackedByModel
|
4
|
-
attr_accessor :graph_type, :model_type, :object_to_model
|
5
|
-
|
6
4
|
DEFAULT_OBJECT_TO_MODEL = -> (obj) { obj }
|
7
5
|
|
8
|
-
def initialize(graph_type, model_type)
|
6
|
+
def initialize(graph_type, model_type, base_model_type: model_type, path: [], object_to_model: DEFAULT_OBJECT_TO_MODEL, detect_nulls: true)
|
7
|
+
model_type = model_type.to_s.classify.constantize unless model_type.is_a?(Class)
|
8
|
+
base_model_type = base_model_type.to_s.classify.constantize unless model_type.is_a?(Class)
|
9
|
+
|
9
10
|
@graph_type = graph_type
|
10
11
|
@model_type = model_type
|
11
|
-
@object_to_model =
|
12
|
+
@object_to_model = object_to_model
|
13
|
+
@base_model_type = base_model_type
|
14
|
+
@path = path
|
15
|
+
@detect_nulls = detect_nulls
|
12
16
|
end
|
13
17
|
|
14
18
|
def types
|
@@ -20,36 +24,90 @@ module GraphQL
|
|
20
24
|
@object_to_model
|
21
25
|
end
|
22
26
|
|
23
|
-
|
24
|
-
|
27
|
+
# Allows you to overide the automatic nullability detection. By default, nulls are detected. However, attributes inside
|
28
|
+
# of a proxy_to block are assumed to be nullable, unless the association itself has a presence validator.
|
29
|
+
def detect_nulls(value = nil)
|
30
|
+
@detect_nulls = value if !value.nil?
|
31
|
+
@detect_nulls
|
25
32
|
end
|
26
33
|
|
34
|
+
# Adds a field to the graph type that is resolved to an attribute on the model.
|
35
|
+
# @param attribute Symbol with the name of the attribute on the model
|
36
|
+
# @param description Description for the field
|
37
|
+
# @param name Name of the field to use. By default, the attribute name is camelized.
|
38
|
+
# @param nullable Set to false to force the field to be non-null. By default, nullability is automatically detected.
|
39
|
+
# @param deprecation_reason Sets the deprecation reason on the field.
|
40
|
+
def attr(attribute, name: attribute.to_s.camelize(:lower), nullable: nil, description: nil, deprecation_reason: nil, &block)
|
41
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
42
|
+
|
43
|
+
options = {
|
44
|
+
name: name,
|
45
|
+
nullable: nullable,
|
46
|
+
description: description,
|
47
|
+
deprecation_reason: deprecation_reason
|
48
|
+
}
|
49
|
+
|
50
|
+
DefinitionHelpers.define_attribute(@graph_type, @base_model_type, @model_type, @path, attribute, @object_to_model, options, nullable, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Flattens an associated model into the graph type, allowing to you adds its attributes as if they existed on the parent model.
|
54
|
+
# @param association Name of the association to use. Polymorphic belongs_to associations are not supported.
|
27
55
|
def proxy_to(association, &block)
|
28
|
-
DefinitionHelpers.define_proxy(graph_type,
|
56
|
+
DefinitionHelpers.define_proxy(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, @detect_nulls, &block)
|
29
57
|
end
|
30
58
|
|
31
|
-
def has_one(association,
|
32
|
-
|
59
|
+
def has_one(association, name: association.to_s.camelize(:lower), nullable: nil, description: nil, deprecation_reason: nil)
|
60
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
61
|
+
|
62
|
+
options = {
|
63
|
+
name: name,
|
64
|
+
nullable: nullable,
|
65
|
+
description: description,
|
66
|
+
deprecation_reason: deprecation_reason
|
67
|
+
}
|
68
|
+
|
69
|
+
DefinitionHelpers.define_has_one(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, options, @detect_nulls)
|
33
70
|
end
|
34
71
|
|
35
|
-
def has_many_connection(association, **
|
36
|
-
|
72
|
+
def has_many_connection(association, name: association.to_s.camelize(:lower), nullable: nil, description: nil, deprecation_reason: nil, **goco_options)
|
73
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
74
|
+
|
75
|
+
options = goco_options.merge({
|
76
|
+
name: name,
|
77
|
+
nullable: nullable,
|
78
|
+
description: description,
|
79
|
+
deprecation_reason: deprecation_reason
|
80
|
+
})
|
81
|
+
|
82
|
+
DefinitionHelpers.define_has_many_connection(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, options, @detect_nulls)
|
37
83
|
end
|
38
84
|
|
39
|
-
def has_many_array(association,
|
40
|
-
|
85
|
+
def has_many_array(association, name: association.to_s.camelize(:lower), nullable: nil, description: nil, deprecation_reason: nil, type: nil)
|
86
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
87
|
+
|
88
|
+
options = {
|
89
|
+
name: name,
|
90
|
+
type: type,
|
91
|
+
nullable: nullable,
|
92
|
+
description: description,
|
93
|
+
deprecation_reason: deprecation_reason
|
94
|
+
}
|
95
|
+
|
96
|
+
DefinitionHelpers.define_has_many_array(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, options, @detect_nulls)
|
41
97
|
end
|
42
98
|
|
43
99
|
def field(*args, &block)
|
44
|
-
defined_field = GraphQL::Define::AssignObjectField.call(graph_type, *args, &block)
|
100
|
+
defined_field = GraphQL::Define::AssignObjectField.call(@graph_type, *args, &block)
|
101
|
+
name = defined_field.name
|
102
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
45
103
|
|
46
|
-
DefinitionHelpers.register_field_metadata(graph_type,
|
104
|
+
DefinitionHelpers.register_field_metadata(@graph_type, name, {
|
47
105
|
macro: :field,
|
48
106
|
macro_type: :custom,
|
49
|
-
path:
|
50
|
-
base_model_type: @
|
51
|
-
model_type: @model_type
|
52
|
-
object_to_base_model: object_to_model
|
107
|
+
path: @path,
|
108
|
+
base_model_type: @base_model_type,
|
109
|
+
model_type: @model_type,
|
110
|
+
object_to_base_model: @object_to_model
|
53
111
|
})
|
54
112
|
|
55
113
|
defined_field
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module GraphQL
|
2
|
+
module Models
|
3
|
+
module DatabaseTypes
|
4
|
+
TypeStruct = Struct.new(:input, :output)
|
5
|
+
|
6
|
+
def self.registered_type(database_type)
|
7
|
+
@registered_types ||= {}.with_indifferent_access
|
8
|
+
|
9
|
+
result = @registered_types[database_type]
|
10
|
+
return nil if result.nil?
|
11
|
+
|
12
|
+
if !result.input.is_a?(GraphQL::BaseType) || !result.output.is_a?(GraphQL::BaseType)
|
13
|
+
input = result.input
|
14
|
+
output = result.output
|
15
|
+
|
16
|
+
input = input.call if input.is_a?(Proc)
|
17
|
+
output = output.call if output.is_a?(Proc)
|
18
|
+
|
19
|
+
input = input.constantize if input.is_a?(String)
|
20
|
+
output = output.constantize if output.is_a?(String)
|
21
|
+
|
22
|
+
TypeStruct.new(input, output)
|
23
|
+
else
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.register(database_type, output_type, input_type = output_type)
|
29
|
+
@registered_types ||= {}.with_indifferent_access
|
30
|
+
@registered_types[database_type] = TypeStruct.new(input_type, output_type)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
DatabaseTypes.register(:boolean, GraphQL::BOOLEAN_TYPE)
|
35
|
+
DatabaseTypes.register(:integer, GraphQL::INT_TYPE)
|
36
|
+
DatabaseTypes.register(:float, GraphQL::FLOAT_TYPE)
|
37
|
+
DatabaseTypes.register(:string, GraphQL::STRING_TYPE)
|
38
|
+
end
|
39
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module GraphQL
|
2
2
|
module Models
|
3
3
|
module DefinitionHelpers
|
4
|
-
def self.define_proxy(graph_type, base_model_type, model_type, path, association, object_to_model, &block)
|
4
|
+
def self.define_proxy(graph_type, base_model_type, model_type, path, association, object_to_model, detect_nulls, &block)
|
5
5
|
reflection = model_type.reflect_on_association(association)
|
6
6
|
raise ArgumentError.new("Association #{association} wasn't found on model #{model_type.name}") unless reflection
|
7
7
|
raise ArgumentError.new("Cannot proxy to polymorphic association #{association} on model #{model_type.name}") if reflection.polymorphic?
|
@@ -9,7 +9,15 @@ module GraphQL
|
|
9
9
|
|
10
10
|
return unless block_given?
|
11
11
|
|
12
|
-
proxy =
|
12
|
+
proxy = BackedByModel.new(
|
13
|
+
graph_type,
|
14
|
+
reflection.klass,
|
15
|
+
base_model_type: base_model_type,
|
16
|
+
path: [*path, association],
|
17
|
+
object_to_model: object_to_model,
|
18
|
+
detect_nulls: detect_nulls && Reflection.is_required(model_type, association)
|
19
|
+
)
|
20
|
+
|
13
21
|
proxy.instance_exec(&block)
|
14
22
|
end
|
15
23
|
|
@@ -18,36 +26,32 @@ module GraphQL
|
|
18
26
|
## Ordinary has_one/belongs_to associations
|
19
27
|
############################################
|
20
28
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
## Polymorphic associations
|
25
|
-
############################################
|
26
|
-
|
27
|
-
# For polymorphic associations, we look for a validator that limits the types of entities that could be
|
28
|
-
# used, and use it to build a union. If we can't find one, raise an error.
|
29
|
+
if reflection.polymorphic?
|
30
|
+
# For polymorphic associations, we look for a validator that limits the types of entities that could be
|
31
|
+
# used, and use it to build a union. If we can't find one, raise an error.
|
29
32
|
|
30
|
-
|
31
|
-
|
33
|
+
model_type = reflection.active_record
|
34
|
+
valid_types = Reflection.possible_values(model_type, reflection.foreign_type)
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
if valid_types.blank?
|
37
|
+
fail ArgumentError.new("Cannot include polymorphic #{reflection.name} association on model #{model_type.name}, because it does not define an inclusion validator on #{reflection.foreign_type}")
|
38
|
+
end
|
36
39
|
|
37
|
-
|
38
|
-
graph_types = valid_types.map { |t| "#{t}Graph".safe_constantize }.compact
|
40
|
+
graph_types = valid_types.map { |t| GraphQL::Models.get_graphql_type(t) }.compact
|
39
41
|
|
40
42
|
GraphQL::UnionType.define do
|
41
43
|
name "#{model_type.name}#{reflection.foreign_type.classify}"
|
42
44
|
description "Objects that can be used as #{reflection.foreign_type.titleize.downcase} on #{model_type.name.titleize.downcase}"
|
43
45
|
possible_types graph_types
|
44
46
|
end
|
47
|
+
else
|
48
|
+
GraphQL::Models.get_graphql_type!(reflection.klass)
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
52
|
# Adds a field to the graph type which is resolved by accessing a has_one association on the model. Traverses
|
49
53
|
# across has_one associations specified in the path. The resolver returns a promise.
|
50
|
-
def self.define_has_one(graph_type, base_model_type, model_type, path, association, object_to_model, options)
|
54
|
+
def self.define_has_one(graph_type, base_model_type, model_type, path, association, object_to_model, options, detect_nulls)
|
51
55
|
reflection = model_type.reflect_on_association(association)
|
52
56
|
|
53
57
|
fail ArgumentError.new("Association #{association} wasn't found on model #{model_type.name}") unless reflection
|
@@ -55,10 +59,9 @@ module GraphQL
|
|
55
59
|
|
56
60
|
# Define the field for the association itself
|
57
61
|
|
58
|
-
camel_name = options[:name]
|
59
|
-
|
60
|
-
|
61
|
-
type_lambda = resolve_has_one_type(reflection)
|
62
|
+
camel_name = options[:name]
|
63
|
+
association_graphql_type = resolve_has_one_type(reflection)
|
64
|
+
association_graphql_type = resolve_nullability(association_graphql_type, model_type, association, detect_nulls, options)
|
62
65
|
|
63
66
|
DefinitionHelpers.register_field_metadata(graph_type, camel_name, {
|
64
67
|
macro: :has_one,
|
@@ -72,7 +75,7 @@ module GraphQL
|
|
72
75
|
|
73
76
|
graph_type.fields[camel_name.to_s] = GraphQL::Field.define do
|
74
77
|
name camel_name.to_s
|
75
|
-
type
|
78
|
+
type association_graphql_type
|
76
79
|
description options[:description] if options.include?(:description)
|
77
80
|
deprecation_reason options[:deprecation_reason] if options.include?(:deprecation_reason)
|
78
81
|
|
@@ -84,6 +87,7 @@ module GraphQL
|
|
84
87
|
|
85
88
|
# Define the field for the associated model's ID
|
86
89
|
id_field_name = :"#{camel_name}Id"
|
90
|
+
id_field_type = resolve_nullability(GraphQL::ID_TYPE, model_type, association, detect_nulls, options)
|
87
91
|
|
88
92
|
DefinitionHelpers.register_field_metadata(graph_type, id_field_name, {
|
89
93
|
macro: :has_one,
|
@@ -103,7 +107,7 @@ module GraphQL
|
|
103
107
|
|
104
108
|
graph_type.fields[id_field_name.to_s] = GraphQL::Field.define do
|
105
109
|
name id_field_name.to_s
|
106
|
-
type
|
110
|
+
type id_field_type
|
107
111
|
deprecation_reason options[:deprecation_reason] if options.include?(:deprecation_reason)
|
108
112
|
|
109
113
|
resolve -> (model, args, context) do
|
@@ -123,14 +127,29 @@ module GraphQL
|
|
123
127
|
end
|
124
128
|
end
|
125
129
|
|
126
|
-
def self.define_has_many_array(graph_type, base_model_type, model_type, path, association, object_to_model, options)
|
130
|
+
def self.define_has_many_array(graph_type, base_model_type, model_type, path, association, object_to_model, options, detect_nulls)
|
127
131
|
reflection = model_type.reflect_on_association(association)
|
128
132
|
|
129
133
|
fail ArgumentError.new("Association #{association} wasn't found on model #{model_type.name}") unless reflection
|
130
134
|
fail ArgumentError.new("Cannot include #{reflection.macro} association #{association} on model #{model_type.name} with has_many_array") unless [:has_many].include?(reflection.macro)
|
131
135
|
|
132
|
-
|
133
|
-
|
136
|
+
association_type = options[:type] || GraphQL::Models.get_graphql_type!(reflection.klass)
|
137
|
+
|
138
|
+
if !association_type.is_a?(GraphQL::ListType)
|
139
|
+
association_type = association_type.to_non_null_type.to_list_type
|
140
|
+
end
|
141
|
+
|
142
|
+
id_field_type = GraphQL::ID_TYPE.to_non_null_type.to_list_type
|
143
|
+
|
144
|
+
# The has_many associations are a little special. Instead of checking for a presence validator, we instead assume
|
145
|
+
# that the outer type should be non-null, unless detect_nulls is false. In other words, we prefer an empty
|
146
|
+
# array for the association, rather than null.
|
147
|
+
if (options[:nullable] == nil && detect_nulls) || options[:nullable] == false
|
148
|
+
association_type = association_type.to_non_null_type
|
149
|
+
id_field_type = id_field_type.to_non_null_type
|
150
|
+
end
|
151
|
+
|
152
|
+
camel_name = options[:name]
|
134
153
|
|
135
154
|
DefinitionHelpers.register_field_metadata(graph_type, camel_name, {
|
136
155
|
macro: :has_many_array,
|
@@ -144,7 +163,7 @@ module GraphQL
|
|
144
163
|
|
145
164
|
graph_type.fields[camel_name.to_s] = GraphQL::Field.define do
|
146
165
|
name camel_name.to_s
|
147
|
-
type
|
166
|
+
type association_type
|
148
167
|
description options[:description] if options.include?(:description)
|
149
168
|
deprecation_reason options[:deprecation_reason] if options.include?(:deprecation_reason)
|
150
169
|
|
@@ -171,7 +190,7 @@ module GraphQL
|
|
171
190
|
|
172
191
|
graph_type.fields[id_field_name.to_s] = GraphQL::Field.define do
|
173
192
|
name id_field_name.to_s
|
174
|
-
type
|
193
|
+
type id_field_type
|
175
194
|
deprecation_reason options[:deprecation_reason] if options.include?(:deprecation_reason)
|
176
195
|
|
177
196
|
resolve -> (model, args, context) do
|
@@ -183,14 +202,19 @@ module GraphQL
|
|
183
202
|
end
|
184
203
|
end
|
185
204
|
|
186
|
-
def self.define_has_many_connection(graph_type, base_model_type, model_type, path, association, object_to_model, options)
|
205
|
+
def self.define_has_many_connection(graph_type, base_model_type, model_type, path, association, object_to_model, options, detect_nulls)
|
187
206
|
reflection = model_type.reflect_on_association(association)
|
188
207
|
|
189
208
|
fail ArgumentError.new("Association #{association} wasn't found on model #{model_type.name}") unless reflection
|
190
209
|
fail ArgumentError.new("Cannot include #{reflection.macro} association #{association} on model #{model_type.name} with has_many_connection") unless [:has_many].include?(reflection.macro)
|
191
210
|
|
192
|
-
|
193
|
-
|
211
|
+
connection_type = GraphQL::Models.get_graphql_type!(reflection.klass).connection_type
|
212
|
+
|
213
|
+
if (options[:nullable] == nil && detect_nulls) || options[:nullable] == false
|
214
|
+
connection_type = connection_type.to_non_null_type
|
215
|
+
end
|
216
|
+
|
217
|
+
camel_name = options[:name]
|
194
218
|
|
195
219
|
DefinitionHelpers.register_field_metadata(graph_type, camel_name, {
|
196
220
|
macro: :has_many_connection,
|
@@ -202,12 +226,20 @@ module GraphQL
|
|
202
226
|
object_to_base_model: object_to_model
|
203
227
|
})
|
204
228
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
229
|
+
# TODO: Figure out a way to remove this from the gem. It's only applicable to GoCo's codebase.
|
230
|
+
if Object.const_defined?('GraphSupport') && GraphSupport.respond_to?(:secure)
|
231
|
+
GraphQL::Define::AssignConnection.call(graph_type, camel_name, connection_type) do
|
232
|
+
resolve -> (model, args, context) do
|
233
|
+
return nil unless model
|
234
|
+
GraphSupport.secure(model.public_send(association), context, permission: options[:permission] || :read)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
else
|
238
|
+
GraphQL::Define::AssignConnection.call(graph_type, camel_name, connection_type) do
|
239
|
+
resolve -> (model, args, context) do
|
240
|
+
return nil unless model
|
241
|
+
model.public_send(association)
|
242
|
+
end
|
211
243
|
end
|
212
244
|
end
|
213
245
|
end
|
@@ -1,104 +1,50 @@
|
|
1
1
|
module GraphQL
|
2
2
|
module Models
|
3
3
|
module DefinitionHelpers
|
4
|
-
def self.
|
5
|
-
|
6
|
-
if
|
7
|
-
|
4
|
+
def self.resolve_nullability(graphql_type, model_class, attribute_or_association, detect_nulls, options)
|
5
|
+
# If detect_nulls is true, it means that everything on the path (ie, between base_model_class and model_class) is non null.
|
6
|
+
# So for example, if we're five levels deep inside of proxy_to blocks, but every single association along the way has
|
7
|
+
# a presence validator, then `detect_nulls` is false. Thus, we can take it one step further and enforce nullability on the
|
8
|
+
# attribute itself.
|
9
|
+
nullable = options[:nullable]
|
10
|
+
|
11
|
+
if nullable == nil
|
12
|
+
nullable = !(detect_nulls && Reflection.is_required(model_class, attribute_or_association))
|
8
13
|
end
|
9
14
|
|
10
|
-
|
11
|
-
|
12
|
-
types.Boolean
|
13
|
-
when :integer
|
14
|
-
types.Int
|
15
|
-
when :float
|
16
|
-
types.Float
|
17
|
-
when :daterange
|
18
|
-
inner_type = type_to_graphql_type(:date)
|
19
|
-
types[!inner_type]
|
20
|
-
when :tsrange
|
21
|
-
inner_type = type_to_graphql_type(:datetime)
|
22
|
-
types[!inner_type]
|
15
|
+
if nullable == false
|
16
|
+
graphql_type = graphql_type.to_non_null_type
|
23
17
|
else
|
24
|
-
|
18
|
+
graphql_type
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
28
|
-
def self.
|
29
|
-
|
30
|
-
|
22
|
+
def self.define_attribute(graph_type, base_model_class, model_class, path, attribute, object_to_model, options, detect_nulls, &block)
|
23
|
+
attribute_graphql_type = Reflection.attribute_graphql_type(model_class, attribute).output
|
24
|
+
attribute_graphql_type = resolve_nullability(attribute_graphql_type, model_class, attribute, detect_nulls, options)
|
31
25
|
|
32
|
-
|
33
|
-
graphql_type = model_type.graphql_enum_types[name]
|
34
|
-
else
|
35
|
-
graphql_type = type_to_graphql_type(col.type)
|
36
|
-
end
|
37
|
-
|
38
|
-
if col.array
|
39
|
-
graphql_type = types[graphql_type]
|
40
|
-
end
|
41
|
-
|
42
|
-
return OpenStruct.new({
|
43
|
-
is_range: /range\z/ === col.type.to_s,
|
44
|
-
camel_name: name.to_s.camelize(:lower).to_sym,
|
45
|
-
graphql_type: graphql_type,
|
46
|
-
nullable: col.null
|
47
|
-
})
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.get_column!(model_type, name)
|
51
|
-
col = get_column(model_type, name)
|
52
|
-
raise ArgumentError.new("The attribute #{name} wasn't found on model #{model_type.name}.") unless col
|
53
|
-
col
|
54
|
-
end
|
55
|
-
|
56
|
-
def self.range_to_graphql(value)
|
57
|
-
return nil unless value
|
58
|
-
|
59
|
-
begin
|
60
|
-
[value.first, value.last_included]
|
61
|
-
rescue TypeError
|
62
|
-
[value.first, value.last]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Adds a field to the graph type which is resolved by accessing an attribute on the model. Traverses
|
67
|
-
# across has_one associations specified in the path. The resolver returns a promise.
|
68
|
-
# @param graph_type The GraphQL::ObjectType that the field is being added to
|
69
|
-
# @param model_type The class object for the model that defines the attribute
|
70
|
-
# @param path The associations (in order) that need to be loaded, starting from the graph_type's model
|
71
|
-
# @param attribute The name of the attribute that is accessed on the target model_type
|
72
|
-
def self.define_attribute(graph_type, base_model_type, model_type, path, attribute, object_to_model, options, &block)
|
73
|
-
column = get_column!(model_type, attribute)
|
74
|
-
field_name = options[:name] || column.camel_name
|
26
|
+
field_name = options[:name]
|
75
27
|
|
76
28
|
DefinitionHelpers.register_field_metadata(graph_type, field_name, {
|
77
29
|
macro: :attr,
|
78
30
|
macro_type: :attribute,
|
79
31
|
path: path,
|
80
32
|
attribute: attribute,
|
81
|
-
|
82
|
-
|
33
|
+
base_model_class: base_model_class,
|
34
|
+
model_class: model_class,
|
83
35
|
object_to_base_model: object_to_model
|
84
36
|
})
|
85
37
|
|
86
38
|
graph_type.fields[field_name.to_s] = GraphQL::Field.define do
|
87
39
|
name field_name.to_s
|
88
|
-
type
|
40
|
+
type attribute_graphql_type
|
89
41
|
description options[:description] if options.include?(:description)
|
90
42
|
deprecation_reason options[:deprecation_reason] if options.include?(:deprecation_reason)
|
91
43
|
|
92
44
|
resolve -> (model, args, context) do
|
93
|
-
|
94
|
-
|
95
|
-
if column.is_range
|
96
|
-
DefinitionHelpers.range_to_graphql(model.public_send(attribute))
|
97
|
-
else
|
98
|
-
model.public_send(attribute)
|
99
|
-
end
|
45
|
+
model&.public_send(attribute)
|
100
46
|
end
|
101
|
-
|
47
|
+
|
102
48
|
instance_exec(&block) if block
|
103
49
|
end
|
104
50
|
end
|
@@ -117,32 +117,6 @@ module GraphQL
|
|
117
117
|
return model
|
118
118
|
end
|
119
119
|
|
120
|
-
# Detects the values that are valid for an attribute by looking at the inclusion validators
|
121
|
-
def self.detect_inclusion_values(model_type, attribute)
|
122
|
-
# Get all of the inclusion validators
|
123
|
-
validators = model_type.validators_on(attribute).select { |v| v.is_a?(ActiveModel::Validations::InclusionValidator) }
|
124
|
-
|
125
|
-
# Ignore any inclusion validators that are using the 'if' or 'unless' options
|
126
|
-
validators = validators.reject { |v| v.options.include?(:if) || v.options.include?(:unless) || v.options[:in].blank? }
|
127
|
-
return nil unless validators.any?
|
128
|
-
return validators.map { |v| v.options[:in] }.reduce(:&)
|
129
|
-
end
|
130
|
-
|
131
|
-
def self.detect_is_required(model_type, attr_or_assoc)
|
132
|
-
col = model_type.columns.detect { |c| c.name == attr_or_assoc.to_s }
|
133
|
-
return true if col && !col.null
|
134
|
-
|
135
|
-
validators = model_type.validators_on(attr_or_assoc)
|
136
|
-
.select { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) }
|
137
|
-
.reject { |v| v.options.include?(:if) || v.options.include?(:unless) }
|
138
|
-
|
139
|
-
return true if validators.any?
|
140
|
-
|
141
|
-
# The column is nullable, and there are no unconditional presence validators,
|
142
|
-
# so it's at least sometimes optional
|
143
|
-
false
|
144
|
-
end
|
145
|
-
|
146
120
|
# Stores metadata about GraphQL fields that are available on this model's GraphQL type.
|
147
121
|
# @param metadata Should be a hash that contains information about the field's definition, including :macro and :type
|
148
122
|
def self.register_field_metadata(graph_type, field_name, metadata)
|
@@ -23,31 +23,23 @@ module GraphQL::Models
|
|
23
23
|
GraphQL::Define::TypeDefiner.instance
|
24
24
|
end
|
25
25
|
|
26
|
-
def attr(attribute, type: nil, name: nil, required:
|
26
|
+
def attr(attribute, type: nil, name: nil, required: nil)
|
27
27
|
attribute = attribute.to_sym if attribute.is_a?(String)
|
28
28
|
|
29
29
|
if type.nil? && !model_type
|
30
30
|
fail ArgumentError.new("You must specify a type for attribute #{name}, because its model type is not known until runtime.")
|
31
31
|
end
|
32
32
|
|
33
|
-
if
|
34
|
-
|
35
|
-
|
36
|
-
if column.nil? && type.nil?
|
37
|
-
fail ArgumentError.new("You must specify a type for attribute #{name}, because it's not a column on #{model_type}.")
|
38
|
-
end
|
33
|
+
if type.nil? && (attribute == :id || foreign_keys.include?(attribute))
|
34
|
+
type = types.ID
|
35
|
+
end
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
type = types.ID
|
44
|
-
else
|
45
|
-
type = column.graphql_type
|
46
|
-
end
|
47
|
-
end
|
37
|
+
if type.nil? && model_type
|
38
|
+
type = Reflection.attribute_graphql_type(model_type, attribute).input
|
39
|
+
end
|
48
40
|
|
49
|
-
|
50
|
-
|
41
|
+
if required.nil?
|
42
|
+
required = model_type ? Reflection.is_required(model_type, attribute) : false
|
51
43
|
end
|
52
44
|
|
53
45
|
name ||= attribute.to_s.camelize(:lower)
|
@@ -118,7 +110,7 @@ module GraphQL::Models
|
|
118
110
|
end
|
119
111
|
|
120
112
|
has_many = reflection.macro == :has_many
|
121
|
-
required =
|
113
|
+
required = Reflection.is_required(model_type, association)
|
122
114
|
|
123
115
|
map = MutationFieldMap.new(reflection.klass, find_by: find_by, null_behavior: null_behavior)
|
124
116
|
map.name = name || association.to_s.camelize(:lower)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Exposes utility methods for getting metadata out of active record models
|
2
|
+
module GraphQL::Models
|
3
|
+
module Reflection
|
4
|
+
class << self
|
5
|
+
# Returns the possible values for an attribute on a model by examining inclusion validators
|
6
|
+
def possible_values(model_class, attribute)
|
7
|
+
# Get all of the inclusion validators
|
8
|
+
validators = model_class.validators_on(attribute).select { |v| v.is_a?(ActiveModel::Validations::InclusionValidator) }
|
9
|
+
|
10
|
+
# Ignore any inclusion validators that are using the 'if' or 'unless' options
|
11
|
+
validators = validators.reject { |v| v.options.include?(:if) || v.options.include?(:unless) || v.options[:in].blank? }
|
12
|
+
return nil unless validators.any?
|
13
|
+
return validators.map { |v| v.options[:in] }.reduce(:&)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Determines if the attribute (or association) is required by examining presence validators
|
17
|
+
# and the nullability of the column in the database
|
18
|
+
def is_required(model_class, attr_or_assoc)
|
19
|
+
return true if model_class.columns_hash[attr_or_assoc.to_s]&.null == false
|
20
|
+
|
21
|
+
model_class.validators_on(attr_or_assoc)
|
22
|
+
.select { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) }
|
23
|
+
.reject { |v| v.options.include?(:if) || v.options.include?(:unless) }
|
24
|
+
.any?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a struct that tells you the input and output GraphQL types for an attribute
|
28
|
+
def attribute_graphql_type(model_class, attribute)
|
29
|
+
# See if it's an enum
|
30
|
+
if model_class.graphql_enum_types.include?(attribute)
|
31
|
+
type = model_class.graphql_enum_types[attribute]
|
32
|
+
DatabaseTypes::TypeStruct.new(type, type)
|
33
|
+
else
|
34
|
+
# See if it's a registered scalar type
|
35
|
+
active_record_type = model_class.type_for_attribute(attribute.to_s)
|
36
|
+
|
37
|
+
if active_record_type.type.nil?
|
38
|
+
fail ArgumentError, "The type for attribute #{attribute} wasn't found on #{model_class.name}"
|
39
|
+
end
|
40
|
+
|
41
|
+
result = DatabaseTypes.registered_type(active_record_type.type)
|
42
|
+
|
43
|
+
if !result
|
44
|
+
fail RuntimeError, "The type #{active_record_type} is not registered with DatabaseTypes (attribute #{attribute} on #{model_class.name})"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Arrays: Rails doesn't have a generalized way to detect arrays, so we use this method to do it:
|
48
|
+
if active_record_type.class.name.ends_with?('Array')
|
49
|
+
DatabaseTypes::TypeStruct.new(result.input.to_list_type, result.output.to_list_type)
|
50
|
+
else
|
51
|
+
result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0.pre.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Foster
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- lib/graphql/models/association_load_request.rb
|
177
177
|
- lib/graphql/models/attribute_loader.rb
|
178
178
|
- lib/graphql/models/backed_by_model.rb
|
179
|
+
- lib/graphql/models/database_types.rb
|
179
180
|
- lib/graphql/models/definer.rb
|
180
181
|
- lib/graphql/models/definition_helpers.rb
|
181
182
|
- lib/graphql/models/definition_helpers/associations.rb
|
@@ -191,12 +192,10 @@ files:
|
|
191
192
|
- lib/graphql/models/mutation_helpers/validation.rb
|
192
193
|
- lib/graphql/models/mutation_helpers/validation_error.rb
|
193
194
|
- lib/graphql/models/mutator.rb
|
194
|
-
- lib/graphql/models/object_type.rb
|
195
195
|
- lib/graphql/models/promise_relation_connection.rb
|
196
|
-
- lib/graphql/models/
|
196
|
+
- lib/graphql/models/reflection.rb
|
197
197
|
- lib/graphql/models/relation_load_request.rb
|
198
198
|
- lib/graphql/models/relation_loader.rb
|
199
|
-
- lib/graphql/models/scalar_types.rb
|
200
199
|
- lib/graphql/models/version.rb
|
201
200
|
homepage: http://github.com/goco-inc/graphql-activerecord
|
202
201
|
licenses:
|
@@ -213,9 +212,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
213
212
|
version: '0'
|
214
213
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
215
214
|
requirements:
|
216
|
-
- - "
|
215
|
+
- - ">"
|
217
216
|
- !ruby/object:Gem::Version
|
218
|
-
version:
|
217
|
+
version: 1.3.1
|
219
218
|
requirements: []
|
220
219
|
rubyforge_project:
|
221
220
|
rubygems_version: 2.4.8
|
@@ -1,120 +0,0 @@
|
|
1
|
-
module GraphQL
|
2
|
-
module Models
|
3
|
-
module ObjectType
|
4
|
-
class << self
|
5
|
-
DEFAULT_OBJECT_TO_MODEL = -> (object) { object }
|
6
|
-
|
7
|
-
def object_to_model(graph_type, model_proc)
|
8
|
-
graph_type.instance_variable_set(:@unscoped_object_to_model, model_proc)
|
9
|
-
end
|
10
|
-
|
11
|
-
def model_type(graph_type, model_type)
|
12
|
-
model_type = model_type.to_s.classify.constantize unless model_type.is_a?(Class)
|
13
|
-
|
14
|
-
object_to_model = -> (object) do
|
15
|
-
model_proc = graph_type.instance_variable_get(:@unscoped_object_to_model)
|
16
|
-
if model_proc
|
17
|
-
model_proc.call(object)
|
18
|
-
else
|
19
|
-
DEFAULT_OBJECT_TO_MODEL.call(object)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
graph_type.instance_variable_set(:@unscoped_model_type, model_type)
|
24
|
-
|
25
|
-
graph_type.fields['id'] = GraphQL::Field.define do
|
26
|
-
name 'id'
|
27
|
-
type !types.ID
|
28
|
-
resolve -> (object, args, context) { object.gid }
|
29
|
-
end
|
30
|
-
|
31
|
-
if GraphQL::Models.node_interface_proc
|
32
|
-
node_interface = GraphQL::Models.node_interface_proc.call
|
33
|
-
graph_type.interfaces = [*graph_type.interfaces, node_interface].uniq
|
34
|
-
end
|
35
|
-
|
36
|
-
graph_type.fields['rid'] = GraphQL::Field.define do
|
37
|
-
name 'rid'
|
38
|
-
type !types.String
|
39
|
-
resolve -> (object, args, context) do
|
40
|
-
model = object_to_model.call(object)
|
41
|
-
model.id
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
graph_type.fields['rtype'] = GraphQL::Field.define do
|
46
|
-
name 'rtype'
|
47
|
-
type !types.String
|
48
|
-
resolve -> (object, args, context) do
|
49
|
-
model = object_to_model.call(object)
|
50
|
-
model.class.name
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
if model_type.columns.detect { |c| c.name == 'created_at'}
|
55
|
-
DefinitionHelpers.define_attribute(graph_type, model_type, model_type, [], :created_at, object_to_model, {})
|
56
|
-
end
|
57
|
-
|
58
|
-
if model_type.columns.detect { |c| c.name == 'updated_at'}
|
59
|
-
DefinitionHelpers.define_attribute(graph_type, model_type, model_type, [], :updated_at, object_to_model, {})
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def proxy_to(graph_type, association, &block)
|
64
|
-
ensure_has_model_type(graph_type, __method__)
|
65
|
-
object_to_model = graph_type.instance_variable_get(:@unscoped_object_to_model) || DEFAULT_OBJECT_TO_MODEL
|
66
|
-
DefinitionHelpers.define_proxy(graph_type, resolve_model_type(graph_type), resolve_model_type(graph_type), [], association, object_to_model, &block)
|
67
|
-
end
|
68
|
-
|
69
|
-
def attr(graph_type, name, **options, &block)
|
70
|
-
ensure_has_model_type(graph_type, __method__)
|
71
|
-
object_to_model = graph_type.instance_variable_get(:@unscoped_object_to_model) || DEFAULT_OBJECT_TO_MODEL
|
72
|
-
DefinitionHelpers.define_attribute(graph_type, resolve_model_type(graph_type), resolve_model_type(graph_type), [], name, object_to_model, options, &block)
|
73
|
-
end
|
74
|
-
|
75
|
-
def has_one(graph_type, association, **options)
|
76
|
-
ensure_has_model_type(graph_type, __method__)
|
77
|
-
object_to_model = graph_type.instance_variable_get(:@unscoped_object_to_model) || DEFAULT_OBJECT_TO_MODEL
|
78
|
-
DefinitionHelpers.define_has_one(graph_type, resolve_model_type(graph_type), resolve_model_type(graph_type), [], association, object_to_model, options)
|
79
|
-
end
|
80
|
-
|
81
|
-
def has_many_connection(graph_type, association, **options)
|
82
|
-
ensure_has_model_type(graph_type, __method__)
|
83
|
-
object_to_model = graph_type.instance_variable_get(:@unscoped_object_to_model) || DEFAULT_OBJECT_TO_MODEL
|
84
|
-
DefinitionHelpers.define_has_many_connection(graph_type, resolve_model_type(graph_type), resolve_model_type(graph_type), [], association, object_to_model, options)
|
85
|
-
end
|
86
|
-
|
87
|
-
def has_many_array(graph_type, association, **options)
|
88
|
-
ensure_has_model_type(graph_type, __method__)
|
89
|
-
object_to_model = graph_type.instance_variable_get(:@unscoped_object_to_model) || DEFAULT_OBJECT_TO_MODEL
|
90
|
-
DefinitionHelpers.define_has_many_array(graph_type, resolve_model_type(graph_type), resolve_model_type(graph_type), [], association, object_to_model, options)
|
91
|
-
end
|
92
|
-
|
93
|
-
def backed_by_model(graph_type, model_type, &block)
|
94
|
-
model_type = model_type.to_s.classify.constantize unless model_type.is_a?(Class)
|
95
|
-
|
96
|
-
backer = GraphQL::Models::BackedByModel.new(graph_type, model_type)
|
97
|
-
backer.instance_exec(&block)
|
98
|
-
end
|
99
|
-
|
100
|
-
private
|
101
|
-
|
102
|
-
def resolve_model_type(graph_type)
|
103
|
-
graph_type.instance_variable_get(:@unscoped_model_type)
|
104
|
-
end
|
105
|
-
|
106
|
-
def ensure_has_model_type(graph_type, method)
|
107
|
-
fail RuntimeError.new("You must call model_type before using the #{method} method.") unless graph_type.instance_variable_get(:@unscoped_model_type)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Attach the methods to ObjectType
|
112
|
-
extensions = ObjectType.methods(false).reduce({}) do |memo, method|
|
113
|
-
memo[method] = ObjectType.method(method)
|
114
|
-
memo
|
115
|
-
end
|
116
|
-
|
117
|
-
GraphQL::ObjectType.accepts_definitions(extensions)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module GraphQL
|
2
|
-
module Models
|
3
|
-
class ProxyBlock
|
4
|
-
def initialize(graph_type, base_model_type, model_type, path, object_to_model)
|
5
|
-
@path = path
|
6
|
-
@base_model_type = base_model_type
|
7
|
-
@model_type = model_type
|
8
|
-
@graph_type = graph_type
|
9
|
-
@object_to_model = object_to_model
|
10
|
-
end
|
11
|
-
|
12
|
-
def types
|
13
|
-
GraphQL::Define::TypeDefiner.instance
|
14
|
-
end
|
15
|
-
|
16
|
-
def attr(name, **options, &block)
|
17
|
-
DefinitionHelpers.define_attribute(@graph_type, @base_model_type, @model_type, @path, name, @object_to_model, options, &block)
|
18
|
-
end
|
19
|
-
|
20
|
-
def proxy_to(association, &block)
|
21
|
-
DefinitionHelpers.define_proxy(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, &block)
|
22
|
-
end
|
23
|
-
|
24
|
-
def has_one(association, **options)
|
25
|
-
DefinitionHelpers.define_has_one(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, options)
|
26
|
-
end
|
27
|
-
|
28
|
-
def has_many_connection(association, **options)
|
29
|
-
DefinitionHelpers.define_has_many_connection(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, options)
|
30
|
-
end
|
31
|
-
|
32
|
-
def has_many_array(association, **options)
|
33
|
-
DefinitionHelpers.define_has_many_array(@graph_type, @base_model_type, @model_type, @path, association, @object_to_model, options)
|
34
|
-
end
|
35
|
-
|
36
|
-
def field(*args, &block)
|
37
|
-
defined_field = GraphQL::Define::AssignObjectField.call(@graph_type, *args, &block)
|
38
|
-
|
39
|
-
DefinitionHelpers.register_field_metadata(@graph_type, defined_field.name, {
|
40
|
-
macro: :field,
|
41
|
-
macro_type: :custom,
|
42
|
-
path: @path,
|
43
|
-
base_model_type: @base_model_type,
|
44
|
-
model_type: @model_type,
|
45
|
-
object_to_base_model: @object_to_model
|
46
|
-
})
|
47
|
-
|
48
|
-
defined_field
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module GraphQL
|
2
|
-
module Models
|
3
|
-
module ScalarTypes
|
4
|
-
def self.registered_type(database_type)
|
5
|
-
@registered_types ||= {}.with_indifferent_access
|
6
|
-
@registered_types[database_type]
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.register(database_type, graphql_type)
|
10
|
-
@registered_types ||= {}.with_indifferent_access
|
11
|
-
@registered_types[database_type] = graphql_type
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|