Skip to content

Commit 87db4e3

Browse files
author
Robert Mosolgo
authored
Merge pull request #1810 from justisb/parse-type
Improve field type string-to-constant resolution
2 parents 6a30ba3 + 1549663 commit 87db4e3

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

lib/graphql/schema/member/build_type.rb

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def parse_type(type_expr, null:)
3333
null = false
3434
parse_type(type_expr[0..-2], null: true)
3535
else
36-
maybe_type = Object.const_get(type_expr)
36+
maybe_type = constantize(type_expr)
3737
case maybe_type
3838
when GraphQL::BaseType
3939
maybe_type
@@ -125,6 +125,38 @@ def camelize(string)
125125
camelized
126126
end
127127

128+
# Resolves constant from string (based on Rails `ActiveSupport::Inflector.constantize`)
129+
def constantize(string)
130+
names = string.split('::')
131+
132+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
133+
Object.const_get(string) if names.empty?
134+
135+
# Remove the first blank element in case of '::ClassName' notation.
136+
names.shift if names.size > 1 && names.first.empty?
137+
138+
names.inject(Object) do |constant, name|
139+
if constant == Object
140+
constant.const_get(name)
141+
else
142+
candidate = constant.const_get(name)
143+
next candidate if constant.const_defined?(name, false)
144+
next candidate unless Object.const_defined?(name)
145+
146+
# Go down the ancestors to check if it is owned directly. The check
147+
# stops when we reach Object or the end of ancestors tree.
148+
constant = constant.ancestors.inject do |const, ancestor|
149+
break const if ancestor == Object
150+
break ancestor if ancestor.const_defined?(name, false)
151+
const
152+
end
153+
154+
# Owner is in Object, so raise.
155+
constant.const_get(name, false)
156+
end
157+
end
158+
end
159+
128160
def underscore(string)
129161
string
130162
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder

spec/graphql/schema/member/build_type_spec.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,52 @@
22
require "spec_helper"
33

44
describe GraphQL::Schema::Member::BuildType do
5+
describe ".parse_type" do
6+
it "resolves a string type from a string" do
7+
assert_equal GraphQL::Types::String, GraphQL::Schema::Member::BuildType.parse_type("String", null: true)
8+
end
9+
10+
it "resolves an integer type from a string" do
11+
assert_equal GraphQL::Types::Int, GraphQL::Schema::Member::BuildType.parse_type("Integer", null: true)
12+
end
13+
14+
it "resolves a float type from a string" do
15+
assert_equal GraphQL::Types::Float, GraphQL::Schema::Member::BuildType.parse_type("Float", null: true)
16+
end
17+
18+
it "resolves a boolean type from a string" do
19+
assert_equal GraphQL::Types::Boolean, GraphQL::Schema::Member::BuildType.parse_type("Boolean", null: true)
20+
end
21+
22+
it "resolves an interface type from a string" do
23+
assert_equal Jazz::BaseInterface, GraphQL::Schema::Member::BuildType.parse_type("Jazz::BaseInterface", null: true)
24+
end
25+
26+
it "resolves an object type from a class" do
27+
assert_equal Jazz::BaseObject, GraphQL::Schema::Member::BuildType.parse_type(Jazz::BaseObject, null: true)
28+
end
29+
30+
it "resolves an object type from a string" do
31+
assert_equal Jazz::BaseObject, GraphQL::Schema::Member::BuildType.parse_type("Jazz::BaseObject", null: true)
32+
end
33+
34+
it "resolves a nested object type from a string" do
35+
assert_equal Jazz::Introspection::NestedType, GraphQL::Schema::Member::BuildType.parse_type("Jazz::Introspection::NestedType", null: true)
36+
end
37+
38+
it "resolves a deeply nested object type from a string" do
39+
assert_equal Jazz::Introspection::NestedType::DeeplyNestedType, GraphQL::Schema::Member::BuildType.parse_type("Jazz::Introspection::NestedType::DeeplyNestedType", null: true)
40+
end
41+
42+
it "resolves a list type from an array of classes" do
43+
assert_instance_of GraphQL::Schema::List, GraphQL::Schema::Member::BuildType.parse_type([Jazz::BaseObject], null: true)
44+
end
45+
46+
it "resolves a list type from an array of strings" do
47+
assert_instance_of GraphQL::Schema::List, GraphQL::Schema::Member::BuildType.parse_type(["Jazz::BaseObject"], null: true)
48+
end
49+
end
50+
551
describe ".to_type_name" do
652
it "works with lists and non-nulls" do
753
t = Class.new(GraphQL::Schema::Object) do

spec/support/jazz.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,18 @@ def name
637637
end
638638
end
639639

640+
class NestedType < GraphQL::Introspection::TypeType
641+
def name
642+
object.name.upcase
643+
end
644+
645+
class DeeplyNestedType < GraphQL::Introspection::TypeType
646+
def name
647+
object.name.upcase
648+
end
649+
end
650+
end
651+
640652
class SchemaType < GraphQL::Introspection::SchemaType
641653
graphql_name "__Schema"
642654

0 commit comments

Comments
 (0)