Class: ForestAdminDatasourceGraphqlHasura::Introspection::SchemaConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/forest_admin_datasource_graphql_hasura/introspection/schema_converter.rb

Overview

Converts introspected tables into Forest Admin field schemas.

Collections are named after the Rails class name, because the Forest serializer resolves the target of a PolymorphicManyToOne from the raw value of the type column — both namings have to match.

Constant Summary collapse

ColumnSchema =
ForestAdminDatasourceToolkit::Schema::ColumnSchema
Relations =
ForestAdminDatasourceToolkit::Schema::Relations
Operators =
ForestAdminDatasourceToolkit::Components::Query::ConditionTree::Operators
BASE_OPERATORS =
[
  Operators::EQUAL, Operators::NOT_EQUAL, Operators::PRESENT, Operators::MISSING,
  Operators::IN, Operators::NOT_IN
].freeze
STRING_OPERATORS =

PRESENT is deliberately absent: on a text column an empty string is not "present", so the toolkit derives it from NOT_IN as NotIn [nil, ''].

[
  Operators::EQUAL, Operators::NOT_EQUAL, Operators::MISSING, Operators::IN, Operators::NOT_IN,
  Operators::CONTAINS, Operators::NOT_CONTAINS, Operators::I_CONTAINS, Operators::NOT_I_CONTAINS,
  Operators::STARTS_WITH, Operators::I_STARTS_WITH, Operators::ENDS_WITH, Operators::I_ENDS_WITH,
  Operators::LIKE, Operators::I_LIKE
].freeze
COMPARABLE_OPERATORS =
(BASE_OPERATORS + [Operators::GREATER_THAN, Operators::LESS_THAN,
Operators::GREATER_THAN_OR_EQUAL,
Operators::LESS_THAN_OR_EQUAL]).freeze
DATE_OPERATORS =
(COMPARABLE_OPERATORS + [Operators::BEFORE, Operators::AFTER]).freeze
ARRAY_OPERATORS =

Hasura's array comparison expressions have no pattern matching, and IncludesAll has no equivalent the filter converter can emit.

[Operators::EQUAL, Operators::NOT_EQUAL, Operators::PRESENT,
Operators::MISSING].freeze

Instance Method Summary collapse

Constructor Details

#initialize(tables, configuration) ⇒ SchemaConverter

Returns a new instance of SchemaConverter.



40
41
42
43
44
45
46
47
48
# File 'lib/forest_admin_datasource_graphql_hasura/introspection/schema_converter.rb', line 40

def initialize(tables, configuration)
  @tables = tables
  # Two indexes rather than one merged map: a table's type_name may equal
  # another table's root field name (crossed custom_root_fields renames),
  # and each lookup knows which spelling it holds.
  @tables_by_root = tables.to_h { |table| [table.name, table] }
  @tables_by_type = tables.to_h { |table| [table.type_name, table] }
  @configuration = configuration
end

Instance Method Details

#build_fields(table) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/forest_admin_datasource_graphql_hasura/introspection/schema_converter.rb', line 67

def build_fields(table)
  fields = {}
  composite_key = table.primary_key.size > 1

  table.columns.each do |column|
    fields[column.name] = convert_column(column, composite_key: composite_key)
  end

  add_polymorphics(table, fields)
  add_relationships(table, fields)
  add_reverse_polymorphics(table, fields)

  fields
end

#collection_name_of(table_name) ⇒ Object

'Banking::Account' -> 'Banking__Account'



63
64
65
# File 'lib/forest_admin_datasource_graphql_hasura/introspection/schema_converter.rb', line 63

def collection_name_of(table_name)
  rails_class_name_of(table_name).gsub('::', '__')
end

#rails_class_name_of(table_name) ⇒ Object

Rails stores the class name derived from the Postgres table, which the GraphQL type name follows — not the root field, which custom_root_fields can rename freely. Callers pass root field names, so only the root index is consulted; type_values accepts either name.



54
55
56
57
58
59
60
# File 'lib/forest_admin_datasource_graphql_hasura/introspection/schema_converter.rb', line 54

def rails_class_name_of(table_name)
  table = @tables_by_root[table_name]

  @configuration.type_values[table_name] ||
    (table && @configuration.type_values[table.type_name]) ||
    (table&.type_name || table_name).classify
end