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



116
117
118
119
# File 'lib/graphql/schema/validator/required_validator.rb', line 116

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



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/graphql/schema/validator/required_validator.rb', line 98

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/graphql/schema/validator/required_validator.rb', line 53

def validate(_object, context, value)
  fully_matched_conditions = 0
  partially_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)
          fully_matched_conditions += 1
        end
      when Array
        any_match = false
        full_match = true

        one_of_condition.each do |k|
          if value.key?(k)
            any_match = true
          else
            full_match = false
          end
        end

        partial_match = !full_match && any_match

        if full_match
          fully_matched_conditions += 1
        end

        if partial_match
          partially_matched_conditions += 1
        end
      else
        raise ArgumentError, "Unknown one_of condition: #{one_of_condition.inspect}"
      end
    end
  end

  if fully_matched_conditions == 1 && partially_matched_conditions == 0
    nil # OK
  else
    @message || build_message(context)
  end
end