Unique constraint

Hi,
I’m trying to give all users an unique token, but I got the following error when there is a duplicate:

If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `unique_constraint/3` on your changeset with the constraint
`:name` as an option.

Code:
Repo.insert(%Token{user_id: user.id, token: token, last_activity: DateTime.utc_now()})

schema "sessions" do
    belongs_to :user, Poll.Accounts.User
    field :token, :string 
    field :last_activity, :utc_datetime_usec    
  end

  @doc false
  def changeset(session, attrs) do
    session
    |> cast(attrs, [:user_id, :token, :last_activity])
    |> validate_required([:user_id, :token, :last_activity])
    |> unique_constraint(:token, name: :sessions_token_index)
  end

Does somebody know what I do wrong?

Post your migration code that’s there the constraint is created at.

Also you’re not doing anything wrong no? If you’re giving a duplicate the unique constraint should be yelling at you. Unless I’m not understanding what you’re trying to do.

1 Like
def change do
    create table(:sessions) do
      add :user_id, references(:users, on_delete: :nothing)
      add :token, :string
      add :last_activity, :timestamp
    end

    create index(:sessions, [:user_id])
    create unique_index(:sessions, [:token])

  end

use the changeset?

Token.changeset(%Token{}, %{user_id: user.id, token: token, last_activity: DateTime.utc_now()} )
|> Repo.insert

You might want to change
def changeset(session, attrs) do
to
def changeset(session \\ %Token{}, attrs) do

and then it’s only:

Token.changeset( %{user_id: user.id, token: token, last_activity: DateTime.utc_now()} )
|> Repo.insert
3 Likes

Thank you!

1 Like

hi guys,

Got this error, when i put a unique constraint on user_id
and html doesn’t have user_id as input.
i set it in controller => Users.create_user_preference(current_user, preference_params)

def create_user_preference(user, attrs \\ %{}) do
    user
    |> Ecto.build_assoc(:preference)
    |> Preference.changeset(attrs)
    |> Repo.insert()
  end

def changeset(preference, attrs) do
    preference
    |> cast(attrs, [:age, :height, :religion_id, :height, :body_type,
                    :education_id, :occupation_id,  :caste_id, :user_id])
    |> validate_required([:religion_id, :user_id])
    |> unique_constraint(:user_id, name: :preferences_user_id_index)
  end

Getting the following error,
lists in Phoenix.HTML and templates may only contain integers representing bytes, binaries or other lists, got invalid entry: {:user_id, {“has already been taken”, [constraint: :unique, constraint_name: “preferences_user_id_index”]}}

How to resolve this fellows?