Use foreign key as primary key with Ecto

I’ve tired to use foreign key as primary key.

ex)

create table(:users) do
end

create table(:traders, primary_key: false) do
  add :id, references(:users, type: :integer), primary_key: true
end

create table(:dum) do
    add :trader_id, references(:traders), null: false
end

defmodule Trader do
    ...
    schema "traders"
        belongs_to :user, User, foreign_key: :id, primary_key: true
        has_many :dums, Dum
    end
end

And it fails with

   ** (ArgumentError) argument error
    lib/ecto/association.ex:498: Ecto.Association.Has.get_ref/3
    lib/ecto/association.ex:448: Ecto.Association.Has.struct/3
    lib/ecto/schema.ex:1399: Ecto.Schema.association/5
    lib/ecto/schema.ex:1556: Ecto.Schema.__has_many__/4
    lib/trader.ex:11: (module)

Can I use foreign key as primary key with Ecto?

1 Like

I solved this problem by adding references: :id to has_many association.

defmodule Trader do
    ...
    schema "traders"
        belongs_to :user, User, foreign_key: :id, primary_key: true
        has_many :dums, Dum, references: :id
    end
end

But I don’t understand why do I need to set :references even though I added :primary_key option to belongs_to association.

2 Likes

I do them as such:


  @primary_key {:id, :binary_id, autogenerate: false}
  schema "accounts_local" do
    belongs_to :account, MyServer.DB.Account, type: :binary_id, primary_key: true, foreign_key: :id, define_field: false
    ...
  end

So basically how you ended up doing it, except I turned off autogenerate since that makes no sense for a foreign key. ^.^;

6 Likes

It works well! Thanks!

1 Like