[英]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: 在模型中,只有几条关于命名的注释:
validate_deadline_xor_payment_term
or validate_deadline_or_payment_term_chosen
would be better names for the validation method. 我认为validate_deadline_xor_payment_term
或validate_deadline_or_payment_term_chosen
是验证方法的更好名称。 "Choice" is actually a good English translation of XOR. “选择”实际上是XOR的良好英文翻译。 In the model spec, 在型号规格中,
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 功能规格
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
会更好。 expect(page).to have_content
and the like) 需要关于索引页面上的内容的expect(page).to have_content
等)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.