简化格式化电话号码的代码

时间:2013-03-05 00:33:39

标签: ruby-on-rails ruby ruby-on-rails-3

我想要完成的是取一个字符串,并解析它只是数字。然后在显示它时,我将使用number_to_phone,它们都将是相同的。

到目前为止,我已经在我的模型中定义了这个:

  def parse_phone_nums
    self.main_phone = self.main_phone.gsub(/[.\-()\W]/, '') if self.main_phone
    self.alt_phone = self.alt_phone.gsub(/[.\-()\W]/, '') if self.alt_phone
    self.main_phone = "925" + self.main_phone if self.main_phone.length == 7
    self.alt_phone = "925" + self.alt_phone if self.alt_phone.length == 7
  end

在我的控制器中调用创建和更新操作。我觉得好像这里有很多重复,并且想知道如何将代码减少为尽可能干。

2 个答案:

答案 0 :(得分:2)

许多可能的解决方案,大致如下:

def clean_up_phone(num)
  return unless num
  num = num.gsub(/[.\-()\W]/, '')
  num.length == 7 ? "925#{num}" : num
end

有多种方法可以使用此方法,包括自动设置,回调期间等等。

我不确定正则表达式是你真正想要的,人们为电话号码输入了很多东西。您可能希望在验证之前稍微处理它,并在此之后添加区号。

答案 1 :(得分:0)

我会选择这样的东西,因为它允许将来扩展(另一个区号?检测用户提交的区号等),并且很容易测试。

由于很容易忘记用户可能使用的角色的匹配器,我会使用不同的方法从给定的String中提取数字。

def parse_phone_nums
  self.main_phone = parse_phone_number(self.main_phone) if self.main_phone
  self.alt_phone  = parse_phone_number(self.alt_phone)  if self.alt_phone
end

private

def parse_phone_number(string)
  number = extract_number(string)
  prefix_area_code(number)
end

def extract_number(string)
  characters = string.split("")
  characters.reduce("") { |memo, char| "#{memo}#{char}" if numeric?(char) }
end

def prefix_area_code(number)
  prefix = number.length == 7 ? "925" : ""
  "#{prefix}#{number}"
end

def numeric?(string)
  Float(string) != nil rescue false
end

理想情况下,我会将所有这些private方法提取到一个自己的类中,假设是一个PhoneNumberParser。

如果您认为def_phone_nums不够干净,或者您有更多电话号码,这应该有效:

def parse_phone_nums
  phones = %w[main alt]
  phones.each do |phone|
    current = self.send("#{phone}_phone")
    next unless current

    parsed = parse_phone_number(current)
    self.send("#{phone}_phone=", parsed)
  end
end