Module: GraphQL::Models::Reflection

Defined in:
lib/graphql/models/reflection.rb

Class Method Summary collapse

Class Method Details

.attribute_graphql_type(model_class, attribute) ⇒ Object

Returns a struct that tells you the input and output GraphQL types for an attribute



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/graphql/models/reflection.rb', line 37

def attribute_graphql_type(model_class, attribute)
  # See if it's an enum
  if model_class.graphql_enum_types.include?(attribute)
    type = model_class.graphql_enum_types[attribute]
    DatabaseTypes::TypeStruct.new(type, type)
  else
    # See if it's a registered scalar type
    active_record_type = model_class.type_for_attribute(attribute.to_s)

    if active_record_type.type.nil?
      raise ArgumentError, "The type for attribute #{attribute} wasn't found on #{model_class.name}"
    end

    result = DatabaseTypes.registered_type(active_record_type.type)

    if !result
      raise "The type #{active_record_type} is not registered with DatabaseTypes (attribute #{attribute} on #{model_class.name})"
    end

    # Arrays: Rails doesn't have a generalized way to detect arrays, so we use this method to do it:
    if active_record_type.class.name.ends_with?('Array')
      DatabaseTypes::TypeStruct.new(result.input.to_list_type, result.output.to_list_type)
    else
      result
    end
  end
end

.is_required(model_class, attr_or_assoc) ⇒ Object

Determines if the attribute (or association) is required by examining presence validators and the nullability of the column in the database



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/graphql/models/reflection.rb', line 19

def is_required(model_class, attr_or_assoc)
  # Check for non-nullability on the column itself
  return true if model_class.columns_hash[attr_or_assoc.to_s]&.null == false

  # Check for a presence validator on the association
  return true if model_class.validators_on(attr_or_assoc)
    .select { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) }
    .reject { |v| v.options.include?(:if) || v.options.include?(:unless) }
    .any?

  # If it's a belongs_to association, check for nullability on the foreign key
  reflection = model_class.reflect_on_association(attr_or_assoc)
  return true if reflection && reflection.macro == :belongs_to && is_required(model_class, reflection.foreign_key)

  false
end

.possible_values(model_class, attribute) ⇒ Object

Returns the possible values for an attribute on a model by examining inclusion validators



7
8
9
10
11
12
13
14
15
# File 'lib/graphql/models/reflection.rb', line 7

def possible_values(model_class, attribute)
  # Get all of the inclusion validators
  validators = model_class.validators_on(attribute).select { |v| v.is_a?(ActiveModel::Validations::InclusionValidator) }

  # Ignore any inclusion validators that are using the 'if' or 'unless' options
  validators = validators.reject { |v| v.options.include?(:if) || v.options.include?(:unless) || v.options[:in].blank? }
  return nil unless validators.any?
  validators.map { |v| v.options[:in] }.reduce(:&)
end