I’d like to match the result of the delete_all and, if it is not exactly 1, stop the transaction.
I think I could do it with Multi.run but I’d like to know if there is an elegant way to perform this using only “data queries”.
I think you will have to use Multi.run this in this case. In order to see the results of delete_all the query needs to actually execute, which only takes place when Repo.transaction is finally called. You will need to use run if you want to adjust an operation in your transaction based on the result of a previous operation.
is arbitrary so Multi.run is made for this exact purpose of ‘arbitrary’ checks. I suppose a .delete might bark if there a 0 or multiple records - but that is very implicit, and I haven’t checked.
Also I would ‘normalize’ your DB and make sure that duplicate records never exists in the first place. If you add a DB constraints like:
ALTER TABLE likes ADD UNIQUE (user_id, post_id)
I would even suggest you add the pair as a primary key eg primary key (user_id, post_id) and then the unique constraint is not needed.
You gave me an idea, you can access to the transaction intermediate value as first argument to the function you pass to Multi.run/3. So at the moment I made this:
I have it, but you still can delete without creating.
At the moment, I don’t have it as a primary key and i’m using unique_index with the constraint. Ecto does not allow deleting by composed key so this won’t solve my problem. Any additional reason to add it like composed primary key? I really don’t know