graphql-ruby Documentation

repository·master·Indexed 26 days ago

https://github.com/rmosolgo/graphql-ruby

Core GraphQL implementation for Ruby, featuring a JavaScript client (graphql-ruby-client v1.15.2) and extensions for Rails. Includes documentation for graphql-enterprise (limiters, ObjectCache, Changesets), graphql-pro (Pundit/CanCan integration, OperationStore, Dashboard), and graphql-relay (global node identification, custom connection types), as well as guides on implementing object, field, and argument authorization.

Tokens
107K
Snippets
357
Records
534
Agent score
90%

What's inside graphql-ruby

  1. Overview of GraphQL ObjectCache

    master

    GraphQL::Enterprise::ObjectCache is an application-level cache for GraphQL-Ruby servers. It improves performance by storing a cache fingerprint for each object in a query and serving cached responses as long as those fingerprints remain unchanged. This reduces latency for clients and decreases the load on your database and application server.

    How it works:

    1. Fingerprinting: Before running a query, it generates a fingerprint using GraphQL::Query#fingerprint and Schema.context_fingerprint_for(ctx).
    2. Cache Lookup: It checks the backend for a matching fingerprint.
    3. Validation: If a match is found, it fetches the previously visited objects and compares their current fingerprints to the cached ones. It also verifies .authorized? for each object (unless re-authorization is explicitly disabled).
    4. Cache Miss/Update: If no match is found or fingerprints differ, the query is re-evaluated. During execution, ObjectCache collects the IDs and fingerprints of encountered objects, then writes the new result and fingerprints to the cache.
  2. Overview of GraphQL-Enterprise Changesets

    master

    Changesets are a feature of GraphQL-Enterprise that allow you to evolve your schema by releasing specific changes—including breaking changes—to clients based on the schema version they are using. While GraphQL is designed to be additive (adding new fields, arguments, or types), Changesets enable you to redefine existing fields, use old names for new types, or add/remove enum values while maintaining backward compatibility for older clients.

    Use Changesets when you need to perform non-additive changes, such as removing a field or redefining a schema element in a way that would otherwise break existing queries.

  3. Overview of GraphQL-Ruby Authorization Framework

    master

    GraphQL-Ruby provides a built-in authorization framework to secure your API at different layers. The framework includes:

    • Visibility: Hides specific parts of the GraphQL schema from users who lack the necessary permissions, preventing them from even seeing certain fields or types.
    • Authorization: Checks permissions on application objects during the execution phase to ensure the user is allowed to access the specific data returned.

    Additionally, GraphQL::Pro offers specialized integrations for popular Ruby authorization libraries:

    • CanCan
    • Pundit
  4. Explore related libraries and tools for graphql-ruby

    master

    The graphql-ruby ecosystem includes several specialized libraries for performance, security, and integration. Key categories include:

    Performance & Caching

    • graphql-batch: Batched query execution strategy.
    • graphql-cache: Resolver-level caching.
    • graphql-ruby-fragment_cache: Caching for response fragments.
    • graphql-query-resolver: Minimizes N+1 queries.

    Rails Integrations

    • graphql-activerecord: ActiveRecord integration.
    • graphql-rails-resolve: Rails resolver helpers.
    • graphql-rails_logger: Readable GraphQL query logging.
    • graphql_rails: A Rails-centric GraphQL build tool.
    • graphql-rails-generators: Generates mutations, types, and input types from ActiveRecord models.
    • apollo_upload_server-ruby: Middleware for file uploads using multipart/form-data.
    • graphql-sources: Common sources for ActiveRecord, ActiveStorage, and Rails.cache.

    Security & Authorization

    • graphql-devise: Authentication interface for Devise.
    • action_policy-graphql: Integration with action_policy for authorization.

    Advanced Schema & API Features

    • graphql-stitching: Combines multiple local and remote schemas into a single graph.
    • apollo-federation-ruby: Implementation of the Apollo Federation subgraph spec.
    • graphql-ruby-persisted_queries: Implementation of Apollo persisted queries.
    • graphql-filters: DSL for defining typed filters for list fields.
    • search_object_graphql: DSL for defining search resolvers.
    • graphql-groups: DSL for group- and aggregation queries.
  5. Understand GraphQL Rate Limiters in GraphQL::Enterprise

    master

    Unlike REST APIs that typically limit the number of requests, GraphQL::Enterprise provides rate limiting based on resource consumption and concurrency to better handle the variable cost of GraphQL queries. It offers two primary types of limiters:

    1. Active Operation Limiter: Limits the number of operations a client can run at a time (concurrency). If a client exceeds the limit, incoming operations are rejected with an error and can be retried once an active operation completes.
    2. Runtime Limiter: Limits the total amount of processing time a client consumes within a specific time window (e.g., total seconds of execution per minute). This manages the total server load regardless of how many operations are running concurrently.
  6. Understand GraphQL Introspection

    master

    GraphQL includes a built-in introspection system that allows clients to query the schema's structure. This is commonly used by tools like GraphiQL to provide autocomplete and documentation.

    Key components include:

    • __schema: A root-level field containing data about the schema (entry points, types, directives).
    • __type(name: String!): A root-level field that returns data about a specific type by name.
    • __typename: A field that can be added to any selection to return the name of the object type being queried. This is particularly useful for resolving types in unions and interfaces.
    {
      __schema {
        queryType {
          name
        }
      }
    }
    # Returns:
    # {
    #   "data": {
    #     "__schema": {
    #       "queryType": {
    #         "name": "Query"
    #       }
    #     }
    #   }
    # }
  7. Understand Persisted Queries with OperationStore

    master

    Persisted queries allow clients to invoke GraphQL operations (query, mutation, or subscription) by reference rather than sending the full query string over the network.

    Instead of sending a large GraphQL document, the client sends:

    • Client name: Identifies the client making the request.
    • Query alias: Specifies which stored operation to run (e.g., @relayHash).
    • Query variables: Provides values for the stored operation.

    GraphQL::Pro::OperationStore manages this by maintaining a normalized, deduplicated database of these queries using either an ActiveRecord or Redis backend. This improves security by allowing you to whitelist queries, increases efficiency by reducing bandwidth, and improves visibility by indexing field and argument usage.

  8. Understand pagination in GraphQL-Ruby

    master
    GraphQL-Ruby provides several implementations of Relay's "connection"-style pagination. Developers can use built-in connection patterns or implement custom connection types and definitions to handle large datasets efficiently. For a deep dive into the underlying mechanics, refer to the official GraphQL pagination documentation.
  9. Understand GraphQL Subscriptions concepts

    master

    GraphQL Subscriptions allow clients to observe specific events and receive live updates (e.g., via WebSockets) from the server. Implementing subscriptions requires understanding these core concepts:

    • Subscription Type: The root-level entry point for all subscription queries in your schema.
    • Subscription Classes: Resolver classes that handle the initial subscription request and all subsequent updates.
    • Triggers: The mechanism that starts the update process by sending a name and payload to GraphQL after an application event occurs.
    • Implementation: The application-specific plumbing required to manage state, transport (delivery), and queueing (distributing the work of re-running queries).
    • Broadcasts: An optimization that allows sending the same GraphQL result to multiple subscribers simultaneously, rather than handling each subscription in isolation.
  10. Understand Connection pagination concepts

    master

    Connection pagination is a standard solution for GraphQL APIs (originating from Relay) that uses three core object types to manage one-to-many relationships:

    • Connections: Generic types that represent a relationship. They provide access to the list items and contain metadata about the collection (e.g., totalCount).
    • Edges: Generic types representing the link between a parent and a child. Edges are used to expose relationship-specific metadata (e.g., a joinedAt timestamp on a membership).
    • Nodes: The actual data objects (list items) within the connection (e.g., a Post object within a PostsConnection).

    Use Edges when the relationship itself has unique data. Use Nodes for direct, simplified access to the items when relationship metadata is not required.

  11. Compare GraphQL::Dataloader and GraphQL::Batch

    master

    Both GraphQL::Dataloader and GraphQL::Batch solve the problem of batch loading to prevent N+1 queries, but they differ in implementation and usage:

    • Concurrency Primitive: GraphQL::Batch uses Promises from promise.rb. GraphQL::Dataloader uses Ruby's Fiber API, allowing for transparent pausing and resuming of work without explicit promise chaining.
    • Scope: GraphQL::Dataloader is designed specifically for use within GraphQL and cannot currently be used independently.
    • Complexity: GraphQL::Dataloader aims to reduce code complexity by removing the need for .then blocks and manual promise management, leveraging Fibers to return requested objects directly.
  12. Configure a Custom Abilities Class for CanCan

    master

    The CanCan integration looks for a top-level ::Ability class by default. If your application uses a different class for authorization, you must provide an instance of that class in the GraphQL context using the key :can_can_ability.

    A common pattern is to inject this instance within your schema's execute method, passing the current user to the abilities class constructor.

    class MySchema < GraphQL::Schema
      # Override `execute` to provide a custom Abilities instance for the CanCan integration
      def self.execute(*args, context: {}, **kwargs)
        # Assign `context[:can_can_ability]` to an instance of our custom class
        context[:can_can_ability] = MyAuthorization::CustomAbilitiesClass.new(context[:current_user])
        super
      end
    end