Class: GraphQL::Schema::Validator::RequiredValidator

Inherits:
GraphQL::Schema::Validator show all
Defined in:
lib/graphql/schema/validator/required_validator.rb

Overview

Use this validator to require one of the named arguments to be present. Or, use Arrays of symbols to name a valid set of arguments.

(This is for specifying mutually exclusive sets of arguments.)

Examples:

Require exactly one of these arguments


field :update_amount, IngredientAmount, null: false do
  argument :ingredient_id, ID, required: true
  argument :cups, Integer, required: false
  argument :tablespoons, Integer, required: false
  argument :teaspoons, Integer, required: false
  validates required: { one_of: [:cups, :tablespoons, :teaspoons] }
end

Require one of these sets of arguments


field :find_object, Node, null: true do
  argument :node_id, ID, required: false
  argument :object_type, String, required: false
  argument :object_id, Integer, required: false
  # either a global `node_id` or an `object_type`/`object_id` pair is required:
  validates required: { one_of: [:node_id, [:object_type, :object_id]] }
end

require some value for an argument, even if it's null

field :update_settings, AccountSettings do
  # `required: :nullable` means this argument must be given, but may be `null`
  argument :age, Integer, required: :nullable
end

Constant Summary

Constants included from EmptyObjects

EmptyObjects::EMPTY_ARRAY, EmptyObjects::EMPTY_HASH

Instance Attribute Summary

Attributes inherited from GraphQL::Schema::Validator

#validated

Instance Method Summary collapse

Methods inherited from GraphQL::Schema::Validator

from_config, install, #partial_format, #permitted_empty_value?, uninstall, validate!

Constructor Details

#initialize(one_of: nil, argument: nil, message: nil, **default_options) ⇒ RequiredValidator

Returns a new instance of RequiredValidator.

Parameters:

  • one_of (Array<Symbol>) (defaults to: nil)

    A list of arguments, exactly one of which is required for this field

  • argument (Symbol) (defaults to: nil)

    An argument that is required for this field

  • message (String) (defaults to: nil)


41
42
43
44
45
46
47
48
49
50
51
# File 'lib/graphql/schema/validator/required_validator.rb', line 41

def initialize(one_of: nil, argument: nil, message: nil, **default_options)
  @one_of = if one_of
    one_of
  elsif argument
    [argument]
  else
    raise ArgumentError, "`one_of:` or `argument:` must be given in `validates required: {...}`"
  end
  @message = message
  super(**default_options)
end

Instance Method Details

#arg_keyword_to_grapqhl_name(argument_definitions, arg_keyword) ⇒ Object



99
100
101
102
# File 'lib/graphql/schema/validator/required_validator.rb', line 99

def arg_keyword_to_grapqhl_name(argument_definitions, arg_keyword)
  argument_definition = argument_definitions.find { |defn| defn.keyword == arg_keyword }
  argument_definition.graphql_name
end

#build_message(context) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/graphql/schema/validator/required_validator.rb', line 81

def build_message(context)
  argument_definitions = @validated.arguments(context).values
  required_names = @one_of.map do |arg_keyword|
    if arg_keyword.is_a?(Array)
      names = arg_keyword.map { |arg| arg_keyword_to_grapqhl_name(argument_definitions, arg) }
      "(" + names.join(" and ") + ")"
    else
      arg_keyword_to_grapqhl_name(argument_definitions, arg_keyword)
    end
  end

  if required_names.size == 1
    "%{validated} must include the following argument: #{required_names.first}."
  else
    "%{validated} must include exactly one of the following arguments: #{required_names.join(", ")}."
  end
end

#validate(_object, context, value) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/graphql/schema/validator/required_validator.rb', line 53

def validate(_object, context, value)
  matched_conditions = 0

  if !value.nil?
    @one_of.each do |one_of_condition|
      case one_of_condition
      when Symbol
        if value.key?(one_of_condition)
          matched_conditions += 1
        end
      when Array
        if one_of_condition.all? { |k| value.key?(k) }
          matched_conditions += 1
          break
        end
      else
        raise ArgumentError, "Unknown one_of condition: #{one_of_condition.inspect}"
      end
    end
  end

  if matched_conditions == 1
    nil # OK
  else
    @message || build_message(context)
  end
end