RStankov / SearchObjectGraphQL

GraphQL plugin for SearchObject gem
MIT License
159 stars 25 forks source link

graphql-ruby 1.12.4: NoMethodError: undefined method `validate_directive_argument' #29

Closed haines closed 3 years ago

haines commented 3 years ago

https://github.com/rmosolgo/graphql-ruby/pull/3320 breaks SearchObject::Plugin::GraphQL, because including the plugin does not result in the validate_directive_argument class method being defined on the resolver.

Here's a script to reproduce:

# frozen_string_literal: true

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'graphql', ENV.fetch('GRAPHQL_VERSION')
  gem 'minitest'
  gem 'search_object_graphql', github: 'RStankov/SearchObjectGraphQL'
end

require 'minitest/autorun'
require 'search_object'
require 'search_object/plugin/graphql'

class Post
  def self.all
    [Post.new('Foo'), Post.new('Bar')]
  end

  attr_reader :name

  def initialize(name)
    @name = name
  end
end

class PostType < GraphQL::Schema::Object
  field :name, String, null: false
end

class PostResolver
  include SearchObject.module(:graphql)

  type [PostType], null: false

  scope { Post.all }

  option :name, type: String do |scope, value|
    scope.select { |post| post.name == value }
  end
end

class QueryType < GraphQL::Schema::Object
  field :posts, resolver: PostResolver
end

class Schema < GraphQL::Schema
  query QueryType
end

class SearchObjectGraphQLTest < Minitest::Test
  def test_query
    query = <<~GRAPHQL
      query {
        posts(name: "Foo") {
          name
        }
      }
    GRAPHQL

    expected_result = {
      'data' => {
        'posts' => [
          { 'name' => 'Foo' }
        ]
      }
    }

    assert_equal expected_result, Schema.execute(query).to_h
  end
end

This works with graphql-ruby 1.12.3:

$ GRAPHQL_VERSION=1.12.3 ruby search_object_graphql_test.rb
Run options: --seed 14042

# Running:

.

Finished in 0.002023s, 494.3154 runs/s, 494.3154 assertions/s.

1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

But fails on graphql-ruby 1.12.4:

$ GRAPHQL_VERSION=1.12.4 ruby search_object_graphql_test.rb
Run options: --seed 12779

# Running:

E

Finished in 0.001467s, 681.6633 runs/s, 0.0000 assertions/s.

  1) Error:
SearchObjectGraphQLTest#test_query:
NoMethodError: undefined method `validate_directive_argument' for PostResolver:Class
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema/argument.rb:282:in `block in coerce_into_values'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema.rb:115:in `after_lazy'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema/argument.rb:281:in `coerce_into_values'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema/member/has_arguments.rb:113:in `block (2 levels) in coerce_arguments'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/dataloader/null_dataloader.rb:16:in `append_job'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema/member/has_arguments.rb:111:in `block in coerce_arguments'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema/member/has_arguments.rb:110:in `each'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema/member/has_arguments.rb:110:in `coerce_arguments'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/arguments_cache.rb:49:in `dataload_for'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:205:in `evaluate_selection'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:142:in `block (2 levels) in evaluate_selections'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/dataloader/null_dataloader.rb:16:in `append_job'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:141:in `block in evaluate_selections'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:140:in `each'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:140:in `evaluate_selections'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:62:in `block in run_eager'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/dataloader/null_dataloader.rb:16:in `append_job'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter/runtime.rb:61:in `run_eager'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter.rb:77:in `block in evaluate'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/tracing.rb:66:in `trace'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter.rb:76:in `evaluate'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/interpreter.rb:49:in `begin_query'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:85:in `begin_query'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:104:in `block (2 levels) in run_as_multiplex'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/dataloader/null_dataloader.rb:16:in `append_job'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:104:in `block in run_as_multiplex'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:103:in `each'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:103:in `each_with_index'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:103:in `run_as_multiplex'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:63:in `block (2 levels) in run_queries'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:208:in `block in instrument_and_analyze'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:29:in `block (2 levels) in apply_instrumenters'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:46:in `block (2 levels) in each_query_call_hooks'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:41:in `each_query_call_hooks'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:45:in `block in each_query_call_hooks'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:72:in `call_hooks'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:44:in `each_query_call_hooks'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:27:in `block in apply_instrumenters'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:72:in `call_hooks'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/instrumentation.rb:26:in `apply_instrumenters'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:187:in `instrument_and_analyze'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:62:in `block in run_queries'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/tracing.rb:66:in `trace'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:60:in `run_queries'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/execution/multiplex.rb:50:in `run_all'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema.rb:1690:in `multiplex'
    ${GEM_HOME}/gems/graphql-1.12.4/lib/graphql/schema.rb:1661:in `execute'
    search_object_graphql_test.rb:71:in `test_query'

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
RStankov commented 3 years ago

Thank you very much for the detail explanation and test case.

Due to change in 1.12.4, now the search objects class, requires the inheritance of GraphQL::Schema::Resolver:

-- class PostResolver
++ class PostResolver < GraphQL::Schema::Resolver
  include SearchObject.module(:graphql)

  type [PostType], null: false

  scope { Post.all }

  option :name, type: String do |scope, value|
    scope.select { |post| post.name == value }
  end
end

I updated the documentation and will be releasing 1.0.0 which will make sure users are warned about this.