class ActiveModel::Validations::TrackingNumberValidator
Constants
- MOD10_WEIGHTS
- MOD11_WEIGHTS
- UPS_REGEXES
UPS: ups tracking codes are validated solely on their format see www.ups.com/content/us/en/tracking/help/tracking/tnh.html
- USS128_REGEX
- USS39_REGEX
Public Instance Methods
usps_mod10(chars)
click to toggle source
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 46 def usps_mod10(chars) (10 - weighted_sum(chars.reverse, MOD10_WEIGHTS) % 10) % 10 end
usps_mod11(chars)
click to toggle source
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 51 def usps_mod11(chars) mod = weighted_sum(chars, MOD11_WEIGHTS) % 11 case mod when 0 then 5 when 1 then 0 else 11 - mod end end
uss228?(value)
click to toggle source
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 32 def uss228?(value) m = value.match(USS128_REGEX) m.present? && (m[2].to_i == usps_mod10(m[1])) end
uss39?(value)
click to toggle source
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 38 def uss39?(value) m = value.match(USS39_REGEX) # it appears to be valid for a USS39 barcode's checkdigit to be calculated with either the usps mod 10 # algorithm or the usps mod 11. m.present? && (m[2].to_i == usps_mod10(m[1]) || m[2].to_i == usps_mod11(m[1])) end
valid_ups?(value)
click to toggle source
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 16 def valid_ups?(value) !!UPS_REGEXES.detect { |fmt| value.match(fmt) } end
valid_usps?(value)
click to toggle source
USPS: usps tracking codes are validated based on format (one of USS228 or USS39) and a check digit (using either of the USPS's MOD10 or MOD11 algorithms) see USPS Publications:
- #91 (05/2008) pp. 38 - #97 (05/2002) pp. 62-63 - #109 (09/2007) pp. 19-21
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 27 def valid_usps?(value) uss228?(value) || uss39?(value) end
validate_each(record, attribute, value)
click to toggle source
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 4 def validate_each(record, attribute, value) carrier = options[:carrier] || (options[:carrier_field] && record.send(options[:carrier_field])) raise "Carrier option required" unless carrier method = "valid_#{carrier.to_s}?" raise "Tracking number validation not supported for carrier #{carrier}" unless self.respond_to?(method) record.errors.add(attribute) if value.blank? || !self.send(method, value) end
weighted_sum(value, weights)
click to toggle source
takes a string containing digits and calculates a checksum using the provided weight array cycles the weight array if it's not long enough
# File lib/active_validators/active_model/validations/tracking_number_validator.rb, line 62 def weighted_sum(value, weights) digits = value.split('').map { |d| d.to_i } weights = weights.cycle.take(digits.count) if weights.count < digits.count digits.zip(weights).inject(0) { |s,p| s + p[0] * p[1] } end