Module: Synthra::SchemaInheritance

Defined in:
lib/synthra/schema_inheritance.rb

Overview

Schema Inheritance Support

Allows schemas to inherit fields from parent schemas using the < operator.

Examples:

DSL syntax

BaseUser:
  id: uuid
  created_at: timestamp

AdminUser < BaseUser:
  role: const("admin")
  permissions: array(text, 1..5)

Class Method Summary collapse

Class Method Details

.convert_field_to_node(field) ⇒ Parser::AST::FieldNode

Convert a Field object to a field node (for inheritance)

Parameters:

  • field (Field)

    the field to convert

Returns:



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/synthra/schema_inheritance.rb', line 67

def self.convert_field_to_node(field)
  Parser::AST::FieldNode.new(
    name: field.name,
    type_node: Parser::AST::TypeNode.new(
      name: field.type_name,
      arguments: field.type_args,
      nullable: field.nullable?,
      line: 0
    ),
    optional: field.optional?,
    condition: nil,
    behaviors: [],
    line: 0
  )
end

.parse_inheritance(name) ⇒ Array<String, String>

Parse inheritance syntax from schema name

Examples:

parse_inheritance("AdminUser < BaseUser")
# => ["AdminUser", "BaseUser"]

parse_inheritance("User")
# => ["User", nil]

Parameters:

  • name (String)

    the schema name potentially with inheritance

Returns:

  • (Array<String, String>)

    [schema_name, parent_name or nil]



95
96
97
98
99
100
101
102
# File 'lib/synthra/schema_inheritance.rb', line 95

def self.parse_inheritance(name)
  if name.include?("<")
    parts = name.split("<").map(&:strip)
    [parts[0], parts[1]]
  else
    [name, nil]
  end
end

.resolve(schema_node, registry) ⇒ AST::SchemaNode

Resolve inheritance for a schema node

Parameters:

  • schema_node (AST::SchemaNode)

    the schema node to process

  • registry (Registry)

    the registry containing parent schemas

Returns:

  • (AST::SchemaNode)

    schema node with inherited fields



24
25
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
57
58
59
60
# File 'lib/synthra/schema_inheritance.rb', line 24

def self.resolve(schema_node, registry)
  return schema_node unless schema_node.parent_name

  parent_schema = registry.schema(schema_node.parent_name)
  
  # Merge parent fields with child fields (child fields override parent)
  parent_field_names = parent_schema.fields.map(&:name)
  child_field_names = schema_node.fields.map { |f| f.respond_to?(:name) ? f.name : f[:name] }
  
  # Get parent fields that aren't overridden
  inherited_fields = parent_schema.fields.reject do |f|
    child_field_names.include?(f.name)
  end
  
  # Create new schema node with merged fields
  # Parent fields come first, then child fields
  merged_fields = []
  
  # Add inherited fields
  inherited_fields.each do |field|
    merged_fields << convert_field_to_node(field)
  end
  
  # Add child's own fields
  schema_node.fields.each do |field|
    merged_fields << field
  end
  
  # Create new schema node with merged fields
  Parser::AST::SchemaNode.new(
    name: schema_node.name,
    fields: merged_fields,
    behaviors: schema_node.behaviors,
    parent_name: schema_node.parent_name,
    line: schema_node.line
  )
end