Validation
Arguments can be validated at runtime using built-in or custom validators.
Validations are configured in argument(...) calls on fields or input objects:
argument :home_phone, String, description: "A US phone number", validates: { format: { with: /\d{3}-\d{3}-\d{4}/ } }
or, validates required: { ... } inside a field ... do ... end block:
field :comments, [Comment], description: "Find comments by author ID or author name" do argument :author_id, ID, required: false argument :author_name, String, required: false # Either `authorId` or `authorName` must be provided by the client, but not both: validates required: { one_of: [:author_id, :author_name] } end
Validations can be provided with a keyword (validates: { ... }) or with a method inside the configuration block (validates ...).
Built-In Validations
See each validator’s API docs for details:
-
length: { maximum: ..., minimum: ..., is: ..., within: ... }Schema::Validator::LengthValidator -
format: { with: /.../, without: /.../ }Schema::Validator::FormatValidator -
numericality: { greater_than:, greater_than_or_equal_to:, less_than:, less_than_or_equal_to:, other_than:, odd:, even: }Schema::Validator::NumericalityValidator -
inclusion: { in: [...] }Schema::Validator::InclusionValidator -
exclusion: { in: [...] }Schema::Validator::ExclusionValidator -
required: { one_of: [...] }Schema::Validator::RequiredValidator -
allow_blank: true|falseSchema::Validator::AllowBlankValidator -
allow_null: true|falseSchema::Validator::AllowNullValidator -
all: { ... }Schema::Validator::AllValidator
Some of the validators accept customizable messages for certain validation failures; see the API docs for examples.
allow_blank: and allow_null: may affect other validations, for example:
validates: { format: { with: /\A\d{4}\Z/ }, allow_blank: true }
Will permit any String containing four digits, or the empty string ("") if Rails is loaded. (GraphQL-Ruby checks for .blank?, which is usually defined by Rails.)
Alternatively, they can be used alone, for example:
argument :id, ID, required: false, validates: { allow_null: true }
Will permit any query that passes id: null.
Validation options may also be passed as procs that accept no parameters, for example:
validates :title, String, validates: { format: { with: -> { Flipper.enabled?(:new_title_format) ? NEW_TITLE_FORMAT : /.*/ }}
Custom Validators
You can write custom validators, too. A validator is a class that extends GraphQL::Schema::Validator. It should implement:
-
def initialize(..., **default_options)to accept any validator-specific options and pass along the defaults tosuper(**default_options) -
def validate(_empty, context, value)which is called at runtime to validatevalue. It may return a String error message or an Array of Strings. GraphQL-Ruby will add those messages to the top-level"errors"array along with runtime context information.
Then, custom validators can be attached either:
-
directly, passed to
validates, likevalidates: { MyCustomValidator => { some: :options } -
by keyword, if the keyword is registered with
GraphQL::Schema::Validator.install(:custom, MyCustomValidator). (That would supportvalidates: { custom: { some: :options }}).)
Validators are initialized when the schema is constructed (at application boot), and validate(...) is called while executing the query. There’s one Validator instance for each configuration on each field, argument, or input object. (Validator instances aren’t shared.)