Search code examples
elixirphoenix-frameworkuuidhas-manybelongs-to

Using has_many - belongs_to association when using UUID (String)


I'm trying to associate two models (user & country) where:

· A country has_many users.

· A user belongs_to one country.

Also, I use UUIDs as Primary Key for the two models, so I don't have an :id type to relate them and only have strings to do it. The countries are static but I will create a lot of users.

How should I relate this two models and which parameters should I write in the two functions in the schemas (has_many & belongs_to)? And which function should I call to relate them: cast_assoc, build_assoc or put_assoc?

Thanks!!

  @primary_key {:uuid, :string, []}
  @derive {Phoenix.Param, key: :uuid}
  schema "countries" do
    field :country_name, :string

    has_many :users, UserManagement.User, foreign_key: :country_id
  end
  @primary_key {:uuid, :string, []}
  @derive {Phoenix.Param, key: :uuid}
  schema "users" do
    field :nickname, :string
    field :password, :string, virtual: true

    belongs_to :country, UserManagement.Country, references: :uuid

    timestamps()
  end

Solution

  • You can pass the :type option in belongs_to:

    belongs_to :country, UserManagement.Country, references: :uuid, type: :string
    

    And all of the association functions and helpers should work. You can find all available options here: https://hexdocs.pm/ecto/Ecto.Schema.html#belongs_to/3


    If you want all of your schemas to use UUID, you can encapsulate the setup in a custom module like this:

    defmodule MyApp.Schema do
      defmacro __using__(_) do
        quote do
          use Ecto.Schema
          @primary_key {:uuid, :string, []}
          @foreign_key_type :string
          @derive {Phoenix.Param, key: :uuid}
        end
      end
    end
    

    And now instead of use Ecto.Schema you do use MyApp.Schema.