Magicmarkker
Magicmarkker

Reputation: 1063

Custom validation for two fields with same validation but slightly different

Here is the scope that causes code smell:

validates :email, uniqueness: { scope: :client_id }, if: Proc.new {|u| u.active? and !u.email.blank? }
validates :companyemail, uniqueness: { scope: :client_id }, if: Proc.new {|u| u.active? and !u.companyemail.blank? }

Here's what I've tried, but it causes my tests to fail saying the email fields have already been taken:

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors[attribute] << 'has already been taken' if record.active? and !attribute.blank?
  end
end

validates :email, :companyemail, uniqueness: { scope: :client_id }, email: true

Upvotes: 0

Views: 84

Answers (2)

Ian Kenney
Ian Kenney

Reputation: 6446

It looks when I read your code that this validator should fail every time the record is active and the email address is present.

Did you look at using the allow_blank: true option? http://edgeguides.rubyonrails.org/active_record_validations.html#:allow_blank

maybe something like:

validates :email,: companyemail uniqueness: { scope: :client_id },  if: "record.active?", allow_blank: true

Upvotes: 0

vee
vee

Reputation: 38645

You could group the two lines using with_options:

Example:

with_options uniqueness: { scope: :client_id }, if: Proc.new { |u| u.active? && u.email } do 
  validates :email
  validates :companyemail
end

Upvotes: 1

Related Questions