# GraphitiGql GraphQL bindings for [Graphiti](www.graphiti.dev). Write code like this: ```ruby class EmployeeResource < ApplicationResource attribute :first_name, :string attribute :age, :integer has_many :positions end ``` Get an API like this: ```gql query { employees( filter: { firstName: { match: "arha" } }, sort: [{ att: age, dir: desc }], first: 10, after: "abc123" ) { edges { node { id firstName age positions { nodes { title } } } cursor } stats { total { count } } } } ``` ### Getting Started ```ruby # Gemfile gem 'graphiti' gem "graphiti-rails" gem 'graphiti_gql' ``` ```ruby # config/routes.rb Rails.application.routes.draw do scope path: ApplicationResource.endpoint_namespace do mount GraphitiGql::Engine, at: "/gql" end end ``` Write your Graphiti code as normal, omit controllers. ### How does it work? This autogenerates `graphql-ruby` code by introspecting Graphiti Resources. Something like this happens under-the-hood: ```ruby field :employees, [EmployeeType], null: false do argument :filter, EmployeeFilter, required: false # ... etc ... end def employees(**arguments) EmployeeResource.all(**arguments).to_a end ``` In practice it's more complicated, but this is the basic premise - use Graphiti resources to handle query and persistence operations; autogenerate `graphql-ruby` code to expose those Resources as an API. This means we play nicely with e.g. telemetry and error-handling libraries because it's all `graphql-ruby` under-the-hood...except for actually **performing** the operations, which is really more a Ruby thing than a GraphQL thing. ### Caveats This rethinks the responsibilities of Graphiti, coupling the execution cycle to `graphql-ruby`. We do this so we can play nicely with other gems in the GQL ecosystem, and saves on development time by offloading responsibilities. The downside is we can no longer run a `JSON:API` with the same codebase, and certain documentation may be out of date. Longer-term, we should rip out only the parts of Graphiti we really need and redocument.