diff --git a/Gemfile b/Gemfile index fa75df1..4196d04 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ source 'https://rubygems.org' gemspec +gem "graphql", github: "rmosolgo/graphql-ruby", branch: "1.9-dev" +gem "graphql-client", github: "github/graphql-client", branch: "support-1.9-dev" diff --git a/lib/graphql/relay/walker/query_builder.rb b/lib/graphql/relay/walker/query_builder.rb index cf34b59..ec2a268 100644 --- a/lib/graphql/relay/walker/query_builder.rb +++ b/lib/graphql/relay/walker/query_builder.rb @@ -58,27 +58,6 @@ module GraphQL::Relay::Walker true end - # Private: Make a AST of the given type. - # - # klass - The GraphQL::Language::Nodes::AbstractNode subclass - # to create. - # needs_selections: - Boolean. Will this AST be invalid if it doesn't have - # any selections? - # - # Returns a GraphQL::Language::Nodes::AbstractNode subclass instance or nil - # if the created AST was invalid for having no selections. - def make(klass, needs_selections: true) - k_ast = klass.new - yield(k_ast) if block_given? - k_ast.selections.compact! - - if k_ast.selections.empty? && needs_selections - nil - else - k_ast - end - end - # Make an inline fragment AST. # # type - The GraphQL::ObjectType instance to make the fragment @@ -89,22 +68,24 @@ module GraphQL::Relay::Walker # Returns a GraphQL::Language::Nodes::InlineFragment instance or nil if the # created AST was invalid for having no selections. def inline_fragment_ast(type, with_children: true) - make(GraphQL::Language::Nodes::InlineFragment) do |if_ast| - if_ast.type = make_type_name_node(type.name) - - if with_children - type.all_fields.each do |field| - field_type = field.type.unwrap - if node_field?(field) && include?(field_type) - if_ast.selections << node_field_ast(field) - elsif connection_field?(field) && include?(field_type) - if_ast.selections << connection_field_ast(field) - end + selections = [] + if with_children + type.all_fields.each do |field| + field_type = field.type.unwrap + if node_field?(field) && include?(field_type) + selections << node_field_ast(field) + elsif connection_field?(field) && include?(field_type) + selections << connection_field_ast(field) end - elsif id = type.get_field('id') - if_ast.selections << field_ast(id) end + elsif id = type.get_field('id') + selections << field_ast(id) end + + GraphQL::Language::Nodes::InlineFragment.new( + type: make_type_name_node(type.name), + selections: selections, + ) end # Make a field AST. @@ -126,15 +107,12 @@ module GraphQL::Relay::Walker arguments.key?(name) end - make(GraphQL::Language::Nodes::Field, needs_selections: !type.kind.scalar?) do |f_ast| - f_ast.name = field.name - f_ast.alias = random_alias unless field.name == 'id' - f_ast.arguments = arguments.map do |name, value| - GraphQL::Language::Nodes::Argument.new(name: name, value: value) - end - - yield(f_ast, type) if blk + f_alias = field.name == 'id' ? nil : random_alias + f_args = arguments.map do |name, value| + GraphQL::Language::Nodes::Argument.new(name: name, value: value) end + + GraphQL::Language::Nodes::Field.new(name: field.name, alias: f_alias, arguments: f_args) end # Make a field AST for a node field. @@ -143,17 +121,19 @@ module GraphQL::Relay::Walker # # Returns a GraphQL::Language::Nodes::Field instance. def node_field_ast(field) - field_ast(field) do |f_ast, type| - selections = f_ast.selections + f_ast = field_ast(field) + type = field.type.unwrap + selections = f_ast.selections - if type.kind.object? - selections << field_ast(type.get_field('id')) - else - possible_node_types(type).each do |if_type| - selections << inline_fragment_ast(if_type, with_children: false) - end + if type.kind.object? + selections << field_ast(type.get_field('id')) + else + possible_node_types(type).each do |if_type| + selections << inline_fragment_ast(if_type, with_children: false) end end + f_ast = f_ast.merge(selections: selections) + f_ast end # Make a field AST for an edges field. @@ -162,9 +142,10 @@ module GraphQL::Relay::Walker # # Returns a GraphQL::Language::Nodes::Field instance. def edges_field_ast(field) - field_ast(field) do |f_ast, type| - f_ast.selections << node_field_ast(type.get_field('node')) - end + f_ast = field_ast(field) + node_fields = [node_field_ast(field.type.unwrap.get_field('node'))] + f_ast = f_ast.merge(selections: f_ast.selections + node_fields) + f_ast end # Make a field AST for a connection field. @@ -174,9 +155,10 @@ module GraphQL::Relay::Walker # Returns a GraphQL::Language::Nodes::Field instance or nil if the created # AST was invalid for missing required arguments. def connection_field_ast(field) - field_ast(field, connection_arguments) do |f_ast, type| - f_ast.selections << edges_field_ast(type.get_field('edges')) - end + f_ast = field_ast(field, connection_arguments) + edges_fields = [edges_field_ast(field.type.unwrap.get_field('edges'))] + f_ast = f_ast.merge(selections: f_ast.selections + edges_fields) + f_ast end # Is this field for a relay node? diff --git a/spec/query_builder_spec.rb b/spec/query_builder_spec.rb index c2d0823..ebceddd 100644 --- a/spec/query_builder_spec.rb +++ b/spec/query_builder_spec.rb @@ -30,29 +30,11 @@ describe GraphQL::Relay::Walker::QueryBuilder do end describe 'with aliases removed' do - before do - fields(ast).each { |field| field.alias = nil } - end - it 'matches the expected query string' do - expect(subject).to eq(File.read(query_path).strip) + # Replace the aliases, leaving the leading whitespace in place + string_without_aliases = subject.gsub(/ [a-z]{12}: /, " ") + expect(string_without_aliases).to eq(File.read(query_path).strip) end end end - - def fields(ast) - nodes(ast).select { |node| node.is_a?(GraphQL::Language::Nodes::Field) } - end - - def nodes(ast) - children = if ast.respond_to?(:selections) - ast.selections - elsif ast.respond_to?(:definitions) - ast.definitions - else - [] - end - - children + children.map { |child| nodes(child) }.flatten - end end