Skip to content

Handle ecto custom types by default #120

Closed

Description

@jakespracher

Is it possible to handle custom Ecto type schema fields by default? I just added one and it broke my Live Admin UI for that schema (field cannot be set or updated).

https://hexdocs.pm/ecto/Ecto.Type.html

Need to figure out how to get it working again now.

Activity

  1. tfwright commented on Oct 2, 2024

    @tfwright
    Owner

    Hi @jakespracher if by "handle" you mean offer full support without any extra config, I don't think so, because there would be no way for LiveAdmin to know how the type should be treated, unless you have something specific in mind?

    But to avoid having them break your instance I think just adding them to immutable_fields should do the trick (hidden_fields should also work but wouldn't allow you to even view the data). If that doesn't work, if you could post more info about how to replicate I can take a closer look.

    https://hexdocs.pm/live_admin/LiveAdmin.html#base_configs_schema/0

  2. jakespracher commented on Oct 2, 2024

    @jakespracher
    ContributorAuthor

    It used to be a string field and could be updated as such, but the custom type adds validation. E.g.

    defmodule App.Types.PhoneNumber do
      @moduledoc """
      An Ecto.Type for handling US phone numbers.
    
      This module provides custom casting, loading, and dumping functions for phone numbers,
      ensuring that they are properly formatted and validated as full US phone numbers.
      It uses the ExPhoneNumber library for parsing and formatting.
    
      The phone numbers are stored and returned in the E.164 format (e.g., "+12345678900").
      """
    
      use Ecto.Type
      require Logger
    
      @type t :: String.t()
    
      @impl true
      def type, do: :string
    
      @impl true
      def cast(phone_number) when is_binary(phone_number) do
        phone_number =
          if String.starts_with?(phone_number, "+1") do
            String.slice(phone_number, 2, String.length(phone_number) - 2)
          else
            phone_number
          end
    
        case ExPhoneNumber.parse(phone_number, "US") do
          {:ok, parsed} ->
            if full_us_number?(parsed) do
              {:ok, ExPhoneNumber.format(parsed, :e164)}
            else
              Logger.warning("Invalid US phone number format: #{phone_number}")
              :error
            end
    
          {:error, reason} ->
            Logger.warning("Failed to parse phone number '#{phone_number}': #{inspect(reason)}")
            :error
        end
      end
    
      def cast(_), do: :error
    
      @impl true
      def load(phone_number) when is_binary(phone_number) do
        {:ok, phone_number}
      end
    
      def load(_), do: :error
    
      @impl true
      def dump(phone_number) when is_binary(phone_number) do
        case cast(phone_number) do
          {:ok, formatted} -> {:ok, formatted}
          :error -> :error
        end
      end
    
      def dump(_), do: :error
    
      defp full_us_number?(%ExPhoneNumber.Model.PhoneNumber{} = parsed_number) do
        formatted = ExPhoneNumber.format(parsed_number, :e164)
        String.starts_with?(formatted, "+1") and String.length(formatted) == 12
      end
    end
    

    So I need to be able to teach LiveAdmin how to edit this field. Not clear on this from the linked function which I also saw in the readme

  3. changed the title [-]Handle custom types by default[/-] [+]Handle ecto custom types by default[/+] on Oct 2, 2024
  4. tfwright commented on Oct 2, 2024

    @tfwright
    Owner

    I need to be able to teach LiveAdmin how to edit this field

    This is currently only possible by overriding the form component.

  5. Repository owner locked and limited conversation to collaborators on Oct 2, 2024
  6. converted this issue into a discussion #121 on Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions