Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
benkimball opened this issue Feb 16, 2018 · 2 comments
Closed

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

benkimball opened this issue Feb 16, 2018 · 2 comments

Comments

@benkimball
Copy link
Contributor

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
}
@rmosolgo
Copy link
Owner

It was added to experiment with different workflows, I heard on Slack that Vox Media is using it in a pretty nice way, similar to the "Resolving with a single function" documented here:

http://rmosolgo.github.io/blog/2017/03/17/prototyping-a-graphql-schema-from-definition-with-ruby/

That blog post includes a few ways to try it out. Although I don't use it much, I certainly don't plan to break it! You could also give the upcoming class-based API a spin: https://github.com/rmosolgo/graphql-ruby/blob/1.8-dev/guides/schema/class_based_api.md

@benkimball
Copy link
Contributor Author

Thanks so much for the quick and comprehensive response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants