collectiveidea / audited

Audited (formerly acts_as_audited) is an ORM extension that logs all changes to your Rails models.
MIT License
3.34k stars 645 forks source link

Updating an enum field on audited record while updating nested resource with touch: true creates a double audit #695

Closed ycp3 closed 3 months ago

ycp3 commented 5 months ago

Reproduction:

class User < ActiveRecord::Base
  audited
  has_many :companies
  accepts_nested_attributes_for :companies
  enum status: {active: 0, reliable: 1, banned: 2}
end

class Company < ActiveRecord::Base
  belongs_to :user, touch: true
end

user = User.create(status: :active)
user.status = :reliable
user.companies_attributes = [{name: "test"}]
user.save

user.audits.count
# => 3
user.audits.last(2).map(&:action)
# => ["update", "update"]
user.audits.last(2).map(&:audited_changes)
# => [{"status"=>[0, 1]}, {"status"=>[0, 1]}]

The audit_touch method filters out changes that were just audited to avoid duplicates, however enums are stored in the audit as the db integer value by default, and Rails' methods give the string alias of the enum.

# stored in previous audit
{"status"=>[0, 1]}

# user.previous_changes
{"status"=>["active", "reliable"]}