# Using With Ecto

The Ecto integration requires Ecto 3.12 or later within the 3.x series. Ecto remains
optional when using Uniq for UUID generation, parsing, and formatting alone.

You can use the type provided by this library in lieu of `Ecto.UUID`, simply use `Uniq.UUID` 
where you would use `Ecto.UUID`, and specify `:binary` or `:string` as the type of the column 
in your migrations, depending on what parameters you pass to the type. By default, with no
parameters, the UUID will be stored as `:binary`, and loaded in `:default` format. You can control
this behaviour by using the `:dump` and `:format` options to control what format is used for persistence
and in-memory, respectively. The format atoms are the same as you can pass elsewhere, i.e. `:raw`, `:default`,
`:hex`, `:urn`, and `:slug`. All of them but `:raw` are printable strings, while `:raw` is a binary-encoded
format.

If you wish to use autogenerated UUIDs with Ecto, you have a couple of options:

```elixir
# Generate UUIDv4 primary keys
@primary_key {:id, Uniq.UUID, autogenerate: true}
schema "foo" do
  ...
end

# Generate primary keys using UUIDs of a specific version
# NOTE: To autogenerate UUIDs using version 3 or 5, see below
@primary_key {:id, Uniq.UUID, version: 1, autogenerate: true}
schema "foo" do
  ...
end

# Generate primary keys using, version 3 or 5, which are namespaced
# NOTE: Uniq generates 8 bytes of cryptographically strong random data for the name, but
# you must provide a custom namespace in which these names are allocated, as the predefined
# namespaces are not a good fit for random generated ids.
@namespace Uniq.UUID.uuid5(:dns, "foo.example.com", :raw)
@primary_key {:id, Uniq.UUID, version: 5, namespace: @namespace, autogenerate: true}
schema "foo" do
  ...
end

# The same rules as above can be used to autogenerate UUIDs for any field, not just primary keys
schema "foo" do
  field :uuidv4, Uniq.UUID, autogenerate: true
  field :uuidv1, Uniq.UUID, version: 1, autogenerate: true
  # This field will be dumped to a 36-byte printable string format, and loaded into a 22-byte base64-encoded string
  field :uuidv3, Uniq.UUID, version: 3, namespace: @namespace, format: :slug, dump: :default, autogenerate: true
end
```

To use UUIDs for all keys, you can do something like this:

```elixir
# Define your global schema defaults in a module
defmodule MyApp.Schema do
  defmacro __using__(_) do
    quote do
      use Ecto.Schema
      @primary_key {:id, Uniq.UUID, autogenerate: true}
      @foreign_key_type Uniq.UUID
    end
  end
end

# Then use that module anywhere that you would use `Ecto.Schema` to apply those defaults
defmodule MyApp.Comment do
  use MyApp.Schema

  schema "comments" do
    belongs_to :post, MyApp.Post
  end
end
```

For many_to_many association you should add `type: :uuid`:

```elixir
@primary_key {:id, Uniq.UUID, version: 7, autogenerate: true, type: :uuid}
```
