class TrackingNumber::Base

Attributes

original_number[RW]
tracking_number[RW]

Public Class Methods

new(tracking_number) click to toggle source
# File lib/tracking_number/base.rb, line 6
def initialize(tracking_number)
  @original_number = tracking_number
  @tracking_number = tracking_number.strip.gsub(" ", "").upcase
end
scan(body) click to toggle source
# File lib/tracking_number/base.rb, line 22
def self.scan(body)
  # matches with match groups within the match data
  matches = []

  body.scan(self.const_get(:SEARCH_PATTERN)){
    #get the match data instead, which is needed with these types of regexes
    matches << $~
  }

  if matches
    matches.collect { |m| m[0] }
  else
    []
  end
end

Public Instance Methods

carrier()
Alias for: courier_code
carrier_code()
Alias for: courier_code
carrier_name()
Alias for: courier_name
check_digit() click to toggle source
# File lib/tracking_number/base.rb, line 55
def check_digit
  match_group("CheckDigit")
end
courier_code() click to toggle source
# File lib/tracking_number/base.rb, line 118
def courier_code
  self.class.const_get(:COURIER_CODE).to_sym
end
Also aliased as: carrier, carrier_code
courier_info() click to toggle source
# File lib/tracking_number/base.rb, line 136
def courier_info
  basics = {:name => courier_name, :code => courier_code}

  if info = matching_additional["Courier"]
    basics.merge!(:name => info[:courier], :url => info[:courier_url], :country => info[:country])
  end

  @courier ||= Info.new(basics)
end
courier_name() click to toggle source
# File lib/tracking_number/base.rb, line 122
def courier_name
  if matching_additional["Courier"]
    matching_additional["Courier"][:courier]
  else
    if self.class.constants.include?(:COURIER_INFO)
      self.class.const_get(:COURIER_INFO)[:name]
    end
  end
end
Also aliased as: carrier_name
decode() click to toggle source
# File lib/tracking_number/base.rb, line 59
def decode
  decoded = {}
  (self.matches.try(:names) || []).each do |name|
    sym = name.underscore.to_sym
    decoded[sym] = self.matches[name]
  end

  decoded
end
destination_zip() click to toggle source
# File lib/tracking_number/base.rb, line 164
def destination_zip
  match_group("DestinationZip")
end
info() click to toggle source
# File lib/tracking_number/base.rb, line 107
def info
  Info.new({
    :courier => courier_info,
    :service_type => service_type,
    :service_description => service_description,
    :destination_zip => destination_zip,
    :shipper_id => shipper_id,
    :package_type => package_type
  })
end
inspect() click to toggle source
# File lib/tracking_number/base.rb, line 103
def inspect
  "#<%s:%#0x %s>" % [self.class.to_s, self.object_id, tracking_number]
end
matching_additional() click to toggle source
# File lib/tracking_number/base.rb, line 187
def matching_additional
  additional = self.class.const_get(:ADDITIONAL) || []

  relevant_sections = {}

  additional.each do |info|
    if self.matches && self.matches.length > 0
      if value = self.matches[info[:regex_group_name]].gsub(/\s/, "")
        # has matching value
        matches = info[:lookup].find do |i|
          if i[:matches]
            value == i[:matches]
          elsif i[:matches_regex]
            value =~ Regexp.new(i[:matches_regex])
          end
        end

        relevant_sections[info[:name]] = matches
      end
    end
  end

  relevant_sections
end
package_type() click to toggle source
# File lib/tracking_number/base.rb, line 158
def package_type
  if matching_additional["Container Type"]
    @package_type ||= Info.new(matching_additional["Container Type"]).name
  end
end
serial_number() click to toggle source
# File lib/tracking_number/base.rb, line 38
def serial_number
  return match_group("SerialNumber") unless self.class.const_get("VALIDATION")

  format_info   = self.class.const_get(:VALIDATION)[:serial_number_format]
  raw_serial    = match_group("SerialNumber")

  if format_info
    if format_info[:prepend_if] && raw_serial.match(Regexp.new(format_info[:prepend_if][:matches_regex]))
      return "#{format_info[:prepend_if][:content]}#{raw_serial}"
    elsif format_info[:prepend_if_missing]

    end
  end

  return raw_serial
end
service_description() click to toggle source
# File lib/tracking_number/base.rb, line 152
def service_description
  if matching_additional["Service Type"]
    @service_description ||= Info.new(matching_additional["Service Type"]).description
  end
end
service_type() click to toggle source
# File lib/tracking_number/base.rb, line 146
def service_type
  if matching_additional["Service Type"]
    @service_type ||= Info.new(matching_additional["Service Type"]).name
  end
end
shipper_id() click to toggle source
# File lib/tracking_number/base.rb, line 168
def shipper_id
  match_group("ShipperId")
end
to_s() click to toggle source
# File lib/tracking_number/base.rb, line 99
def to_s
  self.tracking_number
end
tracking_url() click to toggle source
# File lib/tracking_number/base.rb, line 172
def tracking_url
  url = nil
  if matching_additional["Courier"]
    url = matching_additional["Courier"][:tracking_url]
  else
    if self.class.const_defined?(:TRACKING_URL)
      url = self.class.const_get(:TRACKING_URL)
    end
  end

  if url
    url.sub('%s', self.tracking_number)
  end
end
valid?() click to toggle source
# File lib/tracking_number/base.rb, line 69
def valid?
  return false unless valid_format?
  return false unless valid_checksum?
  return false unless valid_optional_checks?
  return true
end
valid_checksum?() click to toggle source
# File lib/tracking_number/base.rb, line 88
def valid_checksum?
  return false unless self.valid_format?
  checksum_info   = self.class.const_get(:VALIDATION)[:checksum]
  return true unless checksum_info

  name            = checksum_info[:name]
  method_name     = "validates_#{name}?"

  TrackingNumber::ChecksumValidations.send(method_name, serial_number, check_digit, checksum_info)
end
valid_format?() click to toggle source
# File lib/tracking_number/base.rb, line 76
def valid_format?
  !matches.nil?
end
valid_optional_checks?() click to toggle source
# File lib/tracking_number/base.rb, line 80
def valid_optional_checks?
  additional_check = self.class.const_get("VALIDATION")[:additional]
  return true unless additional_check

  exist_checks = (additional_check[:exists] ||= [])
  exist_checks.all? { |w| matching_additional[w] }
end

Protected Instance Methods

match_group(name) click to toggle source
# File lib/tracking_number/base.rb, line 222
def match_group(name)
  begin
    self.matches[name].gsub(/\s/, '')
  rescue
    nil
  end
end
matches() click to toggle source
# File lib/tracking_number/base.rb, line 214
def matches
  if self.class.constants.include?(:VERIFY_PATTERN)
    self.tracking_number.match(self.class.const_get(:VERIFY_PATTERN))
  else
    []
  end
end