I’m building a finance tracking Phoenix LiveView application in which I have a Transaction
schema that embeds (via belongs_to
) a Merchant
schema. The merchant represents where the transaction took place, so naturally, one can have multiple transactions per merchant.
I also have basic forms that allow creating and editing transactions. The complication here is that I want to be able to type in a free-form merchant name and have that upsert a corresponding Merchant
in the backend. This prevents me from having the form be backed by a changeset for the Transaction
schema since when I’m editing a transaction’s merchant, I want to upsert a new Merchant
with the updated name rather than updating the existing merchant (which would affect all transactions that were referencing the old merchant).
What I’ve done to work around this is create a TransactionForm
embedded schema that backs the form. Then when I decide to save the form, I’ll pull out the merchant name, upsert that, grab the ID, and then create a Transaction
changeset with the remaining parameters and the (possibly updated) merchant ID.
I can see how this would make a lot of sense for more complex forms, but this seems repetitive for my use case since it’s duplicating a lot of the changeset validations I have in place for the Transaction
schema with the only meaningful change being it has merchant
instead of merchant_id
as a field. Transaction
s have a bunch of other fields that I haven’t specified here since they’re not relevant to the example, but the validation for all those fields have to be copied as well.
I’m hoping (and assuming) that I’m not the first to encounter this and that a more elegant solution exists.
I’ve read through this page from the Ecto documentation, but I was turned off and a bit surprised by the inclusion of side effects (writing to the DB) in the changeset. My form is validated in realtime as the form values are updated, so I don’t think it’s reasonable to be writing to the DB for each keystroke.
Thank you in advance!