Skip to content

Conversation

@freddiescadding-pennylane
Copy link
Contributor

@freddiescadding-pennylane freddiescadding-pennylane commented Jun 3, 2025

Current behaviour

When a record is updated using batch_update, the dirty changes are not cleared. When processing further update statements, ActiveRecord is not aware that the database has been successfully updated, and so it may not include changes that it believes to be identical to the current state of the record in the database.

Reproduction steps
A cat is making some changes:

original_name = 'Felix'
new_name = 'Felicia'

cat = Cat.create!(name: original_name)
cat.name = new_name

Cat.batch_update(
  [cat],
  validate: false,
  columns: [:name],
)
# cat.changes_to_save => { "name" => [original_name, new_name], "updated_at" => [x, y] }

# we would expect:
# cat.changes_to_save => {}

cat.name
# => new_name

cat.update!(name: original_name)
# because `name` is still in the `changes_to_save`, active record thinks its value is actually still `original_name`
# so it doesn't include it in the update statement:

# ```
# TRANSACTION (3.9ms)
# /*line:(jeancat):11:in '<main>'*/ BEGIN
#   Cat Update (10.5ms)
# /*line:(jeancat):11:in '<main>'*/
# UPDATE "cats" SET "updated_at" = '2025-06-03 15:21:33.316008'
# WHERE "cats"."id" = 8664364538
#   TRANSACTION (1.9ms)
# /*line:(jeancat):11:in '<main>'*/ COMMIT
# ```

#  => true

cat.name
# => original_name

cat.reload.name
# => new_name

cat.update!(name: new_name)
# => true

cat.name
# => new_name

cat.reload.name
# => new_name

Potential impact

In a real world application, following a batch_update further changes to the records may not be applied, even when they appear to have been successful. This could result in some highly unexpected and confusing behaviour.

Changes made

Called clear_attribute_changes on each updated entry to remove dirty changes on the updated attributes

This clears the dirty changes, and restores expected behaviour.

@freddiescadding-pennylane freddiescadding-pennylane force-pushed the fs/clean-dirty-changes-after-update branch from 8f95eba to 42f0199 Compare June 3, 2025 15:53
@freddiescadding-pennylane freddiescadding-pennylane marked this pull request as ready for review June 3, 2025 15:54
Copy link

@jfpimentel jfpimentel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Freddie 😉

@quentindemetz
Copy link
Contributor

Good find 👌🏻

@quentindemetz quentindemetz merged commit 8e231b7 into main Jun 3, 2025
2 checks passed
@quentindemetz quentindemetz deleted the fs/clean-dirty-changes-after-update branch June 3, 2025 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants