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”]}}
If you are running into this type of error, I would assume that we have some issues with your backend code and not the form.
We could do one of two things in my mind. We should be passing the existing preference to the changeset if it exists, or we should change the insert into an upsert (insert or update) so that we can update the existing row in the database.
Take a look at the Ecto.Repo documentation on insert, the two options you are going to want to look at are :on_conflict and :conflict_target if you are considering the upsert option.
Yes @tomciopp, I thought the same. To resolve this i took a different approach. I am a rails guy so i went with find_or_initialize method along with elixir’s pattern matching and assigned action to create or update based on presence of the object id. (preference.id)
def get_user_preference(user_id), do: Repo.get_by(Preference, user_id: user_id)
def find_or_initialize_user_preference(user) do
case get_user_preference(user.id) do
nil ->
user |> Ecto.build_assoc(:preference)
preference ->
%Preference{} = preference
end
end