Senjai
Senjai

Reputation: 1816

Ruby on Rails: Why do I include allow_blank in my validation if I test for presence already?

I'm learning rails with the book Agile Web development with Rails 4e. It uses the following so far as our product model (adapted from a scaffold):

class Product < ActiveRecord::Base
  attr_accessible :description, :image_url, :price, :title

  validates :description, :title, :image_url, presence: true
  validates :price, numericality: {greater_than_or_equal_to: 0.01}
  validates :title, uniqueness: true
  validates :image_url, allow_blank: true, format: {
    with: %r{\.(gif|jpg|png)$}i,
    message: 'Must be a valid URL for a gif, png, or jpg..'
  }
end

I'm wondering why it tests first for the presence of :image_url, but then in the tertiary validation to make sure the image url is valid, it allows for blank responses which contradicts the first validation. I don't understand why this is supposed to work as is.

As an additional question, if the image_url is empty, how can I test if it is empty in my code? (e.g. in the product view to display a default image.)

Upvotes: 0

Views: 605

Answers (3)

Ross Curzon-Butler
Ross Curzon-Butler

Reputation: 1

I'm new to Rails as well and am using the same book. My understanding is that in order to stop the validation returning two errors immediately against validation (i.e. one if the field is blank and one if it doesn't have a correct file extension) it must allow_blank for the file format.

The best way I can explain it is to suggest removing the allow_blank: true code and trying to submit the description form again.

You should then see that you get both the validation errors for the field being blank and the file format being wrong.

The allow_blank therefore tells the validation to only error on the file format once the field is no longer blank.

Confused me as well which is why I ended up here!

Upvotes: 0

dliggat
dliggat

Reputation: 458

Model validations are tested in isolation. A model is valid if and only if it passes validation for each validates statement independently.

It's probably bad-form, and evidently confusing for that allow_blank: true to be in the 4th validation, but that only applies to that single statement. The model must pass all validations to be considered valid, so the 1st statement merely imposes a tighter restriction than the 4th.

A final point, note that presence tests for non-nilness, whereas blank is defined as nil or the empty string. It is therefore possible to be both present and blank; e.g. image_url = ''. However, it remains the case that validations are tested separately in isolation.

Upvotes: 2

Brad Johnson
Brad Johnson

Reputation: 151

I think maybe you are confused about the validation code? I'm a noob, and this is probably not entirely accurate: the validates keyword doesn't test for presence, it starts a block that you use to specify your validations.

As is, your code will validate the :image_url according to your specifications if it exists. If you took out allow_blank: true, then a nonexistent or blank :image_url would fail the validations.

Upvotes: 0

Related Questions