Class: Parse::Phone
- Inherits:
-
Object
- Object
- Parse::Phone
- Defined in:
- lib/parse/model/phone.rb
Overview
This class provides E.164 phone number validation and formatting for Parse properties. E.164 is the international telephone numbering format that ensures worldwide uniqueness.
Format: +[country code][subscriber number]
-
Must start with +
-
Country code: 1-3 digits (cannot start with 0)
-
Subscriber number: remaining digits
-
Total length: 8-15 digits (including country code)
Enhanced Validation with phonelib
For comprehensive phone number validation (including carrier validation, number type detection, and accurate country-specific rules), add the ‘phonelib` gem to your Gemfile:
gem 'phonelib'
When phonelib is available, Parse::Phone will use Google’s libphonenumber data for:
-
Accurate validation for all countries and territories
-
Number type detection (mobile, landline, toll-free, etc.)
-
Carrier information
-
Proper formatting per country standards
Without phonelib, basic E.164 format validation is used (sufficient for most use cases).
Constant Summary collapse
- E164_REGEX =
E.164 format regex (strict validation for fallback mode)
-
Starts with +
-
Country code: 1-3 digits, cannot start with 0
-
Total digits: 8-15 (E.164 max is 15 digits total including country code)
-
/\A\+[1-9]\d{6,14}\z/- STRIP_NON_DIGITS =
Regex to strip non-digit characters (except +)
/[^\d+]/
Instance Attribute Summary collapse
-
#number ⇒ String
readonly
The normalized E.164 formatted number (or nil if invalid input).
-
#raw ⇒ String
readonly
The raw input value.
Class Method Summary collapse
-
.phonelib_available? ⇒ Boolean
Check if phonelib is available for enhanced validation.
-
.typecast(value) ⇒ Parse::Phone?
private
Type casting support for Parse properties.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Check equality with another phone number.
-
#as_json(*args) ⇒ String?
The E.164 formatted phone number for JSON serialization.
-
#blank? ⇒ Boolean
True if the phone number is blank/nil.
-
#carrier ⇒ String?
Get the carrier name for this phone number.
-
#country ⇒ String?
Get the two-letter ISO country code.
-
#country_code ⇒ String?
Get the country code portion of the phone number.
-
#country_name ⇒ String?
Get the country/region name for this phone number’s country code.
-
#errors ⇒ Array<String>
Get validation errors for this phone number.
-
#formatted(format = :international) ⇒ String?
Format the phone number for display.
-
#geo_name ⇒ String?
Get the geographic area for this phone number.
-
#initialize(value) ⇒ Phone
constructor
Creates a new Phone instance.
-
#invalid? ⇒ Boolean
Check if the phone number is invalid.
-
#mobile? ⇒ Boolean?
Check if this is a mobile phone number.
-
#national ⇒ String?
Get the national (subscriber) number without country code.
-
#normalize(value) ⇒ String?
Normalize a phone number string to E.164 format.
-
#phone_type ⇒ Symbol?
Get the phone number type (mobile, landline, etc.).
-
#possible? ⇒ Boolean
Check if the phone number is possibly valid (quick check).
-
#present? ⇒ Boolean
True if the phone number is present.
-
#to_s ⇒ String?
The E.164 formatted phone number.
-
#valid? ⇒ Boolean
Check if this phone number is valid E.164 format.
Constructor Details
#new(number) ⇒ Parse::Phone #new(phone) ⇒ Parse::Phone
Creates a new Phone instance.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/parse/model/phone.rb', line 113 def initialize(value) @raw = nil @number = nil @phonelib_phone = nil if value.is_a?(String) @raw = value @number = normalize(value) elsif value.is_a?(Parse::Phone) @raw = value.raw @number = value.number elsif value.respond_to?(:to_s) && !value.nil? @raw = value.to_s @number = normalize(@raw) end # Parse with phonelib if available @phonelib_phone = Phonelib.parse(@number) if PHONELIB_AVAILABLE && @number end |
Instance Attribute Details
#number ⇒ String (readonly)
Returns the normalized E.164 formatted number (or nil if invalid input).
98 99 100 |
# File 'lib/parse/model/phone.rb', line 98 def number @number end |
#raw ⇒ String (readonly)
Returns the raw input value.
95 96 97 |
# File 'lib/parse/model/phone.rb', line 95 def raw @raw end |
Class Method Details
.phonelib_available? ⇒ Boolean
Check if phonelib is available for enhanced validation
77 78 79 |
# File 'lib/parse/model/phone.rb', line 77 def phonelib_available? PHONELIB_AVAILABLE end |
.typecast(value) ⇒ Parse::Phone?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Type casting support for Parse properties. This allows the property system to convert values to Phone instances.
87 88 89 90 91 |
# File 'lib/parse/model/phone.rb', line 87 def typecast(value) return nil if value.nil? return value if value.is_a?(Parse::Phone) Parse::Phone.new(value) end |
Instance Method Details
#==(other) ⇒ Boolean
Check equality with another phone number.
339 340 341 342 343 344 345 346 347 |
# File 'lib/parse/model/phone.rb', line 339 def ==(other) if other.is_a?(Parse::Phone) @number == other.number elsif other.is_a?(String) @number == normalize(other) else false end end |
#as_json(*args) ⇒ String?
Returns the E.164 formatted phone number for JSON serialization.
157 158 159 |
# File 'lib/parse/model/phone.rb', line 157 def as_json(*args) @number end |
#blank? ⇒ Boolean
Returns true if the phone number is blank/nil.
350 351 352 |
# File 'lib/parse/model/phone.rb', line 350 def blank? @number.blank? end |
#carrier ⇒ String?
Get the carrier name for this phone number. Requires phonelib and may not be available for all numbers.
277 278 279 280 |
# File 'lib/parse/model/phone.rb', line 277 def carrier return nil unless PHONELIB_AVAILABLE && @phonelib_phone&.valid? @phonelib_phone.carrier end |
#country ⇒ String?
Get the two-letter ISO country code. Requires phonelib for accurate detection.
227 228 229 230 |
# File 'lib/parse/model/phone.rb', line 227 def country return nil unless PHONELIB_AVAILABLE && @phonelib_phone&.valid? @phonelib_phone.country end |
#country_code ⇒ String?
Get the country code portion of the phone number.
210 211 212 213 214 215 216 217 218 |
# File 'lib/parse/model/phone.rb', line 210 def country_code return nil unless valid? if PHONELIB_AVAILABLE && @phonelib_phone @phonelib_phone.country_code else extract_country_code_fallback end end |
#country_name ⇒ String?
Get the country/region name for this phone number’s country code.
298 299 300 301 302 303 304 305 306 |
# File 'lib/parse/model/phone.rb', line 298 def country_name if PHONELIB_AVAILABLE && @phonelib_phone&.valid? iso_code = @phonelib_phone.country ISO_COUNTRY_NAMES[iso_code] if iso_code else cc = country_code FALLBACK_COUNTRY_NAMES[cc] if cc end end |
#errors ⇒ Array<String>
Get validation errors for this phone number. Useful for providing user feedback.
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/parse/model/phone.rb', line 363 def errors return [] if valid? return ["Phone number is required"] if @number.blank? if PHONELIB_AVAILABLE && @phonelib_phone result = [] # Phonelib uses impossible? for basic length/format check if @phonelib_phone.impossible? sanitized = @phonelib_phone.sanitized result << "Phone number is too short" if sanitized.length < 7 result << "Phone number is too long" if sanitized.length > 15 end result << "Invalid phone number format" if result.empty? result else ["Invalid E.164 phone number format"] end end |
#formatted(format = :international) ⇒ String?
Format the phone number for display. When phonelib is available, uses proper country-specific formatting. Otherwise, provides basic formatted version.
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/parse/model/phone.rb', line 318 def formatted(format = :international) return nil unless valid? if PHONELIB_AVAILABLE && @phonelib_phone case format when :national @phonelib_phone.national when :e164 @phonelib_phone.e164 else @phonelib_phone.international end else format_fallback end end |
#geo_name ⇒ String?
Get the geographic area for this phone number. Requires phonelib and may not be available for mobile numbers.
286 287 288 289 |
# File 'lib/parse/model/phone.rb', line 286 def geo_name return nil unless PHONELIB_AVAILABLE && @phonelib_phone&.valid? @phonelib_phone.geo_name end |
#invalid? ⇒ Boolean
Check if the phone number is invalid.
199 200 201 |
# File 'lib/parse/model/phone.rb', line 199 def invalid? !valid? end |
#mobile? ⇒ Boolean?
Check if this is a mobile phone number. Requires phonelib for accurate detection.
267 268 269 270 271 |
# File 'lib/parse/model/phone.rb', line 267 def mobile? type = phone_type return nil if type.nil? [:mobile, :fixed_or_mobile].include?(type) end |
#national ⇒ String?
Get the national (subscriber) number without country code.
238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/parse/model/phone.rb', line 238 def national return nil unless valid? if PHONELIB_AVAILABLE && @phonelib_phone @phonelib_phone.national(false)&.gsub(/\D/, "") else cc = country_code return nil unless cc @number[(cc.length + 1)..] # Skip + and country code end end |
#normalize(value) ⇒ String?
Normalize a phone number string to E.164 format. Removes all non-digit characters except leading +.
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/parse/model/phone.rb', line 138 def normalize(value) return nil if value.blank? # Remove all non-digit characters except + cleaned = value.to_s.gsub(STRIP_NON_DIGITS, "") # If it doesn't start with +, add it cleaned = "+#{cleaned}" unless cleaned.start_with?("+") # Return the cleaned value (may still be invalid, but we store it) cleaned end |
#phone_type ⇒ Symbol?
Get the phone number type (mobile, landline, etc.). Requires phonelib for type detection.
257 258 259 260 261 |
# File 'lib/parse/model/phone.rb', line 257 def phone_type return nil unless PHONELIB_AVAILABLE && @phonelib_phone&.valid? types = @phonelib_phone.types types.first if types.any? end |
#possible? ⇒ Boolean
Check if the phone number is possibly valid (quick check). This is faster than full validation and useful for input feedback. Falls back to valid? when phonelib is not available.
186 187 188 189 190 191 192 193 194 |
# File 'lib/parse/model/phone.rb', line 186 def possible? return false if @number.blank? if PHONELIB_AVAILABLE && @phonelib_phone @phonelib_phone.possible? else valid? end end |
#present? ⇒ Boolean
Returns true if the phone number is present.
355 356 357 |
# File 'lib/parse/model/phone.rb', line 355 def present? !blank? end |
#to_s ⇒ String?
Returns the E.164 formatted phone number.
152 153 154 |
# File 'lib/parse/model/phone.rb', line 152 def to_s @number end |
#valid? ⇒ Boolean
Check if this phone number is valid E.164 format. When phonelib is available, uses comprehensive validation. Otherwise, uses basic E.164 regex validation.
171 172 173 174 175 176 177 178 179 |
# File 'lib/parse/model/phone.rb', line 171 def valid? return false if @number.blank? if PHONELIB_AVAILABLE && @phonelib_phone @phonelib_phone.valid? else E164_REGEX.match?(@number) end end |