Skip to content

Intended use of GraphQL::Schema.from_definition? #1287

Closed
@benkimball

Description

@benkimball

I'm using graphql-ruby 1.7.10 in a Rails 4.2.7.1 project, and I'm trying to see if it's possible to use a .gql file to define my schema, rather than using the supplied DSL. Based on the tests in build_from_definition_spec, I decided to try using GraphQL::Schema.from_definition.

I replaced my previous (working) app_schema.rb file:

AppSchema = GraphQL::Schema.define do
  mutation(Types::MutationType)
  query(Types::QueryType)
end

with:

AppSchema = GraphQL::Schema.from_definition(File.read(GRAPHQL_SCHEMA_FILE))

where GRAPHQL_SCHEMA_FILE names a file containing my schema in what #727 calls "IDL" format (included below).

Having done so, I expected that I would be able to run queries. Instead, the following exception is raised:

NoMethodError at /graphql
=========================

> undefined method `award' for nil:NilClass

app/controllers/graphql_controller.rb, line 14
----------------------------------------------

``` ruby
    9       operation_name = params[:operationName]
  10       context = {
  11         # Query context goes here
  12         current_user: current_user
  13       }
>  14       result = AppSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
  15       render json: result
  16     end
  17   
  18     private
  19   
```

App backtrace
-------------

- app/controllers/graphql_controller.rb:14:in `execute'
- lib/time_travel.rb:12:in `time_travel'

Full backtrace
--------------

- graphql (1.7.10) lib/graphql/schema/build_from_definition.rb:21:in `call'
- graphql (1.7.10) lib/graphql/schema/build_from_definition.rb:171:in `block in build_object_type'
- graphql (1.7.10) lib/graphql/schema/build_from_definition.rb:284:in `block (2 levels) in build_fields'
- graphql (1.7.10) lib/graphql/field.rb:244:in `resolve'
- graphql (1.7.10) lib/graphql/execution/execute.rb:254:in `call'
- graphql (1.7.10) lib/graphql/schema/middleware_chain.rb:45:in `invoke_core'
- graphql (1.7.10) lib/graphql/schema/middleware_chain.rb:38:in `invoke'
- graphql (1.7.10) lib/graphql/execution/execute.rb:108:in `resolve_field'
- graphql (1.7.10) lib/graphql/execution/execute.rb:72:in `block (2 levels) in resolve_selection'
- graphql (1.7.10) lib/graphql/tracing.rb:57:in `block in trace'
- graphql (1.7.10) lib/graphql/tracing.rb:71:in `call_tracers'
- graphql (1.7.10) lib/graphql/tracing.rb:57:in `trace'
- graphql (1.7.10) lib/graphql/execution/execute.rb:71:in `block in resolve_selection'
- graphql (1.7.10) lib/graphql/execution/execute.rb:64:in `resolve_selection'
- graphql (1.7.10) lib/graphql/execution/execute.rb:36:in `block in resolve_root_selection'
- graphql (1.7.10) lib/graphql/tracing.rb:57:in `block in trace'
- graphql (1.7.10) lib/graphql/tracing.rb:71:in `call_tracers'
- graphql (1.7.10) lib/graphql/tracing.rb:57:in `trace'
- graphql (1.7.10) lib/graphql/execution/execute.rb:32:in `resolve_root_selection'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:108:in `begin_query'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:81:in `block in run_as_multiplex'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:80:in `run_as_multiplex'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:69:in `block (2 levels) in run_queries'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:174:in `block in instrument_and_analyze'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:29:in `block (2 levels) in apply_instrumenters'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:46:in `block (2 levels) in each_query_call_hooks'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:41:in `each_query_call_hooks'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:45:in `block in each_query_call_hooks'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:58:in `call_hooks'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:44:in `each_query_call_hooks'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:27:in `block in apply_instrumenters'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:58:in `call_hooks'
- graphql (1.7.10) lib/graphql/execution/instrumentation.rb:26:in `apply_instrumenters'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:166:in `instrument_and_analyze'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:68:in `block in run_queries'
- graphql (1.7.10) lib/graphql/tracing.rb:57:in `block in trace'
- graphql (1.7.10) lib/graphql/tracing.rb:71:in `call_tracers'
- graphql (1.7.10) lib/graphql/tracing.rb:57:in `trace'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:58:in `run_queries'
- graphql (1.7.10) lib/graphql/execution/multiplex.rb:48:in `run_all'
- graphql (1.7.10) lib/graphql/schema.rb:299:in `block in multiplex'
- graphql (1.7.10) lib/graphql/schema.rb:612:in `with_definition_error_check'
- graphql (1.7.10) lib/graphql/schema.rb:298:in `multiplex'
- graphql (1.7.10) lib/graphql/schema.rb:275:in `execute'
- app/controllers/graphql_controller.rb:14:in `execute'

After a fair amount of time with my good friend pry, and comparing my code to that in build_from_description_spec.rb, my suspicion is that I need some kind of root resolver, but as I'm new to both this gem and GraphQL in general I'm not sure if I'm on the right track.

My schema:

type Award {
  closes_at: Time!
  core_value_question: String
  description: String

  # A count of the number of people who are in the groups selected as eligible
  # nominators. Before the Award has ended, this is expensive to compute. After
  # the award has ended, this number is stored and no longer computationally expensive.
  eligible_nominator_count: Int
  eligible_nominee_count: Int
  has_nomination_limit: Boolean!
  nomination_limit: Int
  nominator_eligibility_groups: [String]
  nominee_eligibility_groups: [String]
  nominee_question: String!
  opens_at: Time!
  rationale_question: String!
  send_invitations_on_open: Boolean!
  send_reminders_before_close: Boolean!
  skills_question: String
  status: AwardStatusEnumType!
  title: String!
}

# An Award can be in one of four states, depending on its open and close dates and whether a winner has been selected
enum AwardStatusEnumType {
  # Not accepting nominations; a winner has been selected
  awarded

  # No longer accepting nominations; a winner has not been selected
  ended

  # Accepting nominations
  live

  # Not yet accepting nominations
  scheduled
}

type Company {
  name: String!
  subdomain: String!
}

type Mutation {
  # An example field added by the generator
  testField: String
}

type Query {
  # Fetch an Award by ID
  award(id: String!): Award

  # Finds a Company by subdomain
  company(subdomain: String!): Company

  # Fetch the currently logged-in user
  me: User

  # Find a user by email address
  user(email: String!): User
}

scalar Time

type User {
  email: String!
  first_name: String
  last_name: String
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions