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

expected iterable, but did not find one for field Query.XXXX #10

Open
prewk opened this issue Mar 27, 2016 · 8 comments
Open

expected iterable, but did not find one for field Query.XXXX #10

prewk opened this issue Mar 27, 2016 · 8 comments

Comments

@prewk
Copy link

prewk commented Mar 27, 2016

Hello! I'm trying to wire up a User model with two GraphQL query fields.

The type:

const userType = new GraphQLObjectType(BookshelfType({
  name: 'User',
  description: 'A user',
  fields: model => ({
    id: globalIdField('User'), // Relay stuff
    email: model.attr({
      type: GraphQLString,
    }),
    role: model.attr({
      type: GraphQLString,
    }),
  }),
  interfaces: [nodeInterface], // Relay stuff
}));

The schema:

const queryType = new GraphQLObjectType({
  name: 'Query',
  fields: () => ({
    node: nodeField,
    users: {
      type: new GraphQLList(userType),
      resolve: () => User.fetchAll(),
    },
    user: {
      args: {
        id: { type: GraphQLInt },
      },
      type: userType,
      resolve: (_, args) => User.forge({ id: args.id }).fetch(),
    },
  }),
});

export default new GraphQLSchema({
  query: queryType,
});

I can query one user just fine with { user(id: 1) { id, email, role } }.

However, if I query the all users field { users { id, email, role } } I get this error: User Error: expected iterable, but did not find one for field Query.users.

I guess it's complaining about type: new GraphlQLList(userType) as return type? It's expecting an iterable but gets a Bookshelf Collection, right?

If I force it to return an array instead of a collection it works:

// I change
resolve: () => User.fetchAll()
// to:
resolve: () => User.fetchAll().then(users => users.reduce((arr, user) => { arr.push(user); return arr; }, [])),

What am I doing wrong here?

@tmack8001
Copy link

I ran into a very similar issue. I would expect User.fetchAll() to work, though yes instead of an iterable GraphQL is getting a Promise (Promises are fine, as GraphQL will execute the .then on the promise). The way I got around this would be by doing the following:

activities: {
      type: new GraphQLList(ActivityType),
      resolve: async () => {
        return await Activity.fetchAll(...options...).then(function (collection) {
          return collection.models;
        });
      }
    }

Personally I think that this library should be resolving the collection into a list of things, but that might just be me @brysgo what do you think?

@prewk
Copy link
Author

prewk commented Mar 28, 2016

@tmack8001 Thanks for replying! I don't think the promise itself is a problem, but your better insight into Bookshelf collections sizes down the problem to:

resolve: () => User.fetchAll().then(collection => collection.models),

So you actually don't have to do async and await, just converting collection to collection.models is all that it takes to be valid.

@brysgo
Copy link
Owner

brysgo commented Mar 28, 2016

@tmack8001 - There are plenty of ways to make this library more convenient and I'm open to adding as many as possible.

@tmack8001
Copy link

Of course, I am just starting to look at graphQL for a personal project I have been meaning to work on so as I get dirtier with it I will ping out with questions or requests.

Do you think we should encapsulate this Collection -> Iterable within this library? If so, I can work on getting a PR together after diving into things.

I've also been thinking about #5 a little bit, as I'm building pagination into my implementation returning a list. That we would also probably bake in for ease of use for adopters.

@brysgo
Copy link
Owner

brysgo commented Mar 29, 2016

I think encapsulating the collection is a great idea. As soon as you have something, put it up and I'll check it out.

As for #5, I've been working with relay more so if you have any relay helpers you end up making I'd be happy to take a look also.

@tmack8001
Copy link

Thinking about this further, how would one go about doing this. Since in the schema definition we aren't using any encapsulation with this library. We could add a helper around the relationship, but I don't see another way since the query type isn't related to graphql-bookshelf.

@brysgo
Copy link
Owner

brysgo commented Apr 2, 2016

Right, we would need to provide proxies to bookshelf classes that add functionality.

Alternatively, we could wrap every resolve on a bookshelf type and check for collections that get returned.

@zeusbaba
Copy link

in feathersjs case, @prewk answer works well.
see:

users(root, args, context) {
  return Users.find({}).then(results => results.data)
}

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

4 participants