Class: TrackingNumber::Base
- Inherits:
-
Object
- Object
- TrackingNumber::Base
- Defined in:
- lib/tracking_number/base.rb
Direct Known Subclasses
Defined Under Namespace
Classes: PartnerStruct
Constant Summary collapse
- LENGTH_WEIGHT =
0.1
- CHECKSUM_WEIGHT =
5.0
Instance Attribute Summary collapse
-
#original_number ⇒ Object
Returns the value of attribute original_number.
-
#partner ⇒ Object
Returns the value of attribute partner.
-
#partner_data ⇒ Object
Returns the value of attribute partner_data.
-
#tracking_number ⇒ Object
Returns the value of attribute tracking_number.
Class Method Summary collapse
Instance Method Summary collapse
- #carrier? ⇒ Boolean
- #check_digit ⇒ Object
- #checksum? ⇒ Boolean
- #confidence ⇒ Object
- #courier_code ⇒ Object (also: #carrier, #carrier_code)
- #courier_info ⇒ Object
- #courier_name ⇒ Object (also: #carrier_name)
- #decode ⇒ Object
- #destination_zip ⇒ Object
- #info ⇒ Object
-
#initialize(tracking_number) ⇒ Base
constructor
A new instance of Base.
- #inspect ⇒ Object
- #matching_additional ⇒ Object
- #package_type ⇒ Object
- #partners ⇒ Object
- #partnership? ⇒ Boolean
- #partnership_inspect ⇒ Object
- #serial_number ⇒ Object
- #service_description ⇒ Object
- #service_type ⇒ Object
- #shipper? ⇒ Boolean
- #shipper_id ⇒ Object
- #to_s ⇒ Object
- #tracking_url ⇒ Object
- #valid? ⇒ Boolean
- #valid_checksum? ⇒ Boolean
- #valid_format? ⇒ Boolean
- #valid_optional_checks? ⇒ Boolean
Constructor Details
#initialize(tracking_number) ⇒ Base
Returns a new instance of Base.
7 8 9 10 |
# File 'lib/tracking_number/base.rb', line 7 def initialize(tracking_number) @original_number = tracking_number @tracking_number = tracking_number.strip.gsub(' ', '').upcase end |
Instance Attribute Details
#original_number ⇒ Object
Returns the value of attribute original_number.
3 4 5 |
# File 'lib/tracking_number/base.rb', line 3 def original_number @original_number end |
#partner ⇒ Object
Returns the value of attribute partner.
3 4 5 |
# File 'lib/tracking_number/base.rb', line 3 def partner @partner end |
#partner_data ⇒ Object
Returns the value of attribute partner_data.
3 4 5 |
# File 'lib/tracking_number/base.rb', line 3 def partner_data @partner_data end |
#tracking_number ⇒ Object
Returns the value of attribute tracking_number.
3 4 5 |
# File 'lib/tracking_number/base.rb', line 3 def tracking_number @tracking_number end |
Class Method Details
.scan(body) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/tracking_number/base.rb', line 23 def self.scan(body) # matches with match groups within the match data matches = [] body.scan(const_get(:SEARCH_PATTERN)) do # get the match data instead, which is needed with these types of regexes matches << $~ end if matches matches.collect { |m| m[0] } else [] end end |
.search(body) ⇒ Object
12 13 14 15 16 17 18 19 20 21 |
# File 'lib/tracking_number/base.rb', line 12 def self.search(body) valids = scan(body).uniq.collect { |possible| new(possible) }.select { |t| t.valid? } uniques = {} valids.each do |t| uniques[t.tracking_number] = t unless uniques.has_key?(t.tracking_number) end uniques.values end |
Instance Method Details
#carrier? ⇒ Boolean
177 178 179 180 181 |
# File 'lib/tracking_number/base.rb', line 177 def carrier? return true unless partnership? partners.carrier == self end |
#check_digit ⇒ Object
54 55 56 |
# File 'lib/tracking_number/base.rb', line 54 def check_digit match_group('CheckDigit') end |
#checksum? ⇒ Boolean
100 101 102 |
# File 'lib/tracking_number/base.rb', line 100 def checksum? !!self.class.const_get(:VALIDATION)[:checksum] end |
#confidence ⇒ Object
107 108 109 |
# File 'lib/tracking_number/base.rb', line 107 def confidence (checksum? ? CHECKSUM_WEIGHT : 0) + tracking_number.length * LENGTH_WEIGHT end |
#courier_code ⇒ Object Also known as: carrier, carrier_code
141 142 143 |
# File 'lib/tracking_number/base.rb', line 141 def courier_code self.class.const_get(:COURIER_CODE).to_sym end |
#courier_info ⇒ Object
157 158 159 160 161 162 163 164 165 |
# File 'lib/tracking_number/base.rb', line 157 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 ⇒ Object Also known as: carrier_name
145 146 147 148 149 150 151 |
# File 'lib/tracking_number/base.rb', line 145 def courier_name if matching_additional['Courier'] matching_additional['Courier'][:courier] elsif self.class.constants.include?(:COURIER_INFO) self.class.const_get(:COURIER_INFO)[:name] end end |
#decode ⇒ Object
58 59 60 61 62 63 64 65 66 |
# File 'lib/tracking_number/base.rb', line 58 def decode decoded = {} (matches.try(:names) || []).each do |name| sym = name.underscore.to_sym decoded[sym] = matches[name] end decoded end |
#destination_zip ⇒ Object
212 213 214 |
# File 'lib/tracking_number/base.rb', line 212 def destination_zip match_group('DestinationZip') end |
#info ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/tracking_number/base.rb', line 127 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, tracking_url: tracking_url, partners: partners, decode: decode }) end |
#inspect ⇒ Object
115 116 117 |
# File 'lib/tracking_number/base.rb', line 115 def inspect format('#<%s:%#0x %s%s>', self.class.to_s, object_id, tracking_number, partnership_inspect) end |
#matching_additional ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/tracking_number/base.rb', line 231 def matching_additional additional = self.class.const_get(:ADDITIONAL) || [] relevant_sections = {} additional.each do |additional_info| next unless matches && matches.length > 0 # skip if no match groups value = matches[additional_info[:regex_group_name]].gsub(/\s/, '') # match is empty next unless value matches = additional_info[:lookup].find do |i| if i[:matches] value == i[:matches] elsif i[:matches_regex] value =~ Regexp.new(i[:matches_regex]) end end # has matching value relevant_sections[additional_info[:name]] = matches end relevant_sections end |
#package_type ⇒ Object
208 209 210 |
# File 'lib/tracking_number/base.rb', line 208 def package_type @package_type ||= Info.new(matching_additional['Container Type']).name if matching_additional['Container Type'] end |
#partners ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/tracking_number/base.rb', line 183 def partners return unless self.class.const_defined?(:PARTNERS) partner_hash = {} return unless (partner_tn = find_matching_partner) possible_twin = partner_tn.send(:find_matching_partner) if possible_twin.instance_of?(self.class) && possible_twin.tracking_number == tracking_number partner_hash[partner_data[:partner_type].to_sym] = partner_tn partner_hash[partner_tn.partner_data[:partner_type].to_sym] = self end PartnerStruct.new(partner_hash[:shipper], partner_hash[:carrier]) if partner_hash.keys.any? end |
#partnership? ⇒ Boolean
167 168 169 |
# File 'lib/tracking_number/base.rb', line 167 def partnership? partners.present? end |
#partnership_inspect ⇒ Object
119 120 121 122 123 124 125 |
# File 'lib/tracking_number/base.rb', line 119 def partnership_inspect if shipper? ^ carrier? ' (partnership)' else '' end end |
#serial_number ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/tracking_number/base.rb', line 39 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 && 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 && format_info[:prepend_if_missing] end raw_serial end |
#service_description ⇒ Object
204 205 206 |
# File 'lib/tracking_number/base.rb', line 204 def service_description @service_description ||= Info.new(matching_additional['Service Type']).description if matching_additional['Service Type'] end |
#service_type ⇒ Object
200 201 202 |
# File 'lib/tracking_number/base.rb', line 200 def service_type @service_type ||= Info.new(matching_additional['Service Type']).name if matching_additional['Service Type'] end |
#shipper? ⇒ Boolean
171 172 173 174 175 |
# File 'lib/tracking_number/base.rb', line 171 def shipper? return true unless partnership? partners.shipper == self end |
#shipper_id ⇒ Object
216 217 218 |
# File 'lib/tracking_number/base.rb', line 216 def shipper_id match_group('ShipperId') end |
#to_s ⇒ Object
111 112 113 |
# File 'lib/tracking_number/base.rb', line 111 def to_s tracking_number end |
#tracking_url ⇒ Object
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/tracking_number/base.rb', line 220 def tracking_url url = nil if matching_additional['Courier'] url = matching_additional['Courier'][:tracking_url] elsif self.class.const_defined?(:TRACKING_URL) url = self.class.const_get(:TRACKING_URL) end url.sub('%s', tracking_number) if url end |
#valid? ⇒ Boolean
68 69 70 71 72 73 74 |
# File 'lib/tracking_number/base.rb', line 68 def valid? return false unless valid_format? return false unless valid_checksum? return false unless valid_optional_checks? true end |
#valid_checksum? ⇒ Boolean
88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/tracking_number/base.rb', line 88 def valid_checksum? return false unless 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? ⇒ Boolean
76 77 78 |
# File 'lib/tracking_number/base.rb', line 76 def valid_format? !matches.nil? end |
#valid_optional_checks? ⇒ Boolean
80 81 82 83 84 85 86 |
# 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 |