Before_destroy и зависимый уничтожить не стрельбу

У меня есть следующие ассоциации моделей:

class Slider < ActiveRecord::Base
  has_one :featured_happening, :as => :featured_item, :dependent => :destroy   
  before_destroy :destroy_featured_happening
  after_create :create_featured_happening
end

class FeaturedHappening < ActiveRecord::Base
  belongs_to :featured_item, :polymorphic => true
end

Когда я уничтожаю объект Slider, я думал, что dependent => :destroy автоматически уничтожит featured_item, но это не так.

Контроллер ползунка

 def destroy    
    slider = Slider.find(params[:id])
    slider.delete
    render(:status => :ok, :nothing => true )
  end

Итак, я попробовал обратный вызов с before_destroy, чтобы вручную удалить featured_item, когда объект слайдера уничтожен и ничего не вызвано.

Как я могу удалить featured_item при удалении объекта слайдера? Использование Rails 3.2.

Ответ 1

Вы только что заметили разницу между delete и destroy. В контроллере вы вызываете

slider.delete

который просто выполнит SQL delete, но не вызовет никаких обратных вызовов. Поэтому в обычных случаях вы хотите использовать destroy. Он будет извлекать объект (при необходимости), вызывать обратные вызовы, включая рекурсивные разрушения, и только затем удаляет объект из базы данных.

См. документацию для delete и destroy для получения дополнительной информации.

Ответ 2

Убедитесь, что вы вызываете Slider#destroy, чтобы активировать обратные вызовы. Slider#delete просто удалит запись, не вызывая их.

Ответ 3

class Slider < ActiveRecord::Base
  has_one :featured_happening,  :dependent => :destroy  
end

class FeaturedHappening < ActiveRecord::Base
  belongs_to :featured_item
end

Если ваш код был прост, как указано выше, в котором есть простые отношения. Затем с удалением слайдера функция Happing будет удалена с удалением ползунка. Но в вашем случае отношения являются полиморфными. В таблице функций happing в DB abject_id будет идентификатором ползунка или может быть другим классом. Поэтому зависимый: уничтожить не работает. Поэтому вам нужно удалить его с помощью обратного вызова before_destroy, в котором вы сначала извлекаете записи, а затем уничтожаете их.