Module: Quail::Resource::TypeBuilder

Defined in:
lib/quail/resource/type_builder.rb,
lib/quail/resource/type_builder/field_builder.rb,
lib/quail/resource/type_builder/association_builder.rb

Overview

Generates GraphQL object types from resource attribute and association definitions.

Defined Under Namespace

Modules: AssociationBuilder, FieldBuilder

Class Method Summary collapse

Class Method Details

.add_association_fields(resource_class) ⇒ Object

Delegate public API so existing callers (and tests) still work.



62
# File 'lib/quail/resource/type_builder.rb', line 62

def self.add_association_fields(resource_class) = AssociationBuilder.add_fields(resource_class)

.add_polymorphic_fieldObject



64
# File 'lib/quail/resource/type_builder.rb', line 64

def self.add_polymorphic_field(...) = AssociationBuilder.add_polymorphic_field(...)

.add_single_associationObject



63
# File 'lib/quail/resource/type_builder.rb', line 63

def self.add_single_association(...) = AssociationBuilder.add_single(...)

.build_allObject



10
11
12
13
14
15
16
# File 'lib/quail/resource/type_builder.rb', line 10

def self.build_all
  # Two-pass build: first create all GraphQL types so that @graphql_type
  # is available on every resource, then wire up associations (which may
  # reference other resources' types, e.g. polymorphic unions).
  Quail.registry.each_value { |rc| build_scalar_fields(rc) unless rc.graphql_type }
  Quail.registry.each_value { |rc| AssociationBuilder.add_fields(rc) } # rubocop:disable Style/CombinableLoops
end

.build_scalar_fields(resource_class) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/quail/resource/type_builder.rb', line 18

def self.build_scalar_fields(resource_class)
  model = resource_class.model_class
  attrs = resource_class.attribute_definitions
  type_class = create_type_class(model)

  FieldBuilder.define_column_fields(type_class, model, attrs)
  FieldBuilder.define_computed_fields(type_class, attrs)
  resource_class.instance_variable_set(:@graphql_type, type_class)
  register_type_constant(model, type_class)
end

.build_union_typeObject



65
# File 'lib/quail/resource/type_builder.rb', line 65

def self.build_union_type(...) = AssociationBuilder.build_union_type(...)

.create_type_class(model) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/quail/resource/type_builder.rb', line 29

def self.create_type_class(model)
  base = Quail.base_object_class || GraphQL::Schema::Object
  Class.new(base) do
    graphql_name "#{model.name}Type"
    description "Auto-generated type for #{model.name}"
  end
end

.register_type_constant(model, type_class) ⇒ Object



37
38
39
40
# File 'lib/quail/resource/type_builder.rb', line 37

def self.register_type_constant(model, type_class)
  const_name = "#{model.name}Type"
  Object.const_set(const_name, type_class) unless Object.const_defined?(const_name)
end

.resolve_polymorphic_type(obj, assoc_name) ⇒ Object



51
52
53
54
55
56
57
58
59
# File 'lib/quail/resource/type_builder.rb', line 51

def self.resolve_polymorphic_type(obj, assoc_name)
  resource = Quail.resource_for(obj.class)
  unless resource
    raise GraphQL::ExecutionError,
          "Cannot resolve polymorphic type '#{obj.class.name}' " \
          "for association :#{assoc_name} — no resource registered"
  end
  resource.graphql_type
end

.resolve_resource_ref(ref) ⇒ Object

Resolve a resource reference that can be a Class or a String class name.



43
44
45
46
47
48
49
# File 'lib/quail/resource/type_builder.rb', line 43

def self.resolve_resource_ref(ref)
  case ref
  when Class  then ref
  when String then ref.constantize
  else raise ArgumentError, "Expected a resource class or string class name, got #{ref.inspect}"
  end
end