Проверить перед уничтожением - PullRequest
50 голосов
/ 02 апреля 2011

У меня есть три класса: School, Account и Administratorship.

Школа

has_many :administatorships
has_many :administrators, :through => :administratorships

Счет

has_many :administratorships

Администрация

belongs_to :account
belongs_to :school

before_destroy :confirm_presence_of_alternate_administratorship_in_school

protected

def confirm_presence_of_alternate_administratorship_in_school
    unless school.administrators.count(["administratorships.account_id != #{id}"]) > 0
        errors.add_to_base "The school must have at least one administrator"
    end
end

Теперь я хотел бы, чтобы я вызвал destroy для экземпляра Administratorship, для этогодобавить ошибку в модель и предотвратить разрушение модели.Я удалил оператор unless, чтобы проверить, не мешает ли это добавить ошибку, но это не так.Кажется, что наличие ошибок в модели не предотвращает уничтожение.

Поэтому мой вопрос, есть ли способ предотвратить уничтожение с помощью проверок?Я понимаю, что мог бы определить метод, который уничтожает, только если вышеуказанное условие выполнено, но кажется, что подход проверки является более элегантным решением.

Ответы [ 4 ]

64 голосов
/ 02 апреля 2011

Если вы вернете false из этого метода before_destroy, это предотвратит уничтожение.

26 голосов
/ 24 марта 2017

Это ответ Rails 5 , если вы вернете false, он выдаст предупреждение об устаревании: "Возврат false в обратных вызовах Active Record и Active Model не будет неявно останавливать цепочку обратных вызовов в Рельсы 5.1 ".

def confirm_presence_of_alternate_administratorship_in_school
  return if school.administrators.count(["administratorships.account_id != #{id}"]) > 0
  errors[:base] << 'The school must have at least one administrator'
  throw :abort
end
15 голосов
/ 06 января 2012

Возвращение false из вашего метода проверки предотвратит уничтожение записи.

Пример:

def confirm_presence_of_alternate_administratorship_in_school
  unless school.administrators.count(["administratorships.account_id != #{id}"]) > 0
    # errors.add_to_base() is deprecated in Rails 3. Instead do...
    errors.add(:base, "The school must have at least one administrator")

    # this will prevent the object from getting destroyed
    return false
  end
end

Примечание: У меня возникли проблемы с тем, что это сообщение об ошибке не отображается. Проверка работала бы, и объект не был бы удален, но не было бы сообщения, сообщающего мне, что случилось. Причиной этого было то, что контроллер перенаправлял в представление индекса вместо отображения представления удаления (например, если при создании нового пользователя возникла ошибка, он отобразит: action => 'new'. не удалять вид). Когда это произошло, переменная экземпляра, для которой было установлено сообщение об ошибке (в errors.add (: base, "message")), фактически сбрасывается, что уничтожает ошибку в процессе.

1 голос
/ 10 октября 2014

Я использовал код здесь для создания переопределения can_destroy для activerecord: https://gist.github.com/andhapp/1761098

class ActiveRecord::Base
  def can_destroy?
    self.class.reflect_on_all_associations.all? do |assoc|
      assoc.options[:dependent] != :restrict || (assoc.macro == :has_one && self.send(assoc.name).nil?) || (assoc.macro == :has_many && self.send(assoc.name).empty?)
    end
  end
end

Это дает дополнительное преимущество, так как упрощает скрытие / отображение кнопки удаления на интерфейсе пользователя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...