Class: GraphQL::Models::MutationFieldMap

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/models/mutation_field_map.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_type, find_by:, null_behavior:) ⇒ MutationFieldMap

Returns a new instance of MutationFieldMap.



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/graphql/models/mutation_field_map.rb', line 8

def initialize(model_type, find_by:, null_behavior:)
  fail ArgumentError.new("model_type must be a model") if model_type && !(model_type <= ActiveRecord::Base)
  fail ArgumentError.new("null_behavior must be :set_null or :leave_unchanged") unless [:set_null, :leave_unchanged].include?(null_behavior)

  @fields = []
  @nested_maps = []
  @path = []
  @model_type = model_type
  @find_by = Array.wrap(find_by)
  @null_behavior = null_behavior

  @find_by.each { |f| attr(f) }
end

Instance Attribute Details

#associationObject

These are used when this is a proxy_to or a nested field map



6
7
8
# File 'lib/graphql/models/mutation_field_map.rb', line 6

def association
  @association
end

#fieldsObject

Returns the value of attribute fields.



3
4
5
# File 'lib/graphql/models/mutation_field_map.rb', line 3

def fields
  @fields
end

#find_byObject

Returns the value of attribute find_by.



3
4
5
# File 'lib/graphql/models/mutation_field_map.rb', line 3

def find_by
  @find_by
end

#has_manyObject

These are used when this is a proxy_to or a nested field map



6
7
8
# File 'lib/graphql/models/mutation_field_map.rb', line 6

def has_many
  @has_many
end

#model_typeObject

Returns the value of attribute model_type.



3
4
5
# File 'lib/graphql/models/mutation_field_map.rb', line 3

def model_type
  @model_type
end

#nameObject

These are used when this is a proxy_to or a nested field map



6
7
8
# File 'lib/graphql/models/mutation_field_map.rb', line 6

def name
  @name
end

#nested_mapsObject

Returns the value of attribute nested_maps.



3
4
5
# File 'lib/graphql/models/mutation_field_map.rb', line 3

def nested_maps
  @nested_maps
end

#null_behaviorObject

Returns the value of attribute null_behavior.



3
4
5
# File 'lib/graphql/models/mutation_field_map.rb', line 3

def null_behavior
  @null_behavior
end

#pathObject

These are used when this is a proxy_to or a nested field map



6
7
8
# File 'lib/graphql/models/mutation_field_map.rb', line 6

def path
  @path
end

#requiredObject

These are used when this is a proxy_to or a nested field map



6
7
8
# File 'lib/graphql/models/mutation_field_map.rb', line 6

def required
  @required
end

Instance Method Details

#attr(attribute, type: nil, name: nil, required: nil) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/graphql/models/mutation_field_map.rb', line 26

def attr(attribute, type: nil, name: nil, required: nil)
  attribute = attribute.to_sym if attribute.is_a?(String)

  if type.nil? && !model_type
    fail ArgumentError.new("You must specify a type for attribute #{name}, because its model type is not known until runtime.")
  end

  if type.nil? && (attribute == :id || foreign_keys.include?(attribute))
    type = types.ID
  end

  if type.nil? && model_type
    type = Reflection.attribute_graphql_type(model_type, attribute).input
  end

  if required.nil?
    required = model_type ? Reflection.is_required(model_type, attribute) : false
  end

  name ||= attribute.to_s.camelize(:lower)
  name = name.to_s

  detect_field_conflict(name)

  fields.push({
    name: name,
    attribute: attribute,
    type: type,
    required: required
  })
end

#leave_null_unchanged?Boolean

Returns:

  • (Boolean)


128
129
130
# File 'lib/graphql/models/mutation_field_map.rb', line 128

def leave_null_unchanged?
  null_behavior == :leave_unchanged
end

#nested(association, find_by: nil, null_behavior:, name: nil, has_many: false, &block) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/graphql/models/mutation_field_map.rb', line 96

def nested(association, find_by: nil, null_behavior:, name: nil, has_many: false, &block)
  unless model_type
    fail ArgumentError.new("Cannot use `nested` unless the model type is known at build time.")
  end

  association = association.to_sym if association.is_a?(String)
  reflection = model_type.reflect_on_association(association)

  unless reflection
    fail ArgumentError.new("Could not find association #{association} on #{model_type.name}")
  end

  if reflection.polymorphic?
    fail ArgumentError.new("Cannot used `nested` with polymorphic association #{association} on #{model_type.name}")
  end

  has_many = reflection.macro == :has_many
  required = Reflection.is_required(model_type, association)

  map = MutationFieldMap.new(reflection.klass, find_by: find_by, null_behavior: null_behavior)
  map.name = name || association.to_s.camelize(:lower)
  map.association = association.to_s
  map.has_many = has_many
  map.required = required

  detect_field_conflict(map.name)

  map.instance_exec(&block)

  nested_maps.push(map)
end

#proxy_to(association, &block) ⇒ Object



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
# File 'lib/graphql/models/mutation_field_map.rb', line 58

def proxy_to(association, &block)
  association = association.to_sym if association.is_a?(String)

  reflection = model_type&.reflect_on_association(association)

  if reflection
    unless [:belongs_to, :has_one].include?(reflection.macro)
      fail ArgumentError.new("Cannot proxy to #{reflection.macro} association #{association} from #{model_type.name}")
    end

    klass = reflection.polymorphic? ? nil : reflection.klass
  else
    klass = nil
  end

  proxy = MutationFieldMap.new(klass, find_by: nil, null_behavior: null_behavior)
  proxy.association = association
  proxy.instance_exec(&block)

  proxy.fields.each { |f| detect_field_conflict(f[:name]) }
  proxy.nested_maps.each { |m| detect_field_conflict(m.name) }

  proxy.fields.each do |field|
    fields.push({
      name: field[:name],
      attribute: field[:attribute],
      type: field[:type],
      required: field[:required],
      path: [association] + Array.wrap(field[:path])
    })
  end

  proxy.nested_maps.each do |m|
    m.path.unshift(association)
    nested_maps.push(m)
  end
end

#typesObject



22
23
24
# File 'lib/graphql/models/mutation_field_map.rb', line 22

def types
  GraphQL::Define::TypeDefiner.instance
end