Module: AddressHelper
- Defined in:
- app/helpers/address_helper.rb
Instance Method Summary collapse
-
#canadian_postal_code?(code) ⇒ Boolean
Detects Canadian postal code format.
-
#clean_city(raw) ⇒ Object
Helper to clean up city.
-
#normalize_postal_code(postal_code) ⇒ String?
Normalizes postal code for comparison.
-
#parse_address_line(address_line) ⇒ Hash
Parses an address line into city, state, and normalized postal_code.
-
#parse_address_parts(address_hash, type:) ⇒ Hash
Determines the city, state, and postal_code fields with fallback parsing logic.
-
#us_zip_code?(code) ⇒ Boolean
Detects US ZIP code format.
-
#valid_city?(city) ⇒ Boolean
Checks if the city value is valid (not blank and not numeric-only).
-
#valid_state?(state) ⇒ Boolean
Checks if the state value is valid (not blank and exactly 2 characters).
Instance Method Details
#canadian_postal_code?(code) ⇒ Boolean
Detects Canadian postal code format
153 154 155 |
# File 'app/helpers/address_helper.rb', line 153 def canadian_postal_code?(code) !!(code =~ /^[A-Z]\d[A-Z][ ]?\d[A-Z]\d$/) end |
#clean_city(raw) ⇒ Object
Helper to clean up city
115 116 117 118 119 120 121 122 |
# File 'app/helpers/address_helper.rb', line 115 def clean_city(raw) return '' if raw.blank? cleaned = raw.strip # Remove trailing commas cleaned.gsub(/,+$/, '').strip end |
#normalize_postal_code(postal_code) ⇒ String?
Normalizes postal code for comparison
For Canadian postal codes:
- Removes spaces
- Uppercases
For US ZIP codes:
- Removes hyphens
135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'app/helpers/address_helper.rb', line 135 def normalize_postal_code(postal_code) return nil if postal_code.blank? code = postal_code.strip.upcase if canadian_postal_code?(code) code.gsub(/\s+/, '') elsif us_zip_code?(code) code.gsub('-', '') else code end end |
#parse_address_line(address_line) ⇒ Hash
Parses an address line into city, state, and normalized postal_code
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'app/helpers/address_helper.rb', line 61 def parse_address_line(address_line) return { city: '', state: '', postal_code: '' } if address_line.blank? # Remove trailing country name if present address_line = address_line.gsub(/\s+(Canada|USA|US)$/i, '').strip result = {} raw_postal_code = nil # Unified regex to match Canadian or US postal codes regex = / ^\s* (?<city>.*?) (?:,\s*)? (?<state>[A-Z]{2}) \s+ (?<postal> [A-Z]\d[A-Z]\s*\d[A-Z]\d | \d{5}(?:-\d{4})? ) $ /ix if (match = address_line.match(regex)) raw_city = match[:city] result[:city] = clean_city(raw_city) result[:state] = match[:state].strip.upcase raw_postal_code = match[:postal] else # Fallback generic splitting parts = address_line.split(/\s+/) return { city: '', state: '', postal_code: '' } unless parts.size >= 3 result[:city] = parts[0..-3].join(' ').strip result[:state] = parts[-2].strip.upcase raw_postal_code = parts[-1] end # Validate city result[:city] = '' if result[:city].blank? || result[:city].match?(/^\d+$/) # Validate state result[:state] = '' if result[:state].blank? || result[:state].length != 2 # Validate postal code result[:postal_code] = if raw_postal_code.blank? || !(canadian_postal_code?(raw_postal_code) || us_zip_code?(raw_postal_code)) '' else normalize_postal_code(raw_postal_code) end result end |
#parse_address_parts(address_hash, type:) ⇒ Hash
Determines the city, state, and postal_code fields with fallback parsing logic. For ShipAddr and BillAddr with different priorities.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'app/helpers/address_helper.rb', line 8 def parse_address_parts(address_hash, type:) if address_hash.present? && address_hash['City'].present? && address_hash['CountrySubDivisionCode'].present? && address_hash['PostalCode'].present? { city: address_hash['City'], state: address_hash['CountrySubDivisionCode'], postal_code: address_hash['PostalCode'] } else line1 = address_hash&.dig('Line1') line2 = address_hash&.dig('Line2') line3 = address_hash&.dig('Line3') line4 = address_hash&.dig('Line4') line5 = address_hash&.dig('Line5') line_to_parse = if type == :ship_to if line5.present? && line5.match?(/\d/) line5 elsif line4.present? && line4.match?(/\d/) line4 else line3 end elsif line4.present? && line4.match?(/\d/) # :bill_to line4 elsif line3.present? && line3.match?(/\d/) line3 elsif line2.blank? && line3.blank? && line4.blank? if line1.present? && line1.match?(/\d/) line1 else nil end else nil end if line_to_parse.present? parse_address_line(line_to_parse) else { city: '', state: '', postal_code: '' } end end end |
#us_zip_code?(code) ⇒ Boolean
Detects US ZIP code format
161 162 163 |
# File 'app/helpers/address_helper.rb', line 161 def us_zip_code?(code) !!(code =~ /^\d{5}(-\d{4})?$/) end |
#valid_city?(city) ⇒ Boolean
Checks if the city value is valid (not blank and not numeric-only)
169 170 171 172 173 |
# File 'app/helpers/address_helper.rb', line 169 def valid_city?(city) return false if city.blank? !city.strip.match?(/^\d+$/) end |
#valid_state?(state) ⇒ Boolean
Checks if the state value is valid (not blank and exactly 2 characters)
179 180 181 182 183 |
# File 'app/helpers/address_helper.rb', line 179 def valid_state?(state) return false if state.blank? state.strip.length == 2 end |