Lotus.Storage.TypeCaster (Lotus v0.16.5)

Copy Markdown View Source

Casts variable values to appropriate types based on database column types.

Automatically converts string values from web UI inputs to the correct database types. Provides clear error messages when values cannot be cast to the expected type.

UUID Handling

For PostgreSQL UUID columns, we must convert string UUIDs to 16-byte binary format. Postgrex expects: <<160,238,188,153,156,11,78,248,187,109,107,185,189,56,10,17>>

We use Ecto.UUID.dump/1 which works for:

  • Standard UUIDs (v4)
  • UUIDv7 (delegates to Ecto.UUID)
  • Any other UUID type that follows RFC 9562 format

See: https://hexdocs.pm/ecto/Ecto.UUID.html#dump/1

Usage

# Cast UUID string to binary
TypeCaster.cast_value("550e8400-e29b-41d4-a716-446655440000", :uuid, %{table: "users", column: "id"})
# => {:ok, <<85, 14, 132, 0, ...>>}

# Cast integer string to integer
TypeCaster.cast_value("42", :integer, %{table: "users", column: "age"})
# => {:ok, 42}

# Invalid cast returns error
TypeCaster.cast_value("not-a-uuid", :uuid, %{table: "users", column: "id"})
# => {:error, "Failed to cast value for variable bound to users.id..."}

Summary

Functions

Cast a value to match the expected column type.

Functions

cast_value(value, db_type, column_info)

@spec cast_value(
  value :: term(),
  lotus_type :: Lotus.Storage.TypeMapper.lotus_type() | String.t(),
  column_info :: %{column: String.t(), table: String.t()}
) :: {:ok, term()} | {:error, String.t()}

Cast a value to match the expected column type.

First checks for custom type handlers registered via Application config. Falls back to built-in type casting if no custom handler is found.

Returns {:ok, cast_value} on success or {:error, reason} on failure.

Examples

cast_value("550e8400-e29b-41d4-a716-446655440000", :uuid, %{table: "users", column: "id"})
# => {:ok, <<85, 14, 132, ...>>}

cast_value("42", :integer, %{table: "users", column: "age"})
# => {:ok, 42}

cast_value("true", :boolean, %{table: "users", column: "active"})
# => {:ok, true}

Custom Type Handlers

You can register custom handlers in your config:

config :lotus, :type_handlers, %{
  "my_enum" => MyApp.MyEnumHandler
}

When a database type name (string) is passed instead of a Lotus type (atom), the registry is checked first before mapping to a Lotus type.