{"action":"created","issue":{"url":"https://api.github.com/repos/rmosolgo/graphql-ruby/issues/1825","repository_url":"https://api.github.com/repos/rmosolgo/graphql-ruby","labels_url":"https://api.github.com/repos/rmosolgo/graphql-ruby/issues/1825/labels{/name}","comments_url":"https://api.github.com/repos/rmosolgo/graphql-ruby/issues/1825/comments","events_url":"https://api.github.com/repos/rmosolgo/graphql-ruby/issues/1825/events","html_url":"https://github.com/rmosolgo/graphql-ruby/issues/1825","id":355727522,"node_id":"MDU6SXNzdWUzNTU3Mjc1MjI=","number":1825,"title":"Split QueryType into separate files","user":{"login":"cabello","id":60936,"node_id":"MDQ6VXNlcjYwOTM2","avatar_url":"https://avatars1.githubusercontent.com/u/60936?v=4","gravatar_id":"","url":"https://api.github.com/users/cabello","html_url":"https://github.com/cabello","followers_url":"https://api.github.com/users/cabello/followers","following_url":"https://api.github.com/users/cabello/following{/other_user}","gists_url":"https://api.github.com/users/cabello/gists{/gist_id}","starred_url":"https://api.github.com/users/cabello/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cabello/subscriptions","organizations_url":"https://api.github.com/users/cabello/orgs","repos_url":"https://api.github.com/users/cabello/repos","events_url":"https://api.github.com/users/cabello/events{/privacy}","received_events_url":"https://api.github.com/users/cabello/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2018-08-30T19:43:53Z","updated_at":"2018-09-19T05:43:49Z","closed_at":null,"author_association":"NONE","body":"Using old style definitions we have been splitting QueryType into multiple files using the following solution:\r\n\r\n```ruby\r\nQueryType = GraphQL::ObjectType.new.tap do |query|\r\n  query.name = 'Query'\r\n  query.description = 'The query root of this schema. See available queries.'\r\n  query.interfaces = []\r\n\r\n  query_types = [\r\n    ClientQueryType,\r\n    AccountQueryType,\r\n    InstitutionQueryType,\r\n  ]\r\n\r\n  query.fields = FieldCombiner.combine(query_types)\r\nend\r\n```\r\n\r\nExample of `*QueryType`:\r\n\r\n```ruby\r\nClientQueryType = GraphQL::ObjectType.define do\r\n  field :clients, types[ClientType] do\r\n    description 'Find clients by ID'\r\n    argument :ids, types[!types.ID]\r\n    resolve ->(_, args, _) {\r\n      Client.where(id: args['ids'])\r\n    }\r\n  end\r\nend\r\n```\r\n\r\nAnd the field combiner:\r\n\r\n```ruby\r\nclass FieldCombiner\r\n  def self.combine(query_types)\r\n    Array(query_types).inject({}) do |acc, query_type|\r\n      acc.merge!(query_type.fields)\r\n    end\r\n  end\r\nend\r\n```\r\n\r\nI am having a hard time using this concept (or coming up with a similar one) for class based types, when I execute an empty query `{}` I get the following:\r\n\r\n```ruby\r\nNoMethodError: undefined method `edges?' for #<GraphQL::Schema::Field:0x00007fbeb7f51900>\r\n```\r\n\r\nAnd it happens on the first field that gets added to the schema, I believe is something related to the fact that `fields` returning old style definition?\r\n\r\nI will be investigating more, is there a blessed approach for breaking up a huge QueryType into multiple objects?"},"comment":{"url":"https://api.github.com/repos/rmosolgo/graphql-ruby/issues/comments/422660921","html_url":"https://github.com/rmosolgo/graphql-ruby/issues/1825#issuecomment-422660921","issue_url":"https://api.github.com/repos/rmosolgo/graphql-ruby/issues/1825","id":422660921,"node_id":"MDEyOklzc3VlQ29tbWVudDQyMjY2MDkyMQ==","user":{"login":"thefliik","id":12599934,"node_id":"MDQ6VXNlcjEyNTk5OTM0","avatar_url":"https://avatars3.githubusercontent.com/u/12599934?v=4","gravatar_id":"","url":"https://api.github.com/users/thefliik","html_url":"https://github.com/thefliik","followers_url":"https://api.github.com/users/thefliik/followers","following_url":"https://api.github.com/users/thefliik/following{/other_user}","gists_url":"https://api.github.com/users/thefliik/gists{/gist_id}","starred_url":"https://api.github.com/users/thefliik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thefliik/subscriptions","organizations_url":"https://api.github.com/users/thefliik/orgs","repos_url":"https://api.github.com/users/thefliik/repos","events_url":"https://api.github.com/users/thefliik/events{/privacy}","received_events_url":"https://api.github.com/users/thefliik/received_events","type":"User","site_admin":false},"created_at":"2018-09-19T05:43:49Z","updated_at":"2018-09-19T05:43:49Z","author_association":"CONTRIBUTOR","body":"My interpretation of this issue is the desire to break up a graphql type across multiple *files*, rather than across multiple *objects* (which is the way the issue is phrased). So maybe I'm misunderstanding something, but I think you're overthinking this problem (or maybe I'm underthinking it)?\r\n\r\nI've found it very easy to define a graphql type across multiple files (both in the current class-based API, and the old `.define` API).\r\n\r\n### Example:\r\n\r\nIn my project I have a `MutationRoot` class with the base definition in `app/graphql/root/mutation_root.rb`\r\n\r\n```\r\nmodule Types\r\n  class MutationRoot < BaseObject\r\n    graphql_name \"Mutation\"\r\n  end\r\nend\r\n```\r\n\r\nAnd I have a folder `app/graphql/mutations` with individual mutation files such as `app/graphql/mutations/person.rb`\r\n```\r\nrequire_relative '../root/mutation_root'\r\n\r\nmodule Types\r\n  class MutationRoot\r\n    field :personUpdate, PersonType, null: true do\r\n      description \"Update a person's properties\"\r\n      argument :person_id, ID, required: true\r\n      argument :property, Inputs::Person::PropertyUpdate, required: true\r\n    end\r\n  end\r\nend\r\n```\r\nThis works fine for splitting up files. I just make sure the `mutation_root.rb` file is loaded before the individual mutation files.\r\n\r\nFor this matter, in the *pre-class* version of graphql-ruby, I similarly split up my mutation type by calling `.define` on the `MutationRoot` class multiple times, which works fine. I.e.\r\n\r\nIn `app/graphql/mutations/person_mutations.rb`\r\n```\r\nrequire_relative '../root/mutation_root'\r\n\r\nGraphTypes::MutationRoot.define do\r\n  field :personUpdate, !GraphTypes::Person do\r\n    description \"Update a person's properties\"\r\n    argument :personId, !types.ID, as: :person_id\r\n    argument :property, !GraphInputs::PersonPropertyUpdate\r\n    resolve ->(obj,args,ctx) {\r\n      result = Person::Update.(args.to_h, 'current_user' => ctx[:current_user])\r\n\r\n      if result.success?\r\n        ::PersonInstance.new(result[:person], ctx[:current_perspective])\r\n      else\r\n        GraphQL::ExecutionError.new(result[:errors].join(' '))        \r\n      end\r\n    }\r\n  end\r\nend\r\n```\r\nIn `app/graphql/mutations/contact_list_mutations.rb`\r\n```\r\nrequire_relative '../root/mutation_root'\r\n\r\nGraphTypes::MutationRoot.define do\r\n  field :contactListCreate, !GraphTypes::ContactList do\r\n    description \"Create a contactcontactLlist\"\r\n    argument :property, !GraphInputs::ContactListPropertyCreate\r\n    resolve ->(obj,args,ctx) {\r\n      params = args.to_h\r\n      params[:owner_ids] = [ctx[:current_perspective].id]\r\n\r\n      result = ContactList::Create.(params, 'current_user' => ctx[:current_user])\r\n\r\n      if result.success?\r\n        result[:contact_list]\r\n      else\r\n        GraphQL::ExecutionError.new(result[:errors].join(' '))        \r\n      end\r\n    }\r\n  end\r\nend\r\n```\r\n\r\nI don't understand the desire to create additional DSL to accomplish this. Seems unnecessary?"}}
{"actor":{"display_login":"thefliik"}}