扩展apipie-rails的NumberValidator添加min/max校验时描述返回异常问题
问题根因
- 你的
description方法硬编码了范围校验提示,没有区分「非有效数字」和「数值超出范围」两种错误场景,所有校验失败都会返回自定义的范围提示 validate方法逻辑存在错误:配置min、max时,范围校验失败后没有正确返回false,会执行最后的true导致范围校验不生效;多余的self.class.validate(value)调用存在递归风险- 没有复用原生
NumberValidator的错误描述,数值格式校验失败时需要返回原生校验器自带的提示
修正后代码
class NumberValidator < Apipie::Validator::BaseValidator def initialize(param_description, argument, options) super(param_description) @number_validator = Apipie::Validator::NumberValidator.new(param_description) @type = argument @options = options # 记录校验失败类型::invalid_number表示非有效数字,:out_of_range表示超出范围 @validation_failed_type = nil end def validate(value) # 优先走原生数字格式校验 unless @number_validator.valid?(value) @validation_failed_type = :invalid_number return false end # 未配置范围校验直接判定有效 return true unless @options[:min] && @options[:max] # 范围校验 unless value.to_i.between?(@options[:min], @options[:max]) @validation_failed_type = :out_of_range return false end true end def self.build(param_description, argument, options, block) self.new(param_description, argument, options) if argument == :number end def description # 数字格式校验失败返回原生提示 return @number_validator.description if @validation_failed_type == :invalid_number # 未配置范围时返回原生提示 return @number_validator.description unless @options[:min] && @options[:max] # 范围校验失败返回自定义提示 "Must be a number between #{@options[:min]} and #{@options[:max]}." end end
实现说明
- 新增实例变量记录校验失败的类型,作为返回不同错误描述的依据
- 数值格式校验失败时,直接复用原生校验器的「Must be a number」提示
- 仅当数值合法但超出min/max范围时,才返回自定义的范围提示
- 兼容未配置min、max的场景,此时功能和原生NumberValidator完全一致
内容的提问来源于stack exchange,提问作者OwenH
相关产品推荐
相关产品推荐

