Skip to content

How To: Scope email validation

Samet Gunaydin edited this page Aug 21, 2021 · 3 revisions

This feature is not merged.

By default, Devise's validatable module validates the uniqueness of the email attribute in the User model.

But, sometimes, it's useful to scope the email uniqueness validation into some context. Using subdomains or some soft-deletion approach are good examples of these cases.

The email_scope option

Devise now comes with an option to define an array of scopes for email validation.

Let's suppose your User model belongs to an Account and you want to allow the same email into multiple Accounts. You just need to add the email_scope option to your devise.rb file like this:

Devise.setup do |config|
  # Option to scope the email uniqueness validator. Default is nil;
  config.email_scope = [:account_id]
end

By doing this, the validatable module will scope the :email uniqueness validation to the defined keys.

Additional work

Unfortunately, using this option has some caveats and additional work is needed to make the scope work as desired and without affecting some other functionalities of Devise.

Updating the unique index

Devise adds a database unique index to the email attribute. Even if you add the email_scope option, this index will continue to exist, so you need to manually remove it. It's also important to add another unique index scoped to our needs.

class ChangesUniqueIndexOfUsers < ActiveRecord::Migration
  def up
    remove_index :users, :email
    add_index :users, [:email, :account_id], unique: true
  end

  def down
    add_index :users, :email, unique: true
    remove_index :users, [:email, :account_id]
  end
end

Recoverable module incompatibility

By adding a scope to the email key, you may end up with multiple users with the same email address. This will cause the “recoverable” module not to work well, as it will only include a link in the password reset e-mail to the first account for which it finds a matching e-mail. Here is a thread on the Google Group about how to implement adding all the user information into the password reset email.

Clone this wiki locally