ActiveRecord validate url if it is present
Solution 1
Separate your two validators.
validates :url, presence: true
validates :url, format: { with: URI.regexp }, if: Proc.new { |a| a.url.present? }
(almost) 2 year anniversary edit
As vrybas and Barry state, the Proc is unnecessary. You can write your validators like this:
validates :url, presence: true
validates :url, format: { with: URI.regexp }, if: 'url.present?'
Solution 2
Separate the validators as in Yanis's answer, but you don't need a Proc for this.
You can use the common validation options to bypass the format
validation if the value is nil
by setting the allow_nil
parameter.
Alternatively, setting the allow_blank
parameter would also work if the value is the empty string ''
, which may be more useful if you're setting url
from an form input.
The complete validator could look like this:
validates :url, presence: true
validates :url, format: { with: URI.regexp }, allow_blank: true
craig
Certified, Epic-Clarity consultant. Open-source projects: PsCrystal - PowerShell wrapper of the Crystal Reports SDK PsEnterprise - PowerShell wrapper of BusinessObjects Enterprise SDK AppleScript email merge - Email merge using Outlook or Mail/Address Book source-highlight-crystal - GNU source-highlight language for Crystal Reports' formula language crystal-reports-tmbundle - A TextMate bundle for the Crystal Report's forumula language
Updated on June 22, 2022Comments
-
craig almost 2 years
I would like to ensure that my class's
url
property has a value and if it does, it is valid:class Entity < ActiveRecord::Base validates :name, presence: true validates :url, presence: true, :format => {:with => URI.regexp} end
In the rails console:
> e = Entity.new(name: 'foo') => #<Entity id: nil, name: "foo", url: nil, created_at: nil, updated_at: nil>
Which results in two errors for the
url
attribute:> 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"]}>
Ideally, a
nil
url
would produce a single error (i.e.can't be blank
).As such, I've change the
validates
rule:validates :url, presence: true, :with => Proc.new { URI.regexp if :url? }
I can't get the syntax to work, however. What am I missing?
-
craig almost 10 yearsIs there a way to add the error that results from an invalid URL to the objects
errors[]
array? Currently,entity.url = 'foo bar'
raises an error (URI::InvalidURIError: bad URI(is not URI?): foo foo
, rather than adding it to the collection. -
vrybas about 8 yearsWithout using
Proc
:validates :url, format: { with: URI.regexp }, if: 'url.present?'
-
XanderStrike over 7 years
URI.regexp
is not a good validation of URLs. Consider that test cases likea://
andextra text http://google.com extra text
pass this validation. -
Alexander Popov almost 4 yearsAlso without a proc:
if: :url