Rails validations: unique within a certain scope

It’s a great idea to make your database and application validations match. If you have validates :name, presence: true in your model, you should pair it with a not null database constraint. Unique validations should be paired with a UNIQUE database ind…


This content originally appeared on DEV Community and was authored by matt swanson

It’s a great idea to make your database and application validations match. If you have validates :name, presence: true in your model, you should pair it with a not null database constraint. Unique validations should be paired with a UNIQUE database index.

In real-world applications, you often have more complicated validations, but you should continue this practice whenever you can.

Something I encounter regularly is the need to have records that are unique, but within a certain scope.

Imagine you were building a typical project management tool. You might want Projects to have a unique name so they can be distinguished within your UI – but you don’t want the name to be globally unique. If I make a project called “Onboarding”, another customer should not be restricted from using that name as well.

Luckily, Rails has got us covered with a handy feature called validation scopes.

Usage

The scope option to the Rails uniqueness validation rule allows us to specify additional columns to consider when checking for uniqueness.

class Project < ApplicationRecord
  belongs_to :account

  has_many :tasks

  validates :name, presence: true, uniqueness: { scope: :account_id }
end

This rule says that “the name of this project must unique, within the scope of this account”. In other words, the combination of a name and account_id must be unique – but you can have projects with the same name in different accounts.

As we discussed earlier, you really want to back-up your application level validations with database constraints.

In this case, you’ll want to do a multiple column index. You can do this in a normal Rails migration.

class CreateProject < ActiveRecord::Migration[6.0]
  def change
    create_table :projects do |t|
      ...
    end

    add_index :projects, [:name, :account_id], unique: true
  end
end

Options

You can pass multiple columns to scope.

If you were building a dining app and wanted to enforce that a guest could only have one reservation at a restaurant per day.

class Reservation < ApplicationRecord
  belongs_to :guest
  belongs_to :restaurant

  validates :guest_id, uniqueness: {
    scope: [:restaurant_id, :reservation_date]
  }
end

You may wish to change the message since the defaults error message will be fairly spartan: “{field} has already been taken”

validates :guest_id, uniqueness: {
  scope: [:restaurant_id, :reservation_date],
  message: "Only one reservation per guest per day is permitted"
}

Note: In PostgreSQL, the default limit for index names is 63 characters so you may find yourself needing to change the index name if your model or column names are longer.

add_index :reservations, [:guest_id, :restaurant_id, :reservation_date],
  unique: true,
  name: "idx_reserveration_guest_date_uniq"

Additional Resources

Rails API: Uniqueness Validations

PostgreSQL Docs: Postgres Constraints

MySql Docs: Multi-column Indexes


This content originally appeared on DEV Community and was authored by matt swanson


Print Share Comment Cite Upload Translate Updates
APA

matt swanson | Sciencx (2021-03-16T13:00:00+00:00) Rails validations: unique within a certain scope. Retrieved from https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/

MLA
" » Rails validations: unique within a certain scope." matt swanson | Sciencx - Tuesday March 16, 2021, https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/
HARVARD
matt swanson | Sciencx Tuesday March 16, 2021 » Rails validations: unique within a certain scope., viewed ,<https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/>
VANCOUVER
matt swanson | Sciencx - » Rails validations: unique within a certain scope. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/
CHICAGO
" » Rails validations: unique within a certain scope." matt swanson | Sciencx - Accessed . https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/
IEEE
" » Rails validations: unique within a certain scope." matt swanson | Sciencx [Online]. Available: https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/. [Accessed: ]
rf:citation
» Rails validations: unique within a certain scope | matt swanson | Sciencx | https://www.scien.cx/2021/03/16/rails-validations-unique-within-a-certain-scope/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.