这是为具有两个替代验证的模型编写模型,工厂和规范的正确方法(两者都没有设置值,两者都可以为零吗?
我是按照以下方式做到的。但是,我不确定这可能是最优雅的方式。
models / invoice.rb
class Invoice < ActiveRecord::Base
validates :payment_term, presence: true, allow_nil: true
validates :interest_on_arrears, numericality: true, allow_nil: true
validate :choose_xor_date
private
def choose_xor_date
unless deadline.blank? ^ payment_term.blank?
errors.add(:base, 'specify a deadline or a payment term.
Not both empty, nor both filled')
end
end
end
模型/ invoice_spec.rb
RSpec.describe Invoice, type: :model do
describe 'validations' do
it 'fails validation with both deadline and payment_term filled' do
invoice_with_deadline = build(:invoice, deadline: '2016-02-20', payment_term: '')
invoice_with_payment_term = build(:invoice, deadline: '', payment_term: '2')
invoice_with_deadline_and_payment_term =
build(:invoice, deadline: '2016-02-20', payment_term: '2')
expect(invoice_with_deadline).to be_valid
expect(invoice_with_payment_term).to be_valid
expect(invoice_with_deadline_and_payment_term).to be_invalid
end
end
end
工厂/ invoice.rb
FactoryGirl.define do
factory :invoice do
deadline "2016-02-20"
payment_term "2"
end
end
特征/ invoice_feature_spec.rb
# User create with parameter when creating invoice local object.
describe 'when user has invoice' do
@invoice = create(:invoice, deadline: '2016-02-20', payment_term: '')
visit invoices_path
click_link I18n.t('button.show')
end
答案 0 :(得分:0)
你几乎就在那里。以下是我的不同之处:
在模型中,只有几条关于命名的评论:
validate_deadline_xor_payment_term
或validate_deadline_or_payment_term_chosen
是验证方法的更好名称。 &#34;选择&#34;实际上是XOR的一个很好的英文翻译。在型号规格中,
在工厂中,我会删除默认值。如果值是可选的,则具有非限定名称的工厂不应具有可选值。读者很容易记住该约定,并且未指定的值为零是有意义的。如果具有不合格名称的工厂确实具有可选值集,则读者无法知道该值是什么。
功能规范
it
块中,而不是describe
块中。实际上,由于它是a feature spec,因此在feature
块中包围整个要素会更好,并且在此示例中使用scenario
。expect(page).to have_content
等)