Graphql-ruby: Provide a `dig` implementation

Created on 17 Jul 2018  路  7Comments  路  Source: rmosolgo/graphql-ruby

I'm in the middle of setting up a graphQL api on our system, and for some of the mutations I'm reusing our existing service classes rather than rewriting them, and just making a few adjustments for the input objects, and came across an issue which might be something useful to add to graphql-ruby (assuming it can't already be done)

In the API, I'm setting up foreign keys as nested inputs, so a mutation's input looks something like this:

{
    customer {
      id: 1
    },
    currency: {
      id: 1
    }
}

In the service object under the old codebase, I used to simply supply customer_id and currency_id, so checking if they were supplied was simply a case of checking for nil. In this scenario though, it's possible that customer for instance might be nil, so this becomes a more annoying check.

In normal ruby hashes, we can get around this with the #dig method, and I could do something like params.dig(:customer, :id) but now using the graphQL input objects, this isn't possible.

I think adding a dig implementation would be really useful for this situation.

On another note, for testing my service class, how can I instantiate an Input object outside of a full request?

All 7 comments

Unrelated, I had no idea the dig method existed on hashes and I've actually gone through the trouble of monkey patching my own version into hash a few times. Thanks! dig is super convenient

Regarding this issue though, you can simply transform the arguments object into a hash and then use it normally. I.e. args.to_h.dig

Yeah I only just discovered it recently, was very happy when I found it as it cleans up a lot of code.
Ah missed the to_h method, does that convert keys to strings or symbols?

I think it converts them to symbols. But I don't quite remember off the top of my head.

Yes, I agree that .to_h is a good solution here.

Regarding this:

how can I instantiate an Input object outside of a full request

It's basically not possible. GraphQL's objects are all interrelated, using things like query context too, for authorization. Personally, I recommend two kinds of tests:

  • A unit test for the service object (or whatever kind of application logic you have)
  • An integration test that runs a full GraphQL query and checks the result (maybe stubbing the application logic)

That way you can run a test using the full GraphQL "stack" and you don't couple your tests to GraphQL-Ruby's implementation details. That test will give you more stability when upgrading gem versions and more confidence that the API works the same way as the test, since the tests runs the full GraphQL query.

@rmosolgo I was trying to write a unit test for just the service object when I ran into this issue, as that service object takes in the input from the request to perform its operation, but I wasn't sure how to give it the input given that was a GraphQL input object. But if I can simply use to_h then that solves my issue :)

Great, sounds like we're in a good place then :) Thanks for your help, @thefliik !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jesster2k10 picture jesster2k10  路  3Comments

theodorton picture theodorton  路  3Comments

KevinColemanInc picture KevinColemanInc  路  3Comments

rylanc picture rylanc  路  3Comments

sayduck-daniel picture sayduck-daniel  路  3Comments