svilen
Issue with a `many_to_many` assoc and `join_keys`
I’m trying to set up the usual many-to-many relationship between two schemas: User and Conversation. However, the primary key on the conversations table is uuid rather than id.
What I have so far is the following:
# conversation.ex
@primary_key {:uuid, :binary_id, autogenerate: true}
schema "conversations" do
many_to_many :users, User,
join_through: "conversations_users",
join_keys: [user_id: :id, conversation_uuid: :uuid]
end
# user.ex
schema "users" do
many_to_many :conversations, Conversation,
join_through: "conversations_users",
join_keys: [user_id: :id, conversation_uuid: :uuid]
end
Which makes sense to me, after reading the documentation about join_keys but unfortunately produces the following error on compile:
== Compilation error in file lib/myapp_web/models/conversation.ex ==
** (ArgumentError) schema does not have the field :id used by association :users, please set the :join_keys option accordingly
lib/ecto/association.ex:959: Ecto.Association.ManyToMany.struct/3
lib/ecto/schema.ex:1734: Ecto.Schema.association/5
lib/ecto/schema.ex:1876: Ecto.Schema.__many_to_many__/4
lib/myapp_web/models/conversation.ex:23: (module)
(stdlib) erl_eval.erl:677: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:208: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6
So I’m stuck here and I have a feeling I’m missing something really simple, but I can’t figure out what it is
Any help is appreciated! Thank you!
Edit: forgot to mention version numbers:
{:phoenix, "~> 1.4"},
{:phoenix_ecto, "~> 4.0"},
{:ecto_sql, "~> 3.0"},
Elixir: v1.8
Marked As Solved
al2o3cr
From the docs for join_keys:
It expects a keyword list with two entries, the first being how the join table should reach the current schema and the second how the join table should reach the associated schema.
Keyword lists are ordered - have you tried flipping the declaration for :users?
# conversation.ex
@primary_key {:uuid, :binary_id, autogenerate: true}
schema "conversations" do
many_to_many :users, User,
join_through: "conversations_users",
join_keys: [conversation_uuid: :uuid, user_id: :id]
end
Also Liked
svilen
Correction! @al2o3cr is totally right, the order does matter, and I wasn’t careful enough when making the changes.
The final solution is:
# conversation.ex
@primary_key {:uuid, :binary_id, autogenerate: true}
schema "conversations" do
many_to_many :users, User,
join_through: "conversations_users",
join_keys: [conversation_uuid: :uuid, user_id: :id]
end
# user.ex
schema "users" do
many_to_many :conversations, Conversation,
join_through: "conversations_users",
join_keys: [user_id: :id, conversation_uuid: :uuid]
end
Notice that for the Conversation, the order is [conversation_uuid: :uuid, user_id: :id] and for the User it is [user_id: :id, conversation_uuid: :uuid]. What I did previously was using the same order for both, which produced the exception again.
I’ll try to find time to open an issue / PR when I get a chance
it will be great to improve the docs in this area. Thanks everyone!







