App generated UUID primary key

I am working on a legacy database and the primary keys on the tables are a kind of UUID which we call OID.

This OIDs are 32 char strings generated by the application.

When I create a record, I generate a new OID and assign it to the corresponding field like this.

  def create_document(attrs \\ %{}) do
    oid =
      Ecto.UUID.generate()
      |> String.upcase()
      |> String.replace("-", "")

    attrs = Map.put(attrs, "oid", oid)

    %Document{}
    |> Document.changeset(attrs)
    |> Repo.insert()
  end

Since I have to do this for every table I am wondering if there is a better way.

1 Like

Yes there is! I was looking into this the other day because I want to generate repeatable UUID’s for doc generation.

It works by setting the @primary_key module attribute :autogenerate option to a MFA. Here’s a short example:

defmodule MyApp.ExampleSchema do
  @primary_key {:id, Ecto.UUID, autogenerate: {MyApp.OIDGenerator, :generate_oid, []}}
  schema "example_schema" do
    # ... schema fields
  end
end

defmodule MyApp.OIDGenerator do
  def generate_oid do
    Ecto.UUID.generate()
    |> String.upcase()
    |> String.replace("-", "")
  end
end

And you could even put your @primary_key definition in a module and then use MyApp.Data to bring it in.

3 Likes

Yes there is.

UUID.uuid4(:hex) |> String.upcase

Thank you Jason. It worked perfectly!

1 Like

Great tip, Christopher, thank you

Thanks! I’m glad it was helpful! I haven’t been able to make actual use of that code myself yet :joy:

1 Like