GabeStah / vcp

0 stars 0 forks source link

Deleting Raid causes inverse standing_event.change values to double. #76

Closed GabeStah closed 9 years ago

GabeStah commented 9 years ago
class Raid < ActiveRecord::Base
  has_many :participations, dependent: :destroy
end

Is causing Participation callbacks to run for every participation:

class Participation < ActiveRecord::Base
  after_destroy :reset_raid_events
  private

  def reset_raid_events
    raid.reset_standing_events
  end
end

Maybe use :delete_all instead to prevent callbacks then add after_destroy or before_destroy callback to Raid to :destroy_standing_events.

class Raid < ActiveRecord::Base
  has_many :participations, dependent: :delete_all
  has_many :standing_events, dependent: :delete_all

  after_destroy :destroy_standing_events
end
GabeStah commented 9 years ago
has_many :standing_events, dependent: :delete_all
before_destroy :destroy_standing_events

Apparently dependent: :delete/destroy calls run before callbacks (such as before_destroy), so :destroy_standing_events was never returning any associated records.

GabeStah commented 9 years ago

Resolved by removing direct association-based :destroy callback and instead adding after_destroy :destroy_standing_events callback to Raid, ensuring :revert_change is only processed for dominant records (those with children or no parent/children). Parent :destroy association in StandingEvent ensures :revert_change runs once for everything before destroy.

class Raid < ActiveRecord::Base
  has_many :participations, dependent: :delete_all
  has_many :standing_events

  after_destroy :destroy_standing_events

  def destroy_standing_events
    self.standing_events.dominant.destroy_all
  end
end

class StandingEvent < Event
  has_many :children, class_name: "StandingEvent", foreign_key: "parent_id", dependent: :destroy
  after_destroy :revert_change

  def revert_change
    # Subtract what change was prior to current instance; useful for update
    self.change_was ?
      self.standing.update(points: self.standing.points - self.change_was) :
      self.standing.update(points: self.standing.points)
  end
end