Class: Rails::GraphQL::Argument

Inherits:
Object
  • Object
show all
Includes:
Helpers::WithDescription, Helpers::WithValidator
Defined in:
lib/rails/graphql/argument.rb

Overview

GraphQL Argument

This represents an item from the ArgumentsDefinition, which was supposed to be named InputValue, but for clarification, they work more like function arguments. See spec.graphql.org/June2018/#ArgumentsDefinition

An argument also works very similar to an ActiveRecord column. For this reason, multi dimensional arrays are not supported. You can define custom input types in order to accomplish something similar to a multi-dimensional array as input.

Options

  • :owner - The may object that this argument belongs to.

  • :null - Marks if the overall type can be null (defaults to true).

  • :array - Marks if the type should be wrapped as an array (defaults to false).

  • :nullable - Marks if the internal values of an array can be null (defaults to true).

  • :full - Shortcut for null: false, nullable: false, array: true (defaults to false).

  • :default - Sets a default value for the argument (defaults to nil).

  • :desc - The description of the argument (defaults to nil).

Direct Known Subclasses

Source::ScopedArguments::Argument

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers::WithDescription

#desc, #description=, #description?

Constructor Details

#initialize(name, type = nil, owner:, null: true, full: false, array: false, nullable: true, default: nil, desc: nil, description: nil) ⇒ Argument

Returns a new instance of Argument.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rails/graphql/argument.rb', line 44

def initialize(
  name,
  type = nil,
  owner:,
  null: true,
  full: false,
  array: false,
  nullable: true,
  default: nil,
  desc: nil,
  description: nil
)
  @owner = owner
  @name = name.to_s.underscore.to_sym
  @gql_name = @name.to_s.camelize(:lower)

  type = (name == :id ? :id : :string) if type.nil?
  if type.is_a?(Module) && type < GraphQL::Type
    @type_klass = type
    @type = type.name
  else
    @type = type.to_s.underscore.to_sym
  end

  @null     = full ? false : null
  @array    = full ? true  : array
  @nullable = full ? false : nullable

  @default = default
  @default = deserialize(@default) if @default.is_a?(::GQLParser::Token)
  self.description = desc || description
end

Instance Attribute Details

#defaultObject (readonly)

TODO: When arguments are attached to output fields they can have directives so add this possibility



39
40
41
# File 'lib/rails/graphql/argument.rb', line 39

def default
  @default
end

#gql_nameObject (readonly)

TODO: When arguments are attached to output fields they can have directives so add this possibility



39
40
41
# File 'lib/rails/graphql/argument.rb', line 39

def gql_name
  @gql_name
end

#nameObject (readonly)

TODO: When arguments are attached to output fields they can have directives so add this possibility



39
40
41
# File 'lib/rails/graphql/argument.rb', line 39

def name
  @name
end

#nodeObject

Returns the value of attribute node.



40
41
42
# File 'lib/rails/graphql/argument.rb', line 40

def node
  @node
end

#ownerObject (readonly)

TODO: When arguments are attached to output fields they can have directives so add this possibility



39
40
41
# File 'lib/rails/graphql/argument.rb', line 39

def owner
  @owner
end

#typeObject (readonly)

TODO: When arguments are attached to output fields they can have directives so add this possibility



39
40
41
# File 'lib/rails/graphql/argument.rb', line 39

def type
  @type
end

Instance Method Details

#+(other) ⇒ Object Also known as: &

This allows combining arguments



194
195
196
# File 'lib/rails/graphql/argument.rb', line 194

def +(other)
  [self, other].flatten
end

#==(other) ⇒ Object

Check if the other argument is equivalent



85
86
87
# File 'lib/rails/graphql/argument.rb', line 85

def ==(other)
  other.gql_name == gql_name && self =~ other
end

#=~(other) ⇒ Object

Check if the other argument is equivalent, regardless the name



90
91
92
93
94
95
96
# File 'lib/rails/graphql/argument.rb', line 90

def =~(other)
  return false unless other.is_a?(Argument)
  other.type_klass == type_klass &&
    other.array? == array? &&
    (other.null? == null? || other.null? && !null?) &&
    (other.nullable? == nullable? || other.nullable? && !nullable?)
end

#array?Boolean

Checks if the argument can be an array

Returns:

  • (Boolean)


112
113
114
# File 'lib/rails/graphql/argument.rb', line 112

