0

I want to validate that username is not one of the following. ["admin", "moderator", "mod", "administrator"].

I do validate that these names are not allowed at the model level using custom validator.

class User < ActiveRecord::Base
  ...
  validate :username_should_not_be

  def username_should_not_be
    not_allowed = ["admin", "moderator", "mod", "administrator"]
    if not_allowed.include?(username.downcase)
      error.add(:username, "is not allowed.")
    end
  end
  ...
end

I'd like to know if I can validate this at database level as well (maybe using migration file?). Can this be done for the particular case above?

This practise seems to be encouraged by Rails guide as well

it may be a good idea to use some constraints at the database level. Additionally, database-level validations can safely handle some things (such as uniqueness in heavily-used tables) that can be difficult to implement otherwise.

Jason Kim
  • 18,102
  • 13
  • 66
  • 105

1 Answers1

0

You can do it with mv-postgresql gem for PostgreSQL and mv-sqlite gem for SQLite. Both gems are the parts of Migration Validator project ( see details here: https://github.com/vprokopchuk256/mv-core.

With that gem you can define validation on db level. In your case:

def up
  validates :users, :username, 
             exclusion: ["admin", "moderator", "mod", "administrator"]
end

def down
   validates :users, :username, exclusion: false
end

And then you ( preferably ) propagate that validation to your model:

class User < ActiveRecord::Base
  enforce_migration_validations
end

As result:

User.new(username: 'admin').valid?
=> false

User.new(username:  'jasoki').valid?
=> true