0

I want to interrupt the default registration action in my rails application, changing email validation. All I need is to have email field unique ONLY if that user is already registered AND has role 'X'.

I've tried the following but my application returns "Email has already been taken" message:

validation:

validates_uniqueness_of :email, {allow_blank: true, if: :already_exists_as_x?}

def already_exists_as_x?
  User.where(email: self.email, role: :X).exists?
end

(I will be glad for any help)

  • By removing it you might end up having two users with the same email address with different roles, which is not a good idea... – jedi Feb 04 '19 at 09:08

2 Answers2

1

Assuming your model includes :validatable module of Devise, you can remove this module from your model and write your own validations as you desire.

In your model (say user.rb) your devise call contains :validatable like:

devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :validatable, :confirmable, :trackable

Remove or comment :validatable from this call, then your own validations should work as you expected.

F.E.A
  • 289
  • 1
  • 12
  • Thank You for reply . I've removed :validatable, then do validation like this: validates :email, {unique: true, if: :already_exists_as_vg? , on: :create} What's wrong with this code? – Shushanik Kostumyan Feb 04 '19 at 08:25
  • it looks right, you may try to overwrite Devise's validation methods as another way. see: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb – F.E.A Feb 04 '19 at 11:57
  • 1
    Thank You a lot. I found another way to implement the whole logic. Btw what you told was properly solving my problem. – Shushanik Kostumyan Feb 04 '19 at 12:02
0

If you are using Rails 5, you need to override the below method in your User model

  def will_save_change_to_email?
    if User.where(email: self.email, role: :X).exists?
      return true
    else
      return false
    end
  end

when you return true, devise will go ahead and apply the uniqueness check and when you return false devise will not check for uniqueness

You will also need to remove the unique index as by passing devise validation alone will not let you save the user

  def change
    remove_index :users, :name => :index_users_on_email
  end

Note: once you remove the index and create records with duplicate email ids, you will not be able to add the unique index back again at a later moment as creating unique index will fail

opensource-developer
  • 1,990
  • 1
  • 20
  • 57