Search code examples
mysqlruby-on-railsruby-on-rails-4activerecordrails-migrations

Rails 4.2 Ensuring uniqueness across two columns in DB as well as on instance


I am learning Rails right now as we transition a product to it. I have a problem -- and a definite lack of core skills with ruby -- that I am wondering how to address. Not only would I like an answer, I would welcome opinions on whether or not there is a better way to achieve this.

Associations:

We have a Client class which has_many :users. The User belongs_to the Client.

In addition to the :client_id column we also have a :email column that should be unique within the scope of the :client_id

Validations:

I have seen that I could do something like this to ensure that on the instance level by adding this check to the User model.

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

but as far as my understanding goes, this does nothing to ensure uniqueness in the schema. Keep in mind I am trying to avoid manually altering the schema with SQL, I would like to do this with migrations if possible. In other uniqueness checks(for non scoped uniqueness), to ensure the uniqueness of something I would do something like this in the migration:

add_index :users, :email, unique: true

but that doesn't really do what I want, I don't think.

Tips, tricks, comments, suggestions, and answers welcome!

Edit: MySQL example:

CREATE TABLE IF NOT EXISTS users (
email VARCHAR(200),
client_id INTEGER,
UNIQUE INDEX (email, client_id)
)

Solution

  • You can use an array as the second argument to add_index in your migration:

    add_index "users", ["client_id", "email"], :unique => true
    

    This should produce:

    CREATE UNIQUE INDEX users_client_id_email ON users(client_id, email)
    

    http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index