craig
craig

Reputation: 26262

ActiveRecord validate url if it is present

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?

Upvotes: 5

Views: 13178

Answers (3)

Jordan Brough
Jordan Brough

Reputation: 7195

It sounds like you really only need a single validation:

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

this will cover both the url being present and it being a url.

You might want to improve the error message with something like:

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

If you feel like you need separate error messages for blank vs invalid values then you can follow Barry's suggestion:

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

Upvotes: 0

Yanis Vieilly
Yanis Vieilly

Reputation: 857

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?'

Upvotes: 22

Barry
Barry

Reputation: 755

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

Upvotes: 5

Related Questions