Rails 4: Как отменить сохранение на обратном вызове "before_save"?

У меня сложные модели/формы. Я не хочу повторять записи, поэтому я хочу объединить записи, имеющие похожие атрибуты. Как я могу отменить "сохранить", используя обратный вызов before_save? Это то, о чем я думаю:

class ProductsColor < ActiveRecord::Base


  before_save :check_for_similar_record

  def check_for_similar_record
    if ProductsColor.exist?(color_id: self.color_id, product_id: self.product_id)
      # merge values with existing ProductsColor and stop self from saving
    end
  end

end

Ответы

Ответ 1

Чтобы предотвратить сохранение записи, вы должны просто вернуть false:

def check_for_similar_record
  if ProductsColor.exists?(color_id: self.color_id, product_id: self.product_id)
    # merge values
    false
  else
    true
  end
end

Ответ 2

Рельсы 5

Как и в случае с Rails 5, вы можете сигнализировать о том, что операция должна быть прервана путем явного вызова throw :abort внутри вашего обратного вызова. В разделе документации отмена обратных вызовов (сейчас) указано:

Если a before_* обратный вызов throws :abort, все последующие обратные вызовы и связанное с ним действие отменены.

Следующий раздел в transactions продолжается:

Если a before_* обратный вызов отменяет действие a ROLLBACK. Вы также можете запустить ROLLBACK, создавая исключение в любом из обратных вызовов, включая after_* hooks.

Рельсы 4

История очень похожа на Rails 5, за исключением того, что обратные вызовы должны возвращать false. Соответствующие части документации позволяют с уверенностью заявить

Если обратный вызов before_* возвращает значение false, все последующие обратные вызовы и связанное с ним действие отменены. Если обратный вызов after_ * возвращает false, все последующие обратные вызовы будут отменены.

Далее

Если обратный вызов before_ * отменяет действие, выдается a ROLLBACK. Вы также можете запустить ROLLBACK, создавая исключение в любом из обратных вызовов, в том числе after_ * hooks.