Jackson Cunningham
Jackson Cunningham

Reputation: 5073

validate_presence_of *before* before_validation

Let's say I have a before_validation that checks to make sure the first letter of a name is "y":

before_validation :check_name_first_letter_is_y

But I want to make sure that the first name is also present:

validates :name, presence: true

But this will run the before_validation BEFORE validating if there's a first name present, right? How would I check if a name is present before running my before_validate?

I could try:

after_validation :check_name_first_letter_is_y

But will that stop the save method if I return false? Or is it too late because it's already been validated?

Upvotes: 0

Views: 447

Answers (2)

BroiSatse
BroiSatse

Reputation: 44685

You can simply add a second format validation:

validates :name, presence: true, format: { with: /^y/, allow_blank: true }

Upvotes: 1

vee
vee

Reputation: 38645

It might be easier to do this in one call as follows (if I didn't misread your question!):

validates :name, presence: ->(rec) { rec.name.initial == 'Y' }

Update:

Introduce a new ActiveModel::EachValidator that checks the first character in the name to be y and use the presence validator as you normally would, but ensure presence validator comes before the name validator so that presence check is done before checking first letter.

# app/validators/NameValidator.rb

class NameValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if value.initial != 'y'
      record.errors[attribute] << (options[:message] || "First letter in name must be `y`")
    end
  end
end

Then in your model, use the following two validations:

validates :name, presence: true
valdiates :name, name: true

Please refer: http://api.rubyonrails.org/classes/ActiveModel/Validator.html.

Also would suggest you to come up with a "Railsy" name for NameValidator class!

Upvotes: 1

Related Questions