LikeMaBell
LikeMaBell

Reputation: 1609

Rails 3 Validation :presence => false

Here's what I expected to be a perfectly straightforward question, but I can't find a definitive answer in the Guides or elsewhere.

I have two attributes on an ActiveRecord. I want exactly one to be present and the other to be nil or a blank string.

How do I do the equivalent of :presence => false? I want to make sure the value is nil.

validates :first_attribute, :presence => true, :if => "second_attribute.blank?"
validates :second_attribute, :presence => true, :if => "first_attribute.blank?"
# The two lines below fail because 'false' is an invalid option
validates :first_attribute, :presence => false, :if => "!second_attribute.blank?"
validates :second_attribute, :presence => false, :if => "!first_attribute.blank?"

Or perhaps there's a more elegant way to do this...

I'm running Rails 3.0.9

Upvotes: 20

Views: 15402

Answers (5)

Kris
Kris

Reputation: 19938

class NoPresenceValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)                                   
    record.errors[attribute] << (options[:message] || 'must be blank') unless record.send(attribute).blank?
  end                                                                           
end    

validates :first_attribute, :presence => true, :if => "second_attribute.blank?"
validates :second_attribute, :presence => true, :if => "first_attribute.blank?"

validates :first_attribute, :no_presence => true, :if => "!second_attribute.blank?"
validates :second_attribute, :no_presence => true, :if => "!first_attribute.blank?"

Upvotes: 9

Rafaiel
Rafaiel

Reputation: 302

use custom validation.

validate :validate_method

# validate if which one required other should be blank
def validate_method
  errors.add(:field, :blank) if condition
end

Upvotes: 4

La-comadreja
La-comadreja

Reputation: 5755

For allowing an object to be valid if and only if a specific attribute is nil, you can use "inclusion" rather than creating your own method.

validates :name, inclusion: { in: [nil] }

This is for Rails 3. The Rails 4 solution is much more elegant:

validates :name, absence: true

Upvotes: 44

LikeMaBell
LikeMaBell

Reputation: 1609

It looks like :length => { :is => 0 } works for what I need.

validates :first_attribute, :length => {:is => 0 }, :unless => "second_attribute.blank?"

Upvotes: 1

Vik
Vik

Reputation: 5961

Try:

validates :first_attribute, :presence => {:if => second_attribute.blank?}
validates :second_attribute, :presence => {:if => (first_attribute.blank? && second_attribute.blank? )}

Hope that help .

Upvotes: 0

Related Questions