Принятый ответ не решает исходную проблему. Хосе хотел 2 вещи:
1) Чтобы у родителя всегда был хотя бы один ребенок
и
2) Чтобы можно было удалить всех детей при удалении Родителя
Вам не нужны никакие обратные вызовы before_destroy
, чтобы предотвратить удаление ребенка.
Я написал подробное сообщение в блоге, описывающее решение , но здесь я также расскажу об основах.
Решение включает в себя различные ингредиенты: использование проверки присутствия и вложенных атрибутов в модели Parent, а также обеспечение того, чтобы метод, который удаляет дочерний элемент, не вызывал .destroy
для дочернего элемента, но этот дочерний элемент был удален из Родительская модель через вложенные атрибуты.
В родительской модели:
attr_accessible :children_attributes
has_many :children, dependent: :destroy
accepts_nested_attributes_for :children, allow_destroy: true
validates :children, presence: true
В детской модели:
belongs_to :parent
Далее, самый простой способ разрешить удаление потомков, кроме последнего, - это использовать вложенные формы, как описано в Railscasts # 196 . По сути, у вас будет одна форма с полями как для родителей, так и для детей. Любые обновления для Location, а также для Children, включая удаление потомков, будут обрабатываться действием update
в родительском контроллере.
Способ удаления дочернего элемента с помощью вложенных форм заключается в передаче ключа с именем _destroy
со значением, равным true. Опция allow_destroy: true
, которую мы установили в родительской модели, позволяет это сделать. Документация для вложенных атрибутов Active Record охватывает это, но вот быстрый пример, который показывает, как вы удалите ребенка, чей id
равен 2
из его родителя:
parent.children_attributes = { id: '2', _destroy: '1' }
parent.save
Обратите внимание, что вам не нужно делать это самостоятельно в родительском контроллере, если вы используете вложенные формы, как в Railscasts # 196. Rails позаботится об этом за вас.
С проверкой присутствия в родительской модели Rails автоматически предотвратит удаление последнего потомка.
Я думаю, что в то время, когда Хосе разместил свой вопрос, проверка присутствия не работала так, как предполагалось. Это не было исправлено до июля 2012 года с этим запросом на получение , но это было почти 2 года назад. Наблюдение за тем, как dbortz опубликовал свое устаревшее решение 12 дней назад, заставило меня осознать, что по-прежнему существует путаница в этом вопросе, поэтому я хотел опубликовать правильное решение.
Альтернативное решение, которое не использует вложенные формы, см. В моем блоге: http://www.moncefbelyamani.com/rails-prevent-the-destruction-of-child-object-when-parent-requires-its-presence/