Rails:回调防止删除

Rails: callback to prevent deletion

我有一个 before_destroy 回调,如下所示:

class Component < ActiveRecord::Base

  has_many :documents, through: :publications

  def document_check
    if documents.exists?
      errors[:documents] << 'cannot exist'
      return true
    else
      return false
    end
  end

测试看起来像这样:

describe '#document_check' do
  let(:document) { create(:document) }
  let(:component) { create(:component) }

  context 'with documents' do
    before do
      document.components << component
    end
    specify { expect(component.errors).to include(:document, 'cannot exist') }
    specify { expect(component.document_check).to eq true }
  end

  context 'without documents' do
    before do
      document.components = []
    end
    specify { expect(component.document_check).to eq false }
  end
end

我希望它在文档中有组件时引发错误,但我似乎无法正确编写它。第二个测试通过,第一个没有通过:

 Diff:
   @@ -1,2 +1,2 @@
   -[:document, "cannot exist"]
   +[]

我做错了什么?

如何调用 document_check?如果手动(正如你的第二次测试似乎建议的那样),那么你还需要在第一次指定时调用它。

即:

specify { component.document_check; expect(component.errors).to include(:document, 'cannot exist') }

那是可怕的语法,但您需要先调用该方法,然后才能检查其中的错误。

回调如下:

def document_check
  return unless documents.present?
  errors.add(:article, 'in use cannot be deleted')
  false
end

这是它的通过测试。

describe '#document_check' do
  let(:subject)   { create(:component) }
  let(:document)  { create(:document) }
  let(:count)     { Component.size }

  before do
    document.components << subject
    subject.send :document_check
  end

  context 'with documents raises error' do
    specify do
      expect(subject.errors[:article]).to be_present
    end
  end

  context 'with documents raises correct error' do
    specify do
      expect(subject.errors[:article]).to include(
        'in use cannot be deleted')
    end
  end

  context 'with documents prevents deletion' do
    specify do
      expect { subject.destroy }.to_not change(Component, :count)
    end
  end
end

花了很长时间,但这是值得的。