Removing an Association with Ecto

I have an Event that has_one Number (the schema and migrations are shown simplified below). I can use put_assoc when inserting a number to associate a number with an event. However I would like to be able to disassociate the two (essentially remove the relationship) without deleting the Number or Event (so the number would end up with no event_id). Any ideas would be quite helpful.

defmodule App.Events.Event do
  use Ecto.Schema
  import Ecto.Changeset

  schema "events" do
    field :description, :string
    field :name, :string
    
    has_one :number, App.Events.Number

    timestamps()
  end

  @doc false
  def changeset(event, attrs) do
    required_fields = [:name]
    optional_fields = [:description]

    event
    |> cast(attrs, required_fields ++ optional_fields)
    |> validate_required(required_fields)
  end
end


defmodule App.Repo.Migrations.CreateEvents do
  use Ecto.Migration

  def change do
    create table(:events) do
      add :name, :string
      add :description, :text

      timestamps()
    end

  end
end




defmodule App.Events.Number do
  use Ecto.Schema
  import Ecto.Changeset

  schema "numbers" do
    field :description, :string
    field :name, :string
    field :phone_number, :string
  
    belongs_to :event, App.Events.Event
  
    timestamps()
  end

  @doc false
  def changeset(number, attrs) do
    required_fields = [:name, :phone_number]
    optional_fields = [:description]

    number
    |> cast(attrs, required_fields ++ optional_fields)
    |> validate_required(required_fields)
  end
end

defmodule App.Repo.Migrations.CreateNumbers do
  use Ecto.Migration

  def change do
    create table(:numbers) do
      add :name, :string
      add :description, :text
      add :phone_number, :string, null: false
      add :event_id, references(:events, on_delete: :delete_all)

      timestamps()
    end

  end
end

:wave:

Would setting the event_id to NULL work?

import Ecto.Query

def disassociate_number_from_event(number_id) do
  App.Events.Number
  |> where(id: ^number_id)
  |> App.Repo.update_all(set: [event_id: nil])
end
3 Likes

Yes I think so, I was overthinking it! Thank you for the help.