如果存在,ActiveRecord验证URL。

5
我希望确保我的类的url属性有一个值,如果有,它是有效的:
class Entity < ActiveRecord::Base

  validates :name, presence: true
  validates :url, presence: true, :format => {:with => URI.regexp}

end

在Rails控制台中:

> e = Entity.new(name: 'foo')
=> #<Entity id: nil, name: "foo", url: nil, created_at: nil, updated_at: nil> 

这会导致url属性出现两个错误:
> e.valid?
=> false

> e.errors
=> #<ActiveModel::Errors:0x007fed9e324e28 @base=#<Entity id: nil, name: "foo", url: nil, created_at: nil, updated_at: nil>, @messages={:url=>["can't be blank", "is invalid"]}> 

理想情况下,一个空的URL应该只会产生一个错误(即“不能为空”)。因此,我已经修改了验证规则:
validates :url, presence: true, :with => Proc.new { URI.regexp if :url? }

然而,我无法使语法正常工作。我缺少什么?


当你像这样给出 present? 时,它是否有效?validates :url, presence: true, :with => Proc.new { URI.regexp if :url.present? } - Pavan
我使用那种语法时出现了“不是符号”的错误。 - craig
也许你可以将其拆分为两个部分:validates :url, presence: truevalidates_format_of :url, with:=> URI.regexp, if: "url.present?" - Pavan
3个回答

21

将您的两个验证器分开。

validates :url, presence: true
validates :url, format: { with: URI.regexp }, if: Proc.new { |a| a.url.present? }

(将近)两周年纪念版编辑

正如vrybas和Barry所说,Proc是不必要的。您可以像这样编写验证程序:

validates :url, presence: true
validates :url, format: { with: URI.regexp }, if: 'url.present?'

有没有办法将无效 URL 导致的错误添加到对象的 errors[] 数组中?目前,entity.url = 'foo bar' 会引发一个错误 (URI::InvalidURIError: bad URI(is not URI?): foo foo),而不是将其添加到集合中。 - craig
1
不使用 Procvalidates :url, format: { with: URI.regexp }, if: 'url.present?' - vrybas
URI.regexp 不是一个好的 URL 验证工具。请考虑到像 a://extra text http://google.com extra text 这样的测试用例也能通过此验证。 - XanderStrike
没有使用proc的情况下:if: :url - Alexander Popov

5
根据 Yanis 的回答,将验证器分开,但您不需要使用 Proc。
您可以使用 常见验证选项 来绕过格式验证,如果值为 nil,则通过设置 allow_nil 参数来实现此目的。
或者,如果该值为空字符串 '',则设置 allow_blank 参数也可以运行,这可能更有用,尤其是在从表单输入设置 url 时。
完整的验证器可能如下所示:
validates :url, presence: true
validates :url, format: { with: URI.regexp }, allow_blank: true

0

听起来你只需要一个验证:

validates :url, format: { with: URI.regexp }

这将涵盖url存在和它是一个url的情况。

您可能希望使用类似以下内容来改进错误消息:

validates :url, format: { with: URI.regexp, message: 'must be a url' }

如果您觉得需要针对空值和无效值分别提供错误消息,则可以按照巴里的建议进行:

validates :url, presence: true
validates :url, format: { with: URI.regexp }, allow_blank: true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接