Do not touch `updated_at` when upsert has no effect

1 Like

We merged something into main yesterday that should fix the protocol Enumerable not implemented error. Can you try your code with the latest commit from main, please?

1 Like

Thanks @barnabasJ ! That totally fixes the bug.

@zachdaniel when I use upsert_fields {:replace_all_except, [:updated_at]}, updated_at does not change, even if the upsert action is called with different attributes which changes an existing user. I’m fine with leaving it this way, then I know that updated_at relates to when my app updated the record, not when an attribute changed from Auth0.

I’m curious about how I would do it if I wanted updated_at to change whenever other attributes like name actually changed.

Would I look up the existing record inside the change function and then conditionally set updated_at? Or is there a more elegant way?

A perfectly reasonable answer to this question, might be that there are many higher priorities to consider right now, and we will revisit this in the distant future.

1 Like

:thinking: this may actually be something the framework should handle for you? Like if something has an update_default, it should only be applied if something is changing. We actually could solve for this in the update, i.e fields that are being set due to update_defaults would be set only if at least one other thing is changing…The difficulty is pairing that with atomics, i.e we don’t know if nothing is changing until we actually do the upsert. There are a few things we’d need to do to make this work, incrementally, that are on the roadmap that is in my brain :laughing:.

  1. add an expression variable that lets you refer to the thing you are replacing in an upsert.
  2. add an expression variable that corresponds to wether or not you are in an upsert.
  3. add an expression variable that corresponds to wether or not something is changing if you are in an upsert. # this one may or may not be reasonable

So then you could use an atomic_update to get this behavior in the short term, and then in the long term the framework can do this automatically. In a create, set the value, in an update, only set if something is changing.

change atomic_update(:updated_at, expr(
  if ash.updating? and ash.has_changes? do
    now()
  else
    updated_at
  end
))

But yeah none of that will happen in the short term. Someday :smiley:

1 Like

That settles it. It makes sense that people would want a mature framework to handle it for them. And it also makes sense that Ash has other more important steps to take before adding in these kinds of nice-to-haves. Thanks for your commitment to the community @zachdaniel