Toby 1 Kenobi
Toby 1 Kenobi

Reputation: 5037

:dependent => :destroy destroys records that are no longer dependents

Rails 4.2 running on PostgreSQL

I'm refactoring my database and moving some data around. Each ProgressUpdate belongs to a LanguageProgress. In a migration I move some ProgressUpdates from one LanguageProgress to another, then I destroy the LanguageProgress which no longer has any associated ProgressUpdates, however the destroy triggers the destroy on the ProgressUpdates that used to be dependent on it! Why's that?

Here's the relevant code in the migration:

LanguageProgress.find_each do |lp|
  if existing_lp = LanguageProgress.find_by(progress_marker: lp.progress_marker, language_id: lp.state_language.language_id)
    puts "LanguageProgress #{existing_lp.id} has these ProgressUpdates: #{existing_lp.progress_updates.pluck :id}"
    puts "LanguageProgress #{lp.id} has these ProgressUpdates: #{lp.progress_updates.pluck :id}"
    lp.progress_updates.each do |pu|
      pu.language_progress = existing_lp
      pu.save!
    end
    puts "now LanguageProgress #{existing_lp.id} has these ProgressUpdates: #{existing_lp.progress_updates.pluck :id}"
    puts "and LanguageProgress #{lp.id} has #{lp.progress_updates.count} ProgressUpdates"
    puts "destroying LanguageProgress #{lp.id}"
    lp.destroy
  else
    lp.language_id = lp.state_language.language_id
    lp.save!
  end
end

Here's what it prints out:

LanguageProgress 1073685945 has these ProgressUpdates: [1071256240]
LanguageProgress 1073691483 has these ProgressUpdates: [1071256239]
now LanguageProgress 1073685945 has these ProgressUpdates: [1071256239, 1071256240]
and LanguageProgress 1073691483 has 0 ProgressUpdates
destroying LanguageProgress 1073691483
destroying ProgressUpdate 1071256239

Here's the relevant bits of language_progress.rb

class LanguageProgress < ActiveRecord::Base

  belongs_to :language
  belongs_to :state_language
  belongs_to :progress_marker
  has_many :progress_updates, dependent: :destroy

  validates :progress_marker, presence: true, uniqueness: { scope: :state_language }
  validates :state_language, presence: true

and progress_update.rb

class ProgressUpdate < ActiveRecord::Base

  belongs_to :user
  belongs_to :language_progress
  delegate :language, to: :language_progress

  validates :progress, presence: true, inclusion: ProgressMarker.spread_text.keys
  validates :month, presence: true, inclusion: 1..12
  validates :year, presence: true, inclusion: 2000..Time.now.year
  validates :user, presence: true
  validates :language_progress, presence: true

  before_destroy{ |pu| puts "destroying ProgressUpdate #{pu.id}" }

end

Upvotes: 0

Views: 46

Answers (1)

Taryn East
Taryn East

Reputation: 27747

At a guess, I'd try reloading the lp after moving the other processes (and before destroying it).

The instance variable probably contains references to what it thinks are still processes that belong to it (even though they no longer do).

Upvotes: 1

Related Questions