Class: Types::GlobalIDType

Inherits:
BaseScalar
  • Object
show all
Defined in:
app/graphql/types/global_id_type.rb

Direct Known Subclasses

WorkItemIdType

Class Method Summary collapse

Class Method Details

.[](model_class) ⇒ Object

Construct a restricted type, that can only be inhabited by an ID of a given model class.



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
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
97
98
99
100
101
102
103
# File 'app/graphql/types/global_id_type.rb', line 39

def self.[](model_class)
  @id_types ||= {
    # WorkItem has a special class as we want to allow IssueID
    # on WorkItemID while we transition into work items
    ::WorkItem => ::Types::WorkItemIdType
  }

  @id_types[model_class] ||= Class.new(self) do
    model_name = model_class.name

    graphql_name model_name_to_graphql_name(model_name)
    description <<~MD.strip
      A `#{graphql_name}` is a global ID. It is encoded as a string.

      An example `#{graphql_name}` is: `"#{::Gitlab::GlobalId.build(model_name: model_name, id: 1)}"`.
      #{
        if deprecation = Gitlab::GlobalId::Deprecations.deprecation_by(model_name)
          "The older format `\"#{::Gitlab::GlobalId.build(model_name: deprecation.old_name, id: 1)}\"` was deprecated in #{deprecation.milestone}."
        end}

    MD

    define_singleton_method(:to_s) do
      graphql_name
    end

    define_singleton_method(:inspect) do
      graphql_name
    end

    define_singleton_method(:as) do |new_name|
      if @renamed && graphql_name != new_name
        raise "Conflicting names for ID of #{model_name}: " \
              "#{graphql_name} and #{new_name}"
      end

      @renamed = true
      graphql_name(new_name)
      self
    end

    define_singleton_method(:coerce_result) do |gid, ctx|
      global_id = ::Gitlab::GlobalId.as_global_id(gid, model_name: model_name)

      next global_id.to_s if suitable?(global_id)

      raise GraphQL::CoercionError, "Expected a #{model_name} ID, got #{global_id}"
    end

    define_singleton_method(:suitable?) do |gid|
      # an argument can be nil, so allow it here
      next true if gid.nil?

      gid.model_name.safe_constantize.present? &&
        gid.model_class.ancestors.include?(model_class)
    end

    define_singleton_method(:coerce_input) do |string, ctx|
      gid = super(string, ctx)
      next gid if suitable?(gid)

      raise GraphQL::CoercionError, "#{string.inspect} does not represent an instance of #{model_name}"
    end
  end
end

.coerce_input(value, _ctx) ⇒ GID

Parameters:

  • value (String)

Returns:

  • (GID)

Raises:

  • (GraphQL::CoercionError)


27
28
29
30
31
32
33
34
35
# File 'app/graphql/types/global_id_type.rb', line 27

def self.coerce_input(value, _ctx)
  return if value.nil?

  gid = GlobalID.parse(value)
  raise GraphQL::CoercionError, "#{value.inspect} is not a valid Global ID" if gid.nil?
  raise GraphQL::CoercionError, "#{value.inspect} is not a Gitlab Global ID" unless gid.app == GlobalID.app

  gid
end

.coerce_result(value, _ctx) ⇒ String

Parameters:

  • value (GID)

Returns:

  • (String)


21
22
23
# File 'app/graphql/types/global_id_type.rb', line 21

def self.coerce_result(value, _ctx)
  ::Gitlab::GlobalId.as_global_id(value).to_s
end

.model_name_to_graphql_name(model_name) ⇒ Object



105
106
107
# File 'app/graphql/types/global_id_type.rb', line 105

def self.model_name_to_graphql_name(model_name)
  "#{model_name.gsub(/::/, '')}ID"
end