Hi everyone
I have encountered a small issue with my Phoenix code. I have three models, Recipe, Ingredient, and RecipeIngredient. The relationship between them is many to many, and the Recipe and Ingredient are “joined” through RecipeIngredient.
When the validation goes fine for the recipe, everything works fine. However, when there is a validation error with the recipe, the ingredients are inserted, but obviously no association takes place (i.e. no recipe ingredients are created, nor the recipe). I would prefer it if in the event of a validation error no related models were inserted.
The logic for creating the recipe is:
def create_recipe(attrs \\ %{}) do
change_recipe(%Recipe{}, attrs)
|> Repo.insert()
end
And the logic for associating the two models is:
def change_recipe(%Recipe{} = recipe, attrs \\ %{}) do
Recipe.changeset(recipe, attrs)
|> Ecto.Changeset.put_assoc(:ingredients, process_ingredients(attrs))
end
def process_ingredients(params) do
(params["ingredients"] || [])
|> remove_empty_strings()
|> Enum.map(&get_or_insert_ingredient/1)
end
defp get_or_insert_ingredient(ingredient) do
Repo.insert!(
%Ingredient{ingredient: ingredient},
on_conflict: [set: [ingredient: ingredient]],
conflict_target: :ingredient
)
end