0

I have an email ActiveRecord (sub-class, different PG DB) with the following validation:

class Email < DbRecord
  belongs_to :user

  attr_accessor :skip_validation
  alias_method :skip_validation?, :skip_validation

  validates :value,
            presence: true,
            uniqueness: true,
            format: {
              with: URI::MailTo::EMAIL_REGEXP,
              message: "is an invalid email address",
              allow_blank: true,
            },
            unless: :skip_validation?

  before_validation { |record| record.value = record.value&.downcase }

skip_validation is nil. There are no other instance methods.

When there's no user_id the validation works as expected.

> e = Email.new(value: "foo@bar")
=> #<Email id: nil, user_id: nil, value: "foo@bar">

> e.valid?
=> false

When there's a user_id the bogus email doesn't trigger the validation.

> e = Email.new(user_id: 7, value: "foo@bar")
=> #<Email id: nil, user_id: 7, value: "foo@bar">

> e.valid?
=> true

Note that setting validate: true on belongs_to doesn't help:

class Email < DbRecord
  belongs_to :user, validate: true

Still presents:

> e = Email.new(user_id: 7, value: "foo@bar")
=> #<Email id: nil, user_id: 7, value: "foo@bar">

> e.valid?
=> true

Why is that? What else should I be looking at/for?

Dave Newton
  • 158,873
  • 26
  • 254
  • 302

1 Answers1

1

Two-step answer:

  1. "foo@bar" is a valid email according to URI::MailTo::EMAIL_REGEXP...

I can't even, but others have hit the same issue so...

As I always tell everyone else: check your assumptions. I assumed the validation was failing because of the email address, and in my sleep-deprived state I didn't verify the errors.

So why was it failing validation?

  1. Rails 5 changed belongs_to to make the related ID mandatory, so in order for this to make sense (in my use-case) I also needed to add:
  belongs_to :user, optional: true

to get the expected error messages back during validation.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302