Formatting a phone number
You're already using a regex to check that the phone number is 10 digits, but you could also make it more precise, and use it to split the string apart:

def obtain_phone_number
  loop do
    print "Enter phone number: "
    phone_num = gets.chomp
    if phone_num =~ /^(\d{3})(\d{3})(\d{4})$/
      return "(#{$1})#{$2}-#{$3}"
    else
      puts "Invalid phone number, must contain 10 digits only"
    end
  end
end


When the =~ matching runs, it assigns the capture groups to the global $1, $2 etc. variables, so it's easy to glue a string back together from those parts. You can fiddle with it to make it accept more than 10 digits, if you want.

However, I would move the loop somewhere else, and just have the method return a formatted string or nil. Or possibly string, nil or raise an exception. If you get nil back, the user entered nothing (e.g. user cancelled/left it blank). If it raises an error, the user did input something, but it was invalid, and you can warn and retry.

Right now, if you call the method, you can never escape it without entering a number. I don't know the usage context for this, but I'd imagine it'd make sense to allow the user to skip somehow, rather than forcing them to input nonsense just to proceed.

So something like this might be better:

def obtain_phone_number
  phone_num = gets.chomp
  return nil if phone_num.empty?
  if phone_num =~ /^(\d{3})(\d{3})(\d{4})$/
    "(#{$1})#{$2}-#{$3}"
  else
    raise "Invalid input"
  end
end

# simple usage example
begin
  print "Enter phone number: "
  phone = obtain_phone_number
  puts phone
rescue StandardError
  puts "Invalid phone number, must contain 10 digits only"
  retry
end