DRY在rails中编写许多自定义验证器的方法

时间:2012-11-19 09:45:28

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

在我的应用程序中,有多个自定义验证程序,我将其保留在app / validators中,然后调用多个模型。

大多数情况下,我会使用基于正则表达式的验证,例如电子邮件,手机等基本上自定义数据字符串,我需要采用特定格式。

例如:

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
      record.errors[attribute] << (options[:message] || "is not a valid email format")
    end
  end
end

class IpValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/
      record.errors[attribute] << (options[:message] || "is not a valid IP format")
    end
  end
end

这种方法的缺点是我有很多额外的文件,几乎相同的代码,在较大的应用程序中可能会很烦人。

是否有更好的方法(更多DRY)来定义基于正则表达式的验证,以便它们可以跨模型重复使用?

1 个答案:

答案 0 :(得分:2)

您可以为正则表达式验证创建基类:

class RegexValidator < ActiveModel::EachValidator
  def regex_validate_each(regex, err_msg, record, attribute, value)
    unless value =~ regex
      record.errors[attribute] << (options[:message] || err_msg)
    end
  end
end

然后将其子类化为:

class EmailValidator < RegexValidator
  def validate_each(record, attribute, value)
    regex_validate_each(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, "is not a valid IP format", record, attribute, value)
  end
end