Ecto: Updating associations that have custom foreign_key with cast_assoc

I have two tables, Users and Accounts. A user can have many accounts while an account can only belong to one user only. A user can select one account out of their accounts.

User schema

......
has_many :accounts, Account
has_one :selected_account, Account, foreign_key: :selector_id, on_replace: :update

Changeset

def selected_account_changeset(user, attrs) do
  user
  |> cast(attrs, [])
  |> cast_assoc(:selected_account, with: &Account.selector_changeset/2)
end

Account schema

belongs_to :user, User
belongs_to :selector, User, foreign_key: :selector_id

Account changeset

def selector_changeset(account, attrs) do
  account
  |> cast(attrs, [:selector_id])
  |> validate_required([:selector_id])
end

Account migration

create table(:accounts) do
   add :selector_id, references(:users, on_delete: :nothing)
end

I’m not getting my desired result when I tried to select an account.

attrs = %{selector: one_of_user_accounts}
result = User.selected_account_changeset(preloaded_user, attrs)

result.selected_account still gives me nil. I don’t know what I’m doing wrong.

Expecting selected_account but passing selector would cause a “this changeset does nothing” symptom like you’re observing.

1 Like

Thanks, I changed it to selected_account but got another error.

{:error,
 #Ecto.Changeset<
   action: :update,
   changes: %{},
   errors: [selected_account: {"is invalid", [validation: :assoc, type: :map]}],
   data: #Chainstaker.Accounts.User<>,
   valid?: false
 >}