3

我正在使用干类型和干结构,我想进行条件验证。

对于班级:

class Tax < Dry::Struct
  attribute :tax_type, Types::String.constrained(min_size: 2, max_size: 3, included_in: %w[IVA IS NS])
  attribute :tax_country_region, Types::String.constrained(max_size: 5)
  attribute :tax_code, Types::String.constrained(max_size: 10)
  attribute :description, Types::String.constrained(max_size: 255)
  attribute :tax_percentage, Types::Integer
  attribute :tax_ammount, Types::Integer.optional
end

如果'tax_type =='IS' ,我想验证tax_ammount为整数和强制性。

4

1 回答 1

9

dry-struct真正用于基本类型断言和强制。

如果您想要更复杂的验证,那么您可能也想要实现dry-validation(如 推荐的那样dry-rb

请参阅Validating data with dry-struct哪些状态

请不要。结构旨在与有效输入一起工作,它不能生成足以向用户显示它们的错误消息等。使用干验证来验证传入数据,然后将其输出传递给结构。

使用的条件验证dry-validation类似于

TaxValidation = Dry::Validation.Schema do

  # Could be:
  #   required(:tax_type).filled(:str?, 
  #      size?: 2..3, 
  #      included_in?: %w(IVA IS NS)) 
  # but since we are validating against a list of Strings I figured the rest was implied
  required(:tax_type).filled(included_in?: %w(IVA IS NS)) 
  optional(:tax_amount).maybe(:int?)

  # rule name is of your choosing and will be used 
  # as the errors key (i just chose `tax_amount` for consistency)
  rule(tax_amount:[:tax_type, :tax_amount]) do |tax_type, tax_amount|
    tax_type.eql?('IS').then(tax_amount.filled?) 
  end
end
  • 这需要tax_type%w(IVA IS NS)列表中;
  • 允许tax_amount是可选的,但如果已填写,则必须是Integer( int?) 和;
  • 如果tax_type == 'IS'( eql?('IS')) 则tax_amount必须填写(这意味着它必须是Integer基于上述规则的)。

显然,您也可以验证您的其他输入,但为了简洁起见,我将它们省略了。

例子:

TaxValidation.({}).success?
#=> false
TaxValidation.({}).errors
# => {:tax_type=>["is missing"]}
TaxValidation.({tax_type: 'NO'}).errors
#=>  {:tax_type=>["must be one of: IVA, IS, NS"]}
TaxValidation.({tax_type: 'NS'}).errors
#=>  {}
TaxValidation.({tax_type: 'IS'}).errors
#=> {:tax_amount=>["must be filled"]}
TaxValidation.({tax_type: 'IS',tax_amount:'NO'}).errors
#=> {:tax_amount=>["must be an integer"]}
TaxValidation.({tax_type: 'NS',tax_amount:12}).errors 
#=> {}
TaxValidation.({tax_type: 'NS',tax_amount:12}).success?
#=> true 
于 2018-11-12T21:14:59.020 回答