简体   繁体   English

如何为只验证两个属性之一的模型编写规范(xor)?

[英]How to write specs for a model that validates only one of the two attributes are set (xor)?

Is this a correct way to write a Model, Factory and Specs for a model with two alternative validations (neither both of have value set nor, both of them could be nil? 这是为具有两个替代验证的模型编写模型,工厂和规范的正确方法(两者都没有设置值,两者都可以为零吗?

I did it the following way which works right. 我按照以下方式做到了这一点。 However, am not sure that this could the most elegant way of doing it. 但是,我不确定这可能是最优雅的方式。

models/invoice.rb 车型/ 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

models/invoice_spec.rb 车型/ 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

factories/invoice.rb 工厂/ invoice.rb

FactoryGirl.define do
  factory :invoice do
    deadline "2016-02-20"
    payment_term "2"
  end
end

features/invoice_feature_spec.rb 功能/ 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

You're almost there. 你快到了。 Here's what I'd do differently: 以下是我的不同之处:

In the model, only a couple of comments on naming: 在模型中,只有几条关于命名的注释:

  • It's "in arrears", not "on arrears". 这是“拖欠”,而不是“欠款”。
  • I think validate_deadline_xor_payment_term or validate_deadline_or_payment_term_chosen would be better names for the validation method. 我认为validate_deadline_xor_payment_termvalidate_deadline_or_payment_term_chosen是验证方法的更好名称。 "Choice" is actually a good English translation of XOR. “选择”实际上是XOR的良好英文翻译。

In the model spec, 在型号规格中,

  • The single spec that you already have should be three specs, one object and expectation in each. 您已经拥有的单个规格应该是三个规格,每个规格中有一个对象和期望。
  • You need a fourth spec to test that the model is invalid if neither field is set. 如果两个字段都未设置,则需要第四个规范来测试模型是否无效。
  • You correctly set all the optional values explicitly, so it's easy to see what they are. 您可以明确地正确设置所有可选值,因此很容易看出它们是什么。 If you changed your factory as I suggest below you could remove the blank ones. 如果您按照我的建议更改了工厂,则可以删除空白工厂。

In the factory, I would remove the default values. 在工厂,我会删除默认值。 If a value is optional, the factory with the unqualified name shouldn't have the optional value. 如果值是可选的,则具有非限定名称的工厂不应具有可选值。 It's easy for the reader to remember that convention and it makes sense that an unspecified value is nil. 读者很容易记住该约定,并且未指定的值为零是有意义的。 If a factory with an unqualified name does have an optional value set, there is no way for the reader to know what the value is. 如果具有不合格名称的工厂确实具有可选值集,则读者无法知道该值是什么。

The feature spec 功能规格

  • should be in an it block, not a describe block. 应该在it块中,而不是describe块。 Actually, since it's a feature spec , it would read even better to surround the entire feature in a feature block and use scenario for this example. 实际上,由于它是一个特征规范 ,因此在feature块中包围整个特征并使用该示例的scenario会更好。
  • needs expectations about what is on the index page ( expect(page).to have_content and the like) 需要关于索引页面上的内容的expect(page).to have_content等)
  • needs expectations about what is on the show page 需要对展示页面上的内容有所期望

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM