【问题标题】:Is there a gem that normalizes and format US phone numbers in ruby?是否有一种宝石可以在 ruby​​ 中规范化和格式化美国电话号码?
【发布时间】:2011-08-20 05:45:27
【问题描述】:

我使用 phony 来格式化电话号码(意思是,如果我输入 xxx-xxx-xxxx,它会转换为字符串,并且还会告诉之前是否有 (1) 以将其删除)。

但它确实不适用于我们的电话号码,它是为国际号码设计的。

有没有等价物?

谢谢。

http://rubygems.org/gems/phony

【问题讨论】:

  • 在String类中写方法不行?
  • 我该怎么做——可以添加到 lib 文件中吗?
  • 是的,作为一个类 String.rb 然后定义类 String 然后你的方法 "def convert_to_phone_number"\
  • @kyle -- 嗯,该方法实际上是什么来遍历逻辑...有时值是 xxx-xxxx-xxxx 但我可能想规范化为 xxxxxxxx... ..
  • 但是当我想显示时,我希望它以 xxx-xxx-xxxx 的形式......这有意义吗?

标签: ruby-on-rails ruby phone-number


【解决方案1】:

今年早些时候,我回顾了一堆解析和格式化电话号码的 ruby​​ gem。它们分为许多组(见下文)。 TLDR:我使用了“电话”。它可能对您有用,因为如果您的电话号码不包含国家代码,您可以指定它使用的默认国家代码。

1) 以美国为中心:

大骗子 (0.1.4)
phone_wrangler (0.1.3)
simple_phone_number (0.1.9)

2) 取决于 rails 或 active_record:

电话号码 (1.2.0)
validates_and_formats_phones (0.0.7)

3) 已合并回主干的“电话”分支:

elskwid 电话 (0.9.9.4)
tfe 电话 (0.9.9.1)

4) 依靠您提前了解该地区

假冒(0.1.0)

5) 几乎对我有用

电话 (0.9.9.3)

6) 宝石名称中不包含子字符串“电话”(编辑:我看到你尝试过这个)

假的(1.6.1)

这些分组可能有些不公平或过时,因此请随时发表评论。我必须承认,当时我对有多少人部分地重新发明了这个特殊的轮子感到有些沮丧。

【讨论】:

  • phone gem 对我来说看起来有点休眠 - 几个没有得到响应的拉取请求。我改用了这个 fork:github.com/g1smd/carrphone,因为我需要正确获取英国的电话号码。
  • 根据要探索的选项列表更新了此内容。
【解决方案2】:

我从未见过太多可靠的电话号码格式化程序,因为要正确处理它太难了。就在你认为你已经看到了一切的时候,一些其他的格式出现并破坏了它。

十位北美数字可能是最容易格式化的,您可以使用正则表达式,但一旦遇到扩展名,您就会遇到麻烦。不过,如果你愿意,你可以自己破解它:

def formatted_number(number)
  digits = number.gsub(/\D/, '').split(//)

  if (digits.length == 11 and digits[0] == '1')
    # Strip leading 1
    digits.shift
  end

  if (digits.length == 10)
    # Rejoin for latest Ruby, remove next line if old Ruby
    digits = digits.join
    '(%s) %s-%s' % [ digits[0,3], digits[3,3], digits[6,4] ]
  end
end

这只会将 11 位和 10 位数字转换为您想要的格式。

一些例子:

formatted_number("1 (703) 451-5115")
 # => "(703) 451-5115"
formatted_number("555-555-1212")
 # => "(555) 555-1212"

【讨论】:

  • 如果给出 4155551212 会发生什么?
  • 当然,您可以尝试一下并自己找出答案!只要存在 11 位或 10 位数字,非数字字符就会被忽略,格式相同。
  • 哦......非数字字符被忽略......我想我需要了解更多关于正则表达式以及你用它做了什么,这就是我遇到问题的原因......我是猜测 \D 是非数字?
  • \s 是空格,\S 是非空格,所以几个东西的大写版本是相反的。有关更多示例和帮助工具,请参阅 Rubular
  • 在我的 ruby​​ 1.9.3 中,我必须在 '(%s) %s-%s' % [ digits[0,3], digits[3,3], digits[6,4] ] 行之前插入 digits = digits.join
【解决方案3】:

我编写了这个正则表达式来匹配 NANPA 电话号码与 PHP 的一些约定(例如扩展)(感谢上帝,那些日子已经结束了),并在几个月前将其转换为 Rails 验证器用于一个项目。它对我很有用,但它比严格按照规范更实用。

# app/validators/phone_number_validator.rb
class PhoneNumberValidator < ActiveModel::EachValidator
  @@regex = %r{\A(?:1(?:[. -])?)?(?:\((?=\d{3}\)))?([2-9]\d{2})(?:(?<=\(\d{3})\))? ?(?:(?<=\d{3})[.-])?([2-9]\d{2})[. -]?(\d{4})(?: (?:ext|x)\.? ?(\d{1,5}))?\Z}

  def validate_each (object, attribute, value)
    if m = value.match(@@regex)
      # format the phone number consistently
      object.send("#{attribute}=", "(#{m[1]}) #{m[2]}-#{m[3]}")
    else
      object.errors[attribute] << (options[:message] || "is not an appropriately formatted phone number")
    end
  end
end

# app/models/foobar.rb
class Foobar < ActiveRecord::Base
  validates :phone, phone_number: true
end

保存/输出的格式如下:(888) 888-8888。目前输出剥离了扩展,因为我不需要它。您可以将其重新添加并轻松更改格式(请参阅object.send 行。

【讨论】:

    【解决方案4】:
    #RAILS_ROOT/lib/String.rb
    class String
      def convert_to_phone
        number = self.gsub(/\D/, '').split(//)
    
        #US 11-digit numbers
        number = number.drop(1) if (number.count == 11 && number[0] == 1)
    
        #US 10-digit numbers
        number.to_s if (number.count == 10)
    
      end
    
    
      def format_phone
        return "#{self[0,3]}-#{self[3,3]}-#{self[6,4]}"
      end
    end
    
    "585-343-2070".convert_to_phone 
    => "5853432070"
    
    "5853432070".convert_to_phone
    => "5853432070"
    
    "1(585)343-2070".convert_to_phone.format_phone
    => "585-343-2070"
    
    ##Everything formatted as requested in Asker's various comments
    

    【讨论】:

    • @kyle 我明白了,所以这将用于对数据库进行规范化......然后我将使用显示端的另一个响应(像 xxx-xxx-xxxx 一样显示它>
    • 虽然不是很干...我会在这里更新一些更好的东西
    • 我明白了..谢谢...有什么更好的方法...我在想它应该以同样的方式在数据库中,然后允许我格式化,我认为这行得通,让我玩一下,谢谢。
    • @Kyle -- 嗯,我试过了,我的控制器中出现错误,说找不到方法 'convert_to_phone' -- 我将再次重新启动服务器...我把它放入lib/ 文件夹....
    • 这是完整的错误:我尝试将其更改为要包含在模型中的模块,但仍然没有:未定义方法 `convert_to_phone' for "15104762000":String
    【解决方案5】:

    【讨论】:

      【解决方案6】:
      def format_phone_numbers(n)
          "(#{n[-10..-8]}) #{n[-7..-5]}-#{n[-4..-1]}"
      end
      
      format_phone_numbers('555555555555')
      

      “(555)555-5555”

      【讨论】:

        猜你喜欢
        • 2010-10-14
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        • 2015-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-06
        相关资源
        最近更新 更多