### 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] ```