### Install graphql-ruby
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/readme.md
Run bundle install after adding the gem to your Gemfile to install it.
```bash
$ bundle install
```
--------------------------------
### Install graphql-ruby-client
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/overview.md
Install the JavaScript client using Yarn or NPM. This is the first step to using the client in your project.
```sh
yarn add graphql-ruby-client
```
```sh
# Or:
npm install graphql-ruby-client
```
--------------------------------
### Example User Response
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/objects.md
Example JSON response for a User query.
```json
{
"user" => {
"handle" => "rmosolgo",
"email" => nil,
}
}
```
--------------------------------
### Generate graphql installation
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/readme.md
Run the graphql:install generator to set up graphql-ruby in a Rails application.
```bash
$ rails generate graphql:install
```
--------------------------------
### Install Dependencies
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/development.md
Installs project dependencies and compiles native extensions. Ragel is optional but required for building the lexer.
```bash
bundle install
rake compile # If you get warnings at this step, you can ignore them.
```
--------------------------------
### Install Standalone Dependencies
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/javascript_client/readme.md
Install dependencies for the JavaScript client when developing it as a standalone project.
```bash
yarn install
```
--------------------------------
### Initiating a GraphQL Mutation
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/mutations/mutation_root.md
GraphQL mutations must start with the 'mutation' keyword. This example shows the basic syntax for defining a mutation with variables.
```graphql
mutation($accountNumber: ID!, $newBalance: Int!) {
setAccountBalance(accountNumber: $accountNumber, newBalance: $newBalance) {
# ...
}
}
```
--------------------------------
### Install GraphQL::Pro Gem
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/pro/installation.md
After configuring Bundler and adding the gem to your Gemfile, run this command to install the graphql-pro gem and its dependencies.
```sh
bundle install
```
--------------------------------
### Install for Local Development
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/javascript_client/readme.md
Link the local package for development and testing purposes.
```bash
npm link .
```
--------------------------------
### Install JavaScript Client Dependencies
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/javascript_client/readme.md
Install the necessary dependencies for the JavaScript client when working within the GraphQL-Ruby project.
```bash
rake js:install
```
--------------------------------
### GraphQL Subscription Operation Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/subscription_type.md
An example of a client-side subscription operation to receive data when a 'postWasPublished' event is triggered.
```graphql
subscription {
postWasPublished {
# This data will be delivered whenever `postWasPublished`
# is triggered by the server:
title
author {
name
}
}
}
```
--------------------------------
### Install graphql-ruby with Rails Generators
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/getting_started.md
Use Rails generators to install the graphql-ruby boilerplate and mount GraphiQL for development. Remember to run bundle install afterwards.
```bash
# Add graphql-ruby boilerplate and mount graphiql in development
$ rails g graphql:install
# You may need to run bundle install again, as by default graphiql-rails is added on installation.
$ bundle install
# Make your first object type
$ rails g graphql:object Post title:String rating:Int comments:[Comment]
```
--------------------------------
### Install GraphQL Ruby Gem
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/index.html
Use these commands to add the graphql gem to your project and set up GraphQL with Rails.
```bash
# Download the gem: bundle add graphql
# Setup with Rails: rails generate graphql:install
```
--------------------------------
### Example GraphQL Request with Input Object
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/input_objects.md
Demonstrates how an input object is used as an argument in a GraphQL mutation.
```graphql
mutation {
createPost(attributes: { title: "Hello World", fullText: "This is my first post", categories: [GENERAL] }) {
# ^ Here is the input object ..................................................... ^
}
}
```
--------------------------------
### GraphQL Query String
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/language_tools/visitor.md
A basic example of a GraphQL query string.
```ruby
query_string = "query { user(id: \"1\") { userName } }"
```
--------------------------------
### Install GraphQL with Rails Generators
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/generators.md
Use the `graphql:install` generator to add GraphQL to a Rails application. This command sets up the necessary folder structure, schema definition, base type classes, query and mutation types, routes, controllers, and integrates with tools like `graphiql-rails`.
```ruby
rails generate graphql:install
```
--------------------------------
### GraphQL Subscription Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/root_types.md
Example of a GraphQL subscription operation targeting the `Subscription.commentAdded` field with arguments.
```graphql
subscription CommentAdded {
# `Subscription.commentAdded`
commentAdded(postId: 1)
}
```
--------------------------------
### Querying a User Object
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/objects.md
Example of how to query a User object and its fields.
```graphql
user {
handle
email
}
```
--------------------------------
### GraphQL Query Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/root_types.md
Example of a GraphQL query operation targeting the `Query.posts` field.
```graphql
query Posts {
# `Query.posts`
posts { ... }
}
```
--------------------------------
### Example Response with totalCount and totalPageCount
Source: https://github.com/rmosolgo/graphql-ruby/wiki/How-To:-Set-a-Custom-Base-Connection-class-to-provide-totalCount-and-totalPageCount-fields-on-all-Connections
A sample JSON response demonstrating the `totalCount` and `totalPageCount` fields returned by a connection query.
```json
{
"data": {
"widgets": {
"totalCount": 179,
"totalPageCount": 36,
"edges": [
{
"node": {
"id": "1"
}
},
{
"node": {
"id": "2"
}
},
{
"node": {
"id": "3"
}
},
{
"node": {
"id": "4"
}
},
{
"node": {
"id": "5"
}
}
]
}
}
}
```
--------------------------------
### GraphQL Subscription Query with Arguments
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/subscription_classes.md
Example of how to invoke a subscription in GraphQL, passing arguments that are used for loading.
```graphql
subscription($roomId: ID!) {
messageWasPosted(roomId: $roomId) {
# ...
}
}
```
--------------------------------
### GraphQL Mutation Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/root_types.md
Example of a GraphQL mutation operation targeting the `Mutation.createPost` field with input variables.
```graphql
mutation AddPost($postAttrs: PostInput!){
# `Mutation.createPost`
createPost(attrs: $postAttrs)
}
```
--------------------------------
### Basic Counter Analyzer Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/ast_analysis.md
An example analyzer that counts all fields encountered in a query, regardless of context like fragments or directives. It uses `on_leave_field` to track field names.
```ruby
class BasicCounterAnalyzer < GraphQL::Analysis::Analyzer
def initialize(query_or_multiplex)
super
@fields = Set.new
@arguments = Set.new
end
# Visitors are all defined on the Analyzer base class
# We override them for custom analyzers.
def on_leave_field(node, _parent, _visitor)
@fields.add(node.name)
end
def result
# Do something with the gathered result.
Analytics.log(@fields)
end
end
```
--------------------------------
### Query Context Setup with Limiter Key
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/limiters/active_operations.md
Provide a client identifier in the query context to enable the Active Operation Limiter. Operations with the same key are grouped.
```ruby
context = {
viewer: current_user,
# for example:
limiter_key: logged_in? ? "user:#{current_user.id}" : "anon-ip:#{request.remote_ip}",
# ...
}
result = MySchema.execute(query_str, context: context)
```
--------------------------------
### Define Query Root Type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/root_types.md
Example of defining a `QueryType` which returns all blog posts.
```ruby
# app/graphql/types/query_type.rb
class Types::QueryType < GraphQL::Schema::Object
field :posts, [PostType], 'Returns all blog posts', null: false
end
```
--------------------------------
### Render GraphiQL in an HTML page
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/graphiql_subscriptions.md
Install GraphiQL and add JavaScript code to import and render it on your page. This sets up the basic GraphiQL editor.
```html
```
```javascript
import { GraphiQL } from 'graphiql'
import React from 'react'
import { createRoot } from 'react-dom/client'
import 'graphiql/graphiql.css'
import { createGraphiQLFetcher } from '@graphiql/toolkit'
const fetcher = createGraphiQLFetcher({ url: '/graphql' })
const root = createRoot(document.getElementById('root'))
root.render()
```
--------------------------------
### Example Query on Shopify Admin API
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/complexity_and_depth.md
This is an example GraphQL query performed on the Shopify Admin API to illustrate complexity scoring.
```graphql
query {
node(id: "123") { # interface Node
id
...on HasMetafields { # interface HasMetafields
metafield(key: "a") {
value
}
metafields(first: 10) {
nodes {
value
}
}
}
...on Product { # implements HasMetafields
title
metafield(key: "a") {
definition {
description
}
}
}
...on PriceList {
name
catalog {
id
}
}
}
}
```
--------------------------------
### Configure Dalli Client for Object Cache
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/object_cache/memcached.md
Instantiate GraphQL::Enterprise::OperationStore with a Dalli::Client instance for Memcached integration. Ensure Dalli is installed and configured.
```ruby
use GraphQL::Enterprise::OperationStore, dalli: Dalli::Client.new(...)
```
--------------------------------
### Run Integration Tests
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/development.md
Runs integration tests by specifying a particular Gemfile. Ensure dependencies are installed for the chosen Gemfile.
```bash
BUNDLE_GEMFILE=gemfiles/rails_6.1.gemfile bundle install
BUNDLE_GEMFILE=gemfiles/rails_6.1.gemfile bundle exec rake test TEST=spec/integration/rails/graphql/relay/array_connection_spec.rb
```
--------------------------------
### Example Query Complexity Calculation
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/complexity_and_depth.md
Illustrates how complexity is calculated for a connection field with arguments like `first:`, `nodes`, and `pageInfo`.
```graphql
query {
author {
name # +1
books(first: 10) { # +1
nodes # +10 (+1, multiplied by `first:` above)
title # +10 (ditto)
}
pageInfo { # +1
endCursor # +1
}
totalCount # +1
}
}
}
```
--------------------------------
### Configure urql with ActionCable Subscriptions
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/urql_subscriptions.md
This setup allows urql to use ActionCable for GraphQL subscriptions. Make sure ActionCable is running and accessible at the specified WebSocket URL.
```javascript
import { createConsumer } from "@rails/actioncable";
import SubscriptionExchange from "graphql-ruby-client/subscriptions/SubscriptionExchange"
const actionCable = createConsumer('ws://127.0.0.1:3000/cable');
const forwardToActionCable = SubscriptionExchange.create({ consumer: actionCable })
const client = new Client({
url: '/graphql',
exchanges: [
...defaultExchanges,
subscriptionExchange({
forwardSubscription: forwardToActionCable
}),
],
});
```
--------------------------------
### Define Initial Subscription Response
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/subscription_classes.md
Override the `subscribe` method to provide an initial data payload when a client first connects to a subscription. This example returns a `room` object.
```ruby
class Subscriptions::MessageWasPosted < Subscriptions::BaseSubscription
# ...
field :room, Types::RoomType
def subscribe(room:)
# authorize, etc ...
# Return the room in the initial response
{
room: room
}
end
end
```
--------------------------------
### Example GraphQL Response with Extensions
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/response_extensions.md
This shows the structure of a GraphQL response that includes the "extensions" hash populated by the previous code snippet.
```json
{
"data" => { ... },
"extensions" => {
"warnings" => ["To-Dos will be disabled on Jan. 31, 2022"],
},
}
```
--------------------------------
### Run graphql-ruby-client sync utility
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/sync.md
This example shows the typical output of the `graphql-ruby-client sync` command when run without any arguments. It demonstrates the authorization process, the syncing of operations to a specified URL, and the generation of a client module.
```bash
$ graphql-ruby-client sync # ...
Authorizing with HMAC
Syncing 4 operations to http://myapp.com/graphql/operations...
3 added
1 not modified
0 failed
Generating client module in app/javascript/graphql/OperationStoreClient.js...
✓ Done!
```
--------------------------------
### Nesting Resolvers of the Same Type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/fields/resolvers.md
Example demonstrating a potential cyclical loading issue when a resolver is nested within the definition of the type it returns. This setup involves `QueryType` and `TasksResolver`.
```ruby
# app/graphql/types/query_type.rb
module Types
class QueryType < Types::BaseObject
field :tasks, resolver: Resolvers::TasksResolver
end
end
```
--------------------------------
### REST API Authorization Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/authorization/overview.md
Illustrates a typical request-by-request authorization pattern in a REST API controller. Checks user permissions before performing an action.
```ruby
class PostsController < ApiController
def create
# First, check the client's permission level:
if current_user.can?(:create_posts)
# If the user is permitted, then perform the action:
post = Post.create(params)
render json: post
else
# Otherwise, return an error:
render nothing: true, status: 403
end
end
end
```
--------------------------------
### Serve GraphQL-Ruby Website Locally
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/development.md
Run this command to serve the website locally and preview your changes. Visit http://localhost:4000 to view the site.
```bash
bundle exec rake site:serve
```
--------------------------------
### Analyze Specific Method Performance with StackProf
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/testing/profiling.md
Use the `--method` argument with the `stackprof` command to get detailed performance information for a specific method, including its callers and callees.
```bash
$ stackprof tmp/small.dump --method #gather_selections
```
--------------------------------
### Apollo Link Ably Subscription Setup
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/apollo_subscriptions.md
Configure Apollo Client to use Ably for GraphQL subscriptions. Add AblyLink before HttpLink and initialize the ApolloClient.
```javascript
import { ApolloClient, HttpLink, ApolloLink, InMemoryCache } from '@apollo/client';
import AblyLink from 'graphql-ruby-client/subscriptions/AblyLink'
const Ably = require("ably")
const ablyClient = new Ably.Realtime({ key: "your-app-key" })
const httpLink = new HttpLink({
uri: '/graphql',
credentials: 'include'
});
const ablyLink = new AblyLink({ably: ablyClient})
const link = ApolloLink.from([ablyLink, httpLink])
const client = new ApolloClient({
link: link,
cache: new InMemoryCache()
});
```
--------------------------------
### Define Extension with Options
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/field_extensions.md
Shows how to pass options to an extension when defining it. These options are available in the extension's `initialize` method.
```ruby
extension(LimitExtension, limit: 20)
```
--------------------------------
### Apollo Link ActionCable Subscription Setup
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/apollo_subscriptions.md
Configure Apollo Client to use ActionCable for GraphQL subscriptions. Use ApolloLink.split to route subscription queries to ActionCableLink and others to HttpLink.
```javascript
import { ApolloClient, HttpLink, ApolloLink, InMemoryCache } from '@apollo/client';
import { createConsumer } from '@rails/actioncable';
import ActionCableLink from 'graphql-ruby-client/subscriptions/ActionCableLink';
const cable = createConsumer()
const httpLink = new HttpLink({
uri: '/graphql',
credentials: 'include'
});
const hasSubscriptionOperation = ({ query: { definitions } }) => {
return definitions.some(
({ kind, operation }) => kind === 'OperationDefinition' && operation === 'subscription'
)
}
const link = ApolloLink.split(
hasSubscriptionOperation,
new ActionCableLink({cable}),
httpLink
);
const client = new ApolloClient({
link: link,
cache: new InMemoryCache()
});
```
--------------------------------
### Final Query Cost Calculation
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/complexity_and_depth.md
This example demonstrates the final query cost calculation after the complexity algorithm has normalized the selection tree, accounting for abstract types and duplicated paths.
```graphql
query {
node(id: "123") { # max(11, 12, 1) = 12
id
...on HasMetafields { # 1 + 10 = 11
metafield(key: "a") { # 1
value
}
metafields(first: 10) { # 10
nodes {
value
}
}
}
...on Product { # 1 + 11 from HasMetafields = 12
title
metafield(key: "a") { # duplicated in HasMetafields
definition { # 1
description
}
}
}
...on PriceList { # 1 = 1
name
catalog { # 1
id
}
}
}
}
```
--------------------------------
### Include GraphQL Testing Helpers
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/testing/helpers.md
Include the `GraphQL::Testing::Helpers` module in your test suite to gain access to testing methods. This setup is specific to your schema class.
```ruby
# Mix in `run_graphql_field(...)` to run on `MySchema`
include GraphQL::Testing::Helpers.for(MySchema)
```
--------------------------------
### Initialize Redis Client
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/ably_implementation.md
Create a Redis client instance, typically in an initializer, for use with GraphQL subscriptions.
```ruby
# for example, in an initializer:
$graphql_subscriptions_redis = Redis.new # default connection
```
--------------------------------
### Check User Permissions with `#ready?`
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/mutations/mutation_authorization.md
Use the `#ready?` method to perform checks before executing the mutation's core logic. This is useful for verifying user roles or specific permissions.
```ruby
class Mutations::PromoteEmployee < Mutations::BaseMutation
def ready?(**args)
# Called with mutation args.
# Use keyword args such as employee_id: or **args to collect them
if !context[:current_user].admin?
raise GraphQL::ExecutionError, "Only admins can run this mutation"
else
# Return true to continue the mutation:
true
end
end
# ...
end
```
--------------------------------
### Getting the Type Name of an Object
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/introspection.md
Use the `__typename` meta-field to get the name of the object type being queried. This is useful for unions and interfaces.
```graphql
{ user(id: "1") {
handle
__typename
}
}
```
--------------------------------
### Build the GraphQL Schema
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/getting_started.md
Instantiate the GraphQL schema, setting the `QueryType` as the entry point for all queries.
```ruby
class Schema < GraphQL::Schema
query Types::QueryType
end
```
--------------------------------
### Define a Batched Calculation Source for User Following
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/dataloader/sources.md
Implement a source for batched calculations, such as checking if a user follows others. This example optimizes by performing a single database query to check follow relationships for multiple users. It returns a boolean for each handle provided.
```ruby
# for a given user, batch checks to see whether this user follows another user.
# (The default `user.followings.where(followed_user_id: followed).exists?` would cause N+1 queries.)
class Sources::UserFollowingExists < GraphQL::Dataloader::Source
def initialize(user)
@user = user
end
def fetch(handles)
# Prepare a `SELECT id FROM users WHERE handle IN(...)` statement
user_ids = ::User.where(handle: handles).select(:id)
# And use it to filter this user's followings:
followings = @user.followings.where(followed_user_id: user_ids)
# Now, for followings that _actually_ hit a user, get the handles for those users:
followed_users = ::User.where(id: followings.select(:followed_user_id))
# Finally, return a result set, with one entry (true or false) for each of the given `handles`
handles.map { |h| !!followed_users.find { |u| u.handle == h }}
end
end
```
--------------------------------
### Define Subscription Root Type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/root_types.md
Example of defining a `SubscriptionType` that references a `Subscriptions::CommentAdded` subscription.
```ruby
class Types::SubscriptionType < GraphQL::Schema::Object
field :comment_added, subscription: Subscriptions::CommentAdded
end
```
--------------------------------
### Define Mutation Root Type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/root_types.md
Example of defining a `MutationType` that references a `Mutations::AddPost` mutation.
```ruby
class Types::MutationType < GraphQL::Schema::Object
field :create_post, mutation: Mutations::AddPost
end
```
--------------------------------
### Run TypeScript Compiler
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/javascript_client/readme.md
Start the TypeScript compiler in watch mode for continuous compilation during development.
```bash
yarn tsc -w
```
--------------------------------
### Migrating Instance Methods to Class Methods
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/execution/migration.md
Demonstrates how to refactor instance methods to call new class methods for supporting batching, ensuring a single source of truth.
```ruby
field :unpublished_posts, [Types::Post], resolve_each: true
# Support batching:
def self.unpublished_posts(object, context)
object.posts.where(published: false).order("created_at DESC")
end
# Support legacy in a DRY way by calling the class method:
def unpublished_posts
self.class.unpublished_posts(object, context)
end
```
--------------------------------
### GraphQL Subscription Query with Room ID
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/subscription_classes.md
Example of a GraphQL subscription query that requires a `roomId` argument.
```graphql
subscription($roomId: ID!) {
messageWasPosted(roomId: $roomId) {
message {
author { handle }
body
postedAt
}
}
}
```
--------------------------------
### Return Errors as Data with `#ready?`
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/mutations/mutation_authorization.md
The `#ready?` method can return `false` along with a hash of errors to provide structured error data instead of raising an exception.
```ruby
def ready?
if !context[:current_user].allowed?
return false, { errors: ["You don't have permission to do this"]}
else
true
end
end
```
--------------------------------
### Rails Controller for Streaming @defer Responses
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/defer/setup.md
This Rails controller example demonstrates how to stream HTTP Multipart patches to an Apollo Client using ActionController::Live when deferred fields are present.
```ruby
class GraphqlController < ApplicationController
# Support `response.stream` below:
include ActionController::Live
def execute
# ...
result = MySchema.execute(query, variables: variables, context: context, operation_name: operation_name)
# Check if this is a deferred query:
if (deferred = result.context[:defer])
# Required for Rack 2.2+, see https://github.com/rack/rack/issues/1619
response.headers['Last-Modified'] = Time.now.httpdate
# Use built-in `stream_http_multipart` with Apollo-Client & ActionController::Live
deferred.stream_http_multipart(response, incremental: true)
else
# Return a plain, non-deferred result
render json: result
end
ensure
# Always make sure to close the stream
response.stream.close
end
end
```
--------------------------------
### GraphQL Union Definition
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/unions.md
Example of a union type defined in GraphQL Schema Definition Language (SDL).
```graphql
union MediaItem = AudioClip | VideoClip | Image | TextSnippet
```
--------------------------------
### Run Unit Tests
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/development.md
Executes the test suite and Rubocop, or tests only. Use TEST= to specify a file.
```bash
bundle exec rake # tests & Rubocop
bundle exec rake test # tests only
```
```bash
bundle exec rake test TEST=spec/graphql/query_spec.rb
# run tests in `query_spec.rb` only
```
--------------------------------
### Example Operation ID
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/operation_store/overview.md
This shows the format of an operation ID that clients send to run a persisted query.
```ruby
params[:operationId] # => "relay-app-v1/810c97f6631001..."
```
--------------------------------
### Configure Routes for OperationStore Dashboard and Sync API
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/operation_store/getting_started.md
Add routes for the OperationStore Dashboard and Sync API by including GraphQL::Pro's routing extensions and mounting the respective Rack apps. The Sync API has built-in authorization, while the Dashboard requires separate authorization setup.
```ruby
# config/routes.rb
# Include GraphQL::Pro's routing extensions:
using GraphQL::Pro::Routes
Rails.application.routes.draw do
# ...
# Add the Dashboard
# TODO: authorize, see the dashboard guide
mount MySchema.dashboard, at: "/graphql/dashboard"
# Add the Sync API (authorization built-in)
mount MySchema.operation_store_sync, at: "/graphql/sync"
end
```
--------------------------------
### Implement fetchQuery and Subscription Handler
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/relay_subscriptions.md
Set up the `fetchOperation` function to handle GraphQL requests, including logic for production (using `operationId`) and development (using `query`). The `fetchQuery` function then processes the response, and the `subscriptionHandler` uses `fetchOperation` for initial subscription requests. Finally, create a Relay `Network` instance.
```javascript
// This function sends a GraphQL query to the server
const fetchOperation = function(operation, variables, cacheConfig) {
const bodyValues = {
variables,
operationName: operation.name
}
const useStoredOperations = process.env.NODE_ENV === "production"
if (useStoredOperations) {
// In production, use the stored operation
bodyValues.operationId = OperationStoreClient.getOperationId(operation.name)
} else {
// In development, use the query text
bodyValues.query = operation.text
}
return fetch('http://localhost:3000/graphql', {
method: 'POST',
opts: {
credentials: 'include',
},
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(bodyValues),
})
}
// `fetchQuery` uses `fetchOperation`, but returns a Promise of JSON
const fetchQuery = (operation, variables, cacheConfig, uploadables) => {
return fetchOperation(operation, variables, cacheConfig).then(response => {
return response.json()
})
}
// Subscriptions uses the same `fetchOperation` function for initial subscription requests
const subscriptionHandler = createRelaySubscriptionHandler({pusher: pusherClient, fetchOperation: fetchOperation})
// Combine them into a `Network`
const network = Network.create(fetchQuery, subscriptionHandler)
```
--------------------------------
### GraphQL SDL Non-Null Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/non_nulls.md
Illustrates non-null types in GraphQL Schema Definition Language for fields and arguments.
```graphql
type User {
# This field _always_ returns a String, never returns `null`
handle: String!
# `since:` _must_ be passed a `DateTime` value, it can never be omitted or passed `null`
followers(since: DateTime!): [User!]!
}
```
--------------------------------
### Retrieving a Specific Type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/introspection.md
Use the `__type` field to get details about a specific type within the schema by its name.
```graphql
{ __type(name: "User") {
name
kind
}
}
```
--------------------------------
### Sync Relay Project Queries
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/sync.md
Use this command to sync queries from a Relay project's __generated__ directory. It requires specifying the path to the generated files, an output file for the client, and the GraphQL server URL.
```bash
graphql-ruby-client sync --path=src/__generated__ --outfile=src/OperationStoreClient.js --url=...
```
--------------------------------
### Using a custom runtime directive in a GraphQL query
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/directives.md
Example of how to apply a custom runtime directive to a field in a GraphQL query.
```graphql
query {
field @myDirective {
id
}
}
```
--------------------------------
### Custom Limiter Subclass Example
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/limiters/active_operations.md
Create a subclass of ActiveOperationsLimiter to customize its behavior, such as defining custom limiter keys or limits.
```ruby
# app/graphql/limiters/active_operations.rb
class Limiters::ActiveOperations < GraphQL::Enterprise::ActiveOperationsLimiter
# override methods here
end
```
--------------------------------
### Configure RuntimeLimiter with ConnectionPool
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/limiters/redis.md
Use this configuration to integrate `RuntimeLimiter` with a `ConnectionPool` for managing Redis connections.
```ruby
use GraphQL::Enterprise::RuntimeLimiter, # or ActiveOperationLimiter
connection_pool: ConnectionPool.new(...) { ... }
```
--------------------------------
### Define GraphQL Schema Type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/index.html
Example of defining a GraphQL object type for a user profile, specifying fields and their types.
```ruby
class Types::ProfileType < Types::BaseObject
field :id, ID, null: false
field :name, String, null: false
field :avatar, Types::PhotoType
end
```
--------------------------------
### Integrate ActionCable subscriptions with GraphiQL
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/graphiql_subscriptions.md
Use `createActionCableFetcher` to integrate ActionCable subscriptions. Initialize an ActionCable consumer and pass it to the fetcher. This fetcher sends subscription operations via ActionCable and queries/mutations via HTTP POST.
```javascript
import { createConsumer } from "@rails/actioncable"
import createActionCableFetcher from 'graphql-ruby-client/subscriptions/createActionCableFetcher';
// Initialize a client
const actionCable = createConsumer()
// Initialize a new fetcher and pass it to GraphiQL below
var fetcher = createActionCableFetcher({ consumer: actionCable, url: "/graphql" })
const root = createRoot(document.getElementById('root'))
root.render()
```
--------------------------------
### Create Pusher Subscription Handler
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/relay_subscriptions.md
Use this to set up a Relay Modern subscription handler with Pusher. Ensure you have a Pusher client and a `fetchOperation` function.
```javascript
import createRelaySubscriptionHandler from "graphql-ruby-client/subscriptions/createRelaySubscriptionHandler"
var Pusher = require("pusher-js")
var pusherClient = new Pusher(appKey, options)
function fetchOperation(operation, variables, cacheConfig) {
return fetch(...)
}
var subscriptionHandler = createRelaySubscriptionHandler({
pusher: pusherClient,
fetchOperation: fetchOperation
})
var network = Network.create(fetchQuery, subscriptionHandler)
```
--------------------------------
### GraphQL Subscription Query with Generated Payload
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/subscription_classes.md
Example of a GraphQL subscription query that utilizes the fields defined in the generated payload type.
```graphql
subscription($roomId: ID!) {
messageWasPosted(roomId: $roomId) {
room {
name
}
message {
author {
handle
}
body
postedAt
}
}
}
```
--------------------------------
### Define Extension with Options in Schema
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/field_extensions.md
Illustrates how to pass options to an extension directly within the field definition using the `extensions:` hash.
```ruby
field :name, String, null: false, extensions: [LimitExtension => { limit: 20 }]
```
--------------------------------
### Itemized Scoring Distribution
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/complexity_and_depth.md
This example shows the itemized scoring distribution based on defined complexity parameters for leaf, composite, and connection fields.
```graphql
query {
node(id: "123") { # 1, composite
id # 0, leaf
...on HasMetafields {
metafield(key: "a") { # 1, composite
value # 0, leaf
}
metafields(first: 10) { # 1 * 10, connection
nodes { # 1, composite
value # 0, leaf
}
}
}
...on Product {
title # 0, leaf
metafield(key: "a") { # 1, composite
definition { # 1, composite
description # 0, leaf
}
}
}
...on PriceList {
name # 0, leaf
catalog { # 1, composite
id # 0, leaf
}
}
}
}
```
--------------------------------
### Automatic Camelization Enabled
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/fields/arguments.md
Arguments defined with snake_case in Ruby are automatically converted to camelCase in the GraphQL schema. This example shows the schema-level usage.
```ruby
field :posts, [PostType], null: false do
argument :start_year, Int
end
```
--------------------------------
### Prepare Query Options for Multiplex
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/multiplex.md
Build an array of query options, specifying the query string, variables, operation name, and context for each query. This prepares the data structure for concurrent execution.
```ruby
context = {
current_user: current_user,
}
queries = [
{
query: "query Query1 { someField }",
variables: {},
operation_name: 'Query1',
context: context,
},
{
query: "query Query2 ($num: Int){ plusOne(num: $num) }",
variables: { num: 3 },
operation_name: 'Query2',
context: context,
}
]
```
--------------------------------
### Getting Type Names for Union/Interface Members
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/introspection.md
When querying unions or interfaces, `__typename` returns the specific object type for each item in the result set.
```graphql
{ search(term: "puppies") {
title
__typename
}
}
```
--------------------------------
### Get Operation ID with OperationStoreClient
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/sync.md
Use `OperationStoreClient.getOperationId` to retrieve the server-side alias for a given operation name. This is useful for plain JavaScript integrations.
```js
var OperationStoreClient = require("./OperationStoreClient")
OperationStoreClient.getOperationId("AppHomeQuery") // => "my-frontend-app/7a8078c7555e20744cb1ff5a62e44aa92c6e0f02554868a15b8a1cbf2e776b6f"
OperationStoreClient.getOperationId("ProductDetailQuery") // => "my-frontend-app/6726a3b816e99b9971a1d25a1205ca81ecadc6eb1d5dd3a71028c4b01cc254c1"
```
--------------------------------
### Configure urql with Pusher Subscriptions
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/javascript_client/urql_subscriptions.md
Use this configuration to enable urql subscriptions with a Pusher backend. Ensure Pusher is installed and configured in your GraphQL-Ruby application.
```javascript
import SubscriptionExchange from "graphql-ruby-client/subscriptions/SubscriptionExchange"
import Pusher from "pusher"
import { Client, defaultExchanges, subscriptionExchange } from 'urql'
const pusherClient = new Pusher("your-app-key", { cluster: "us2" })
const forwardToPusher = SubscriptionExchange.create({ pusher: pusherClient })
const client = new Client({
url: '/graphql',
exchanges: [
...defaultExchanges,
subscriptionExchange({
forwardSubscription: forwardToPusher
}),
],
});
```
--------------------------------
### Cap List Field Items with `prepare:`
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/fields/limits.md
Use the `prepare:` argument within a field definition to cap the number of items returned by a list. This example limits items to a maximum of 30, while providing a default limit of 20.
```ruby
field :items, [Types::ItemType] do
# Cap the number of items at 30
argument :limit, Integer, default_value: 20, prepare: ->(limit, ctx) {[limit, 30].min}
end
def items(limit:)
object.items.limit(limit)
end
```
--------------------------------
### Defining a specific Enum type
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/enums.md
This example shows how to define a concrete enum type `MediaCategory` by extending the base enum class and defining its values.
```ruby
# app/graphql/types/media_category.rb
class Types::MediaCategory < Types::BaseEnum
value "AUDIO", "An audio file, such as music or spoken word"
value "IMAGE", "A still image, such as a photo or graphic"
value "TEXT", "Written words"
value "VIDEO", "Motion picture, may have audio"
end
```
--------------------------------
### Build and Test GraphQL-CParser
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/development.md
Builds the C parser extension and then runs the test suite with the GRAPHQL_CPARSER environment variable set.
```bash
bundle exec rake build_ext
```
```bash
GRAPHQL_CPARSER=1 bundle exec rake test
```
--------------------------------
### Configure Extras for an Extension
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/type_definitions/field_extensions.md
Shows how to configure `extras` for a field extension, allowing it to access additional metadata like the AST node or errors.
```ruby
class MyExtension < GraphQL::Schema::FieldExtension
extras [:ast_node, :errors, ...]
end
```
--------------------------------
### Accessing Edge Relationship Metadata
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/pagination/connection_concepts.md
This example demonstrates how edges can expose metadata specific to the relationship between two objects, such as 'joinedAt' and 'role' for a team membership.
```graphql
team {
# this is the team name
name
members(first: 10) {
edges {
# this is a team membership
joinedAt
role
node {
# this is the person on the team
name
}
}
}
}
```
--------------------------------
### Tenant Selection for Pusher/Ably Context Loading
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/subscriptions/multi_tenant.md
Customize the `load_context` method in Pusher or Ably subscriptions to select the tenant before building the context hash. This is crucial if context objects need to be loaded from the database in a tenant-aware manner.
```ruby
class CustomSubscriptions < GraphQL::Pro::PusherSubscriptions # or `GraphQL::Pro::AblySubscriptions`
def dump_context(ctx)
JSON.dump(ctx.to_h)
end
def load_context(ctx_string)
ctx_data = JSON.parse(ctx_string)
MultiTenancy.select_tenant(ctx_data["tenant"]) do
# Build a symbol-keyed hash, loading objects from the database if necessary
# to use a `context: ...`
end
end
end
```
--------------------------------
### Define Field with Extras
Source: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/fields/introduction.md
Use the `extras:` option in field definition to specify runtime objects to be injected into the field method. The `ast_node` is one such example.
```ruby
field :my_field, String, null: false, extras: [:ast_node]
```