Incrementing an attribute

\ ឵឵឵
2023-03-23

\ ឵឵឵:

What I have been doing is this:

change fn changeset, opts ->
  attempts = Ash.Changeset.get_attribute(changeset, :attempts)
  Ash.Changeset.change_attribute(changeset, :attempts, attempts + 1)
end

I did speculatively try this with expr as well: 🙂

change set_attribute(:attempts, expr(attr(:attempts) + 1)

Is there another way to do this?

ZachDaniel:

Currently, the only way would be to switch to a manual action and implement the logic with ecto. Atomic updates will be coming along with bulk actions and at that point you’ll be able to update with an expression.

ZachDaniel:

If you need a guaranteed atomic update and you are using ash_postgrse, you can take a lock on the record in a before_action hook and read the value again before updating.

\ ឵឵឵:

Ok, awesome!

\ ឵឵឵:

I can forego atomicity for now, but glad to hear that’s on the way 🙂

\ ឵឵឵:

I thought that maybe it might be interesting to make set_attribute additionally accept a 1-arity function which would be passed the existing value and produce a new value to set.

change set_attribute :count, &(&1 + 1)

\ ឵឵឵:

Not atomic, but useful and more general.

ZachDaniel:

Yeah, I could see the use there 🙂

ZachDaniel:

Could work similar to the before_action changes and the like, to support anonymous functions

\ ឵឵឵:

Cool, I’ll throw together a PR and we can discuss.

\ ឵឵឵:

Mate, could I maybe get you to take a look at https://discord.com/channels/711271361523351632/1087881932282548284 ?