Railsでbefore_destroyを使うときの注意点

class Foo < ActiveRecord::Base
  has_many :bars, dependent: :destroy
  before_destroy :do_something

  def do_something
    return if bars.blank?
    bars.map &:somethig_cool
  end
end

このように, has_many(has_one)な関係をものをbefore_destroyで使うには注意が必要. 上の例だとbefore_destroyの前にbarsは削除されてしまうので, bars.blank?は必ず真になりbars.map &:somethig_coolは永久に実行されない.

これを避けるには以下のようにする.

class Foo < ActiveRecord::Base
  before_destroy :do_something
  has_many :bars, dependent: :destroy

# 以下略

before_destroyhas_manyの順番を逆にしただけだが, これで期待通りの挙動(before_destroyの後にbarsを削除)になる.

なのでこのようなときはObserverは使えない.

class FooObserver < ActiveRecord::Observer
  def before_destroy foo
    return if foo.bars.blank?
    foo.bars.map &:somethig_cool
  end
end

上のbefore_destroyはbarsが削除されてから実行される.