graphql-activerecord 0.9.1 → 0.10.0.pre.alpha1
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/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
|