Module: Quail::Resource::TypeBuilder::AssociationBuilder
- Defined in:
- lib/quail/resource/type_builder/association_builder.rb
Overview
Wires up association fields (belongs_to, has_one, has_many, polymorphic) on a GraphQL type.
Class Method Summary collapse
- .add_association_field(type_class, name, kind, assoc_type, ar_assoc) ⇒ Object
- .add_explicit_resource_field(type_class, model, name, config) ⇒ Object
- .add_fields(resource_class) ⇒ Object
- .add_polymorphic_field(type_class, name, config) ⇒ Object
- .add_reflected_field(type_class, model, name, config) ⇒ Object
- .add_single(type_class, model, name, config) ⇒ Object
- .build_union_type(name, config) ⇒ Object
- .resolve_polymorphic_types(types) ⇒ Object
Class Method Details
.add_association_field(type_class, name, kind, assoc_type, ar_assoc) ⇒ Object
80 81 82 83 84 85 86 87 88 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 80 def self.add_association_field(type_class, name, kind, assoc_type, ar_assoc) case kind when :has_many type_class.field name, [assoc_type], null: false when :has_one, :belongs_to nullable = kind != :belongs_to || !ar_assoc || ar_assoc.[:optional] != false type_class.field name, assoc_type, null: nullable end end |
.add_explicit_resource_field(type_class, model, name, config) ⇒ Object
35 36 37 38 39 40 41 42 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 35 def self.add_explicit_resource_field(type_class, model, name, config) resource_class = TypeBuilder.resolve_resource_ref(config[:resource]) assoc_type = resource_class&.graphql_type return unless assoc_type ar_assoc = model.reflect_on_association(name) add_association_field(type_class, name, config[:kind], assoc_type, ar_assoc) end |
.add_fields(resource_class) ⇒ Object
9 10 11 12 13 14 15 16 17 18 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 9 def self.add_fields(resource_class) model = resource_class.model_class type_class = resource_class.graphql_type resource_class.association_definitions.each do |name, config| next if type_class.own_fields.key?(name.to_s) add_single(type_class, model, name, config) end end |
.add_polymorphic_field(type_class, name, config) ⇒ Object
30 31 32 33 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 30 def self.add_polymorphic_field(type_class, name, config) union_type = build_union_type(name, config) type_class.field name, union_type, null: true end |
.add_reflected_field(type_class, model, name, config) ⇒ Object
44 45 46 47 48 49 50 51 52 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 44 def self.add_reflected_field(type_class, model, name, config) ar_assoc = model.reflect_on_association(name) return unless ar_assoc assoc_type = Quail.resource_for(ar_assoc.klass)&.graphql_type return unless assoc_type add_association_field(type_class, name, config[:kind], assoc_type, ar_assoc) end |
.add_single(type_class, model, name, config) ⇒ Object
20 21 22 23 24 25 26 27 28 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 20 def self.add_single(type_class, model, name, config) if config[:polymorphic] add_polymorphic_field(type_class, name, config) elsif config[:resource] add_explicit_resource_field(type_class, model, name, config) else add_reflected_field(type_class, model, name, config) end end |
.build_union_type(name, config) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 54 def self.build_union_type(name, config) gql_name = config[:union_name] || "#{name.to_s.camelize}Union" resolved_types = resolve_polymorphic_types(config[:polymorphic_types]) assoc_name = name Class.new(GraphQL::Schema::Union) do graphql_name gql_name description "Union type for polymorphic association #{assoc_name}" possible_types(*resolved_types) define_method(:resolve_type) { |obj, _ctx| TypeBuilder.resolve_polymorphic_type(obj, assoc_name) } end end |
.resolve_polymorphic_types(types) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/quail/resource/type_builder/association_builder.rb', line 67 def self.resolve_polymorphic_types(types) types.map do |t| resource = TypeBuilder.resolve_resource_ref(t) gql_type = resource.graphql_type unless gql_type raise ArgumentError, "Polymorphic type #{t.inspect} resolved to #{resource.name} but its graphql_type is nil. " \ "Ensure the resource is registered before building associations." end gql_type end end |