Ruby graphql-ruby: Difference between revisions

From wikinotes
No edit summary
Line 29: Line 29:
|}
|}
</blockquote><!-- Notes -->
</blockquote><!-- Notes -->
= Basics =
<blockquote>
Read [[graphql]] to get a general understanding of how graphql works before reading this.
== Schema ==
<blockquote>
* schemas are assigned a root object for queries(queryable object), and optionally mutations(operations with side effects).
* objects expose fields(objects) which can have arguments
* fields/arguments (exposed methods) are written in snake_case, but converted to camelCase when used in queries.
<source lang="ruby">
class MySchema < GraphQL::Schema
  mutation(MyMutationType)  # fields on MyMutationType accessible to schema
  query(MyQueryType)        # fields on MyQueryType accessible to schema
  # ...
end
class MyQueryType
end
class MyMutationType
end
</source>
</blockquote><!-- schema -->
== Queries(objects) ==
<blockquote>
{| class="wikitable"
|-
| field docs || https://graphql-ruby.org/fields/introduction
|-
| field arg docs || https://graphql-ruby.org/fields/arguments
|-
|}
{{ TODO |
split this example into multiple examples to more clearly describe one concept at a time
}}
Objects are described heirarchically starting with a single/root <code>GraphApi::ObjectType</code> which exposes other <code>GraphApi::ObjectType</code> objects as '''fields'''<br>
This root object is assigned to the schema using it's method <code>query(YourObject)</code>.
<source lang="ruby">
class MyGraph < GraphQL::Schema::ObjectType
  # ==========
  # user query
  # ==========
  field :user, User do |field|
    field.argument(:name, String, required: true, description: "...")
    field.argument(:family, FamilyType)
  end
  def user(name, family)
    User.find_by(
      firstname: name,
      lastname: family[:last_name],  # fields from input graphql types accessible as snake_cased hash-keys
    )
  end
  # =============
  # project query
  # =============
  field :projectDetails, ProjectDetailsType
  def project
    # you may return a hash with keys satisfying return-type
    { name: "myproject", foo: "bar" }
  end
end
class FamilyType
  field :lastName, String  # fields expected in camelCase
end
class User < GraphQL::Schema::ObjectType
  field # ...
end
class ProjectDetailsType < GraphQL::Schema::ObjectType
  field :name, String
  field :foo, String
end
</source>
</blockquote><!-- queries -->
== Mutations ==
<blockquote>
Mutations perform jobs with side-effects (like POST, PATCH, DELETE, ...)
<source lang="ruby">
class MyMutation < GraphQL::Schema::RelayClassicMutation
  field :foo, String, null: false  # exposes attribute 'foo', of type String, non-nullable
  field :bar, String, null: true
  argument :id, Integer, description: '...'
  # method that runs when mutation is executed
  def resolve(id)
    return { foo: "abc", bar: "def" }  # returns all fields defined on class
  end
end
</source>
</blockquote><!-- mutations -->
</blockquote><!-- basics -->


= Syntax =
= Syntax =

Revision as of 20:52, 5 September 2021

graphql gem for ruby.

TODO:

needs revisiting

Documentation

wiki graphql
docs https://graphql-ruby.org/guides
API docs https://graphql-ruby.org/api-doc/1.12.8/
github https://github.com/rmosolgo/graphql-ruby
homepage https://graphql-ruby.org/

Notes

graphql-ruby basics

Syntax

Objects

Fields with Arguments

class User < GraphQL::Schema::Object
  field :id, Integer    # name, returntype
  field :age, Integer   # name, returntype
end

class MyGraph < GraphQL::Schema::Object
  field :user, User, do |field|
    field.argument(:id, Integer, required: true)
  end
end

Mutations

Mutations are graphql fields that trigger side effects.

  • mutations return a hash, that contains all of the fields defined on it.
  • mutations may optionally accept arguments
class MyMutation < GraphQL::Schema::RelayClassicMutation
  argument :username, String, required: true

  field :message, String, null: true    # returns string, allows null
  field :errors, [String], null, false  # returns list of strings, disallows null

  def resolve(username)
    # do thing that produces side effect
    { message: "Hello #{username}",
      errors: [] }
  end
end


class MyMutationRoot < GraphQL::Schema::RelayClassicMutation
  field :mymutation,
    mutation: MyMutation  # TODO: needs arg??
end


class MyGraph < GraphQL::Schema
  mutation(MyMutationRoot)
end

Connections

Connections between nodes are expressed as edges.
Edges can be abstracted as connections to support query params, filters, pagination, etc.

See https://graphql-ruby.org/relay/connections.html

# Defines a `ClassType`, with the connection `StudentType`.

class ClassType < GraphQL::Schema::Object
  field :students, StudentConnectionType,
    connection: true,
    description: "Students that belong to a class"
end

class StudentConnectionType < GraphQL::Types::Relay::BaseConnection
  edge_type StudentEdgeType
end

class StudentEdgeType < GraphQL::Types::Relay::BaseEdge
  node_type StudentType
end

class StudentType < GraphQL::Schema::Object
  field :id, Integer
  field :age, Integer
  field :username, String
end