Correct changeset for one to many

Hello all)
Who can tell how to organize connection 1 to many, because I could not understand which of them is better?

def create_changeset(meetup, attrs) do
    meetup
    |> cast(attrs, [:met_at])
    |> put_assoc(:user1, attrs["meetuper1"], required: true)
    |> put_assoc(:user2, attrs["meetuper2"], required: true)
    |> validate_required([:met_at])
  end
OR
def create_changeset(meetup, attrs) do
    meetup
    |> cast(attrs, [:meetuper1, :meetuper2, :met_at])
    |> validate_required([:meetuper1, :meetuper2, :met_at])
  end

i did so:
-----model users-------------

schema "users" do
    field :email, :string
    field :name, :string
    field :surname, :string

    timestamps()
    
    has_many :meetup1, Meetup, foreign_key: :meetuper1
    has_many :meetup2, Meetup, foreign_key: :meetuper2
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :surname, :email])
    |> validate_required([:name, :surname, :email])
    |> unique_constraint(:email)
  end

  def create_changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :surname, :email])
    |> validate_required([:name, :surname, :email])
    |> unique_constraint(:email)
  end

  def update_changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :surname, :email])
    |> validate_required([:name, :surname, :email])
    |> unique_constraint(:email)
  end

-----meetups ---------

 schema "meetups" do
    field :met_at, :date

    timestamps()

    belongs_to :user1, User, foreign_key: :meetuper1
    belongs_to :user2, User, foreign_key: :meetuper2
  end

  @doc false
  def changeset(meetup, attrs) do
    meetup
    |> cast(attrs, [:met_at])
    |> put_assoc(:user1, attrs["meetuper1"], required: true)
    |> put_assoc(:user2, attrs["meetuper2"], required: true)
    |> validate_required([:met_at])
  end

  def create_changeset(meetup, attrs) do
    meetup
    |> cast(attrs, [:met_at])
    |> put_assoc(:user1, attrs["meetuper1"], required: true)
    |> put_assoc(:user2, attrs["meetuper2"], required: true)
    |> validate_required([:met_at])
  end

  def update_changeset(meetup, attrs) do
    meetup
    |> cast(attrs, [:met_at])
    |> put_assoc(:user1, attrs["meetuper1"])
    |> put_assoc(:user2, attrs["meetuper2"])
    |> validate_required([:met_at])
  end

---------migration users------------

def change do
    create table(:users) do
      add :name, :string
      add :surname, :string
      add :email, :string
    
      timestamps()
    end
    create unique_index(:users, [:email])
  end

------migration meetups---------------

def change do
    create table(:meetups) do
      add :met_at, :date

      add :meetuper1, references(:users, on_delete: :delete_all)
      add :meetuper2, references(:users, on_delete: :delete_all)
      timestamps()
    end

Assuming that your question is about the meetups schema.

put_assoc(:user1, attrs["meetuper1"], required: true)

I’m not exactly sure why you not just send in the attribute user1. If user1 is not clear enough outside of your schema then name your relation differently. Perhaps just name your relation “meetuper1”.

def create_changeset(meetup, attrs) do
    meetup
    |> cast(attrs, [:meetuper1, :meetuper2, :met_at])
    |> validate_required([:meetuper1, :meetuper2, :met_at])
  end

This way is cleaner in my opinion which is very subjective obviously. So just pick the one you prefer and use it.

It also seems like the problem you’re trying to solve is not a one to many but a many to many. (many users have met many users).

1 Like