def array?
  !!@array
end

#as_json(value = nil) ⇒ Object

Turn the given value into a JSON string representation



141
142
143
144
145
146
147
# File 'lib/rails/graphql/argument.rb', line 141

def as_json(value = nil)
  value = @default if value.nil?

  return if value.nil?
  return type_klass.as_json(value) unless array?
  value.map { |part| type_klass.as_json(part) }
end

#default_value?Boolean

Checks if a given default value was provided

Returns:

  • (Boolean)


127
128
129
# File 'lib/rails/graphql/argument.rb', line 127

def default_value?
  !@default.nil?
end

#description(namespace = nil) ⇒ Object

Override to add the kind



122
123
124
# File 'lib/rails/graphql/argument.rb', line 122

def description(namespace = nil, *)
  super(namespace || owner.try(:namespaces), :argument)
end

#deserialize(value = nil) ⇒ Object

Turn the given value into a ruby object through deserialization



150
151
152
153
154
155
156
# File 'lib/rails/graphql/argument.rb', line 150

def deserialize(value = nil)
  value = as_json if value.nil?

  return if value.nil?
  return type_klass.deserialize(value) unless array?
  value.map { |part| type_klass.deserialize(part) }
end

#initialize_copyObject



77
78
79
80
81
82
# File 'lib/rails/graphql/argument.rb', line 77

def initialize_copy(*)
  super

  @owner = nil
  @type_klass = nil
end

#inspectObject



200
201
202
203
204
205
206
207
208
209
# File 'lib/rails/graphql/argument.rb', line 200

def inspect
  result = +"#{name}: "
  result << '[' if array?
  result << type_klass.gql_name
  result << '!' if array? && !nullable?
  result << ']' if array?
  result << '!' unless null?
  result << " = #{as_json.inspect}" if default_value?
  result
end

#null?Boolean

Checks if the argument can be null

Returns:

  • (Boolean)


107
108
109
# File 'lib/rails/graphql/argument.rb', line 107

def null?
  !!@null
end

#nullable?Boolean

Checks if the argument can have null elements in the array

Returns:

  • (Boolean)


117
118
119
# File 'lib/rails/graphql/argument.rb', line 117

def nullable?
  !!@nullable
end

#to_json(value = nil) ⇒ Object

Transforms the given value to its representation in a JSON string



132
133
134
135
136
137
138
# File 'lib/rails/graphql/argument.rb', line 132

def to_json(value = nil)
  value = @default if value.nil?

  return 'null' if value.nil?
  return type_klass.to_json(value) unless array?
  value.map { |part| type_klass.to_json(part) }
end

#type_klassObject

Return the class of the type object



99
100
101
102
103
104
# File 'lib/rails/graphql/argument.rb', line 99

def type_klass
  @type_klass ||= GraphQL.type_map.fetch!(type,
    namespaces: namespaces,
    prevent_register: owner,
  )
end

#valid_input?(value) ⇒ Boolean Also known as: valid?

This checks if a given serialized value is valid for this field

Returns:

  • (Boolean)


159
160
161
162
163
# File 'lib/rails/graphql/argument.rb', line 159

def valid_input?(value)
  return null? if value.nil?
  return valid_input_array?(value) if array?
  type_klass.valid_input?(value)
end

#validate!Object

Checks if the definition of the argument is valid

Raises:



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/rails/graphql/argument.rb', line 173

def validate!(*)
  super if defined? super

  raise NameError, (+<<~MSG).squish if gql_name.start_with?('__')
    The name "#{gql_name}" is invalid. Argument names cannot start with "__".
  MSG

  raise ArgumentError, (+<<~MSG).squish unless type_klass.is_a?(Module)
    Unable to find the "#{type.inspect}" input type on GraphQL context.
  MSG

  raise ArgumentError, (+<<~MSG).squish unless type_klass.input_type?
    The "#{type_klass.gql_name}" is not a valid input type.
  MSG

  raise ArgumentError, (+<<~MSG).squish unless default.nil? || valid?(as_json(default))
    The given default value "#{default.inspect}" is not valid for this argument.
  MSG
end

#validate_output!(value) ⇒ Object

Trigger the exception based value validator



168
169
170
# File 'lib/rails/graphql/argument.rb', line 168

def validate_output!(value)
  super(value, :argument)
end