String#gsub
is used to replace a specific text with another string. For example, "hello world".gsub(/hello/, "goodbye")
would result in "goodbye world"
. The non-bang variant, gsub
, does not modify the string itself; whereas the bang variant, gsub!
, does:
test = "hello world"
test.gsub(/h[ae]ll[ou]/, "goodbye") # => "goodbye world"
test # => "hello world"
test.gsub!(/h[ae]ll[ou]/, "goodbye") # => "goodbye world"
test # => "goodbye world"
String#scan
"scans" the string for a certain pattern, and returns an array of occurrences. This is useful for extracting certain things from a string:
tweet = "@github @you hello, world!"
tweet.scan(/@[\w]+/) # => ["@github", "@you"]
However, if you include groups within the scan, it returns an array of an array of group matches:
tweet.scan(/@([\w]+)/) # => [["github", "you"]]
So, what .gsub!(/\D/, "")
does is it removes all non-digit characters from the string, and modifies the string (this last bit isn't really important right now). .scan
looks for a phone number from the input (a phone number being an optional 1, followed by a set of three digits, followed by a set of three digits, followed by a set of four digits). Since it removes all non-digits from the input, it will attempt create a phone number from the first 10 or 11 numbers in the input, and for every 10 or 11 numbers past that.
However, the join joins together the sets of digits into a single string, 999.999.9999
. But if there are multiple phone numbers in the input, it will end up joining those phone numbers with a period, too.
Hope that helps.