phoebe

phoebe

Build_assoc and UUID

Hi, I’ve been scratching my head around this for a while and trying different combinations, but I’m just stuck whilst using build_assoc which does not recognise binary id UUIDs in my code. Here’s my problem and question.

I’m working on a banking app, so I have a user and wallet. user was created with Pow if that makes any difference. There is a has_many relationship between user and wallet. Here are the schemas:

use MyApp.Schema

schema "users" do
  field :role, :string, null: false, default: "user"
  has_many :wallets, MyApp.Accounts.Wallet
  pow_user_fields()
  timestamps()
end

and

use MyApp.Schema
...
schema "wallets" do
  field :description, :string
  field :balance, Money.Ecto.Composite.Type
  belongs_to :user_id, MyApp.Users.User, references: :uuid, type: :binary_id
  timestamps()
end

where MyApp.Schema is set up for UUIDs:

defmodule MyApp.Schema do
  defmacro __using__(_) do
    quote do
      use Ecto.Schema
      @primary_key {:uuid, :binary_id, autogenerate: true}
      @foreign_key_type :binary_id
      @derive {Phoenix.Param, key: :uuid}
      @timestamps_opts
    end
  end
end

Then in my CreateWallet migration:

defmodule MyApp.Repo.Migrations.CreateWallets do
  use Ecto.Migration

  def change do
    create table(:wallets) do
      add :description, :string, null: false
      add :balance, :money_with_currency, null: false
      add :user_id, references(:users, column: :uuid, type: :binary_id, on_delete: :nothing)
      timestamps()
    end

    create index(:wallets, [:user_id])
  end
end

All standard I think so far. However, if I want to implement a create_user_wallet function:

def create_user_wallet(%User{} = user, %{} = wallet_params) do
  wallet = Ecto.build_assoc(user, :wallets, wallet_params)
  Repo.insert(wallet)
end

and then try to run it, there is an error:

** (KeyError) key :user_uuid not found
    (ecto 3.7.1) lib/ecto/association.ex:754: Ecto.Association.Has.build/3

This is fine if it’s referring to the uuid key in the user map, as I don’t see user_uuid there, it’s just %User{uuid: "1234..."} - or is it referring to user_id in the wallet database? However, why should the build_assoc function expect that and not function as is given the Schema implementation and how can I override it, or set up my schemas and/or own Schema implementation and/or migration correctly?

Thanks for reading this far!

Most Liked

al2o3cr

al2o3cr

The errors you are getting suggest that you have a column named user_uuid on the wallets table. You’ll need to tell the belongs_to / has_many machinery about that:

# in the user schema
has_many :wallets, foreign_key: :user_uuid

# in the wallet schema
belongs_to :user, foreign_key: :user_uuid, ...etc

Where Next?

Popular in Questions Top

gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

We're in Beta

About us Mission Statement