Bhav Bhav - 2 months ago 12
Ruby Question

Validate unique field in Rails app

In my Rails app, I've got two models -

User
and
Account
.

A
User
can have many
Accounts
.

An
Account
includes a
name
field as shown in the schema below.

How can I validate that the
name
field is unique for an
Account
but not necessarily unique in the database? For example,
User1
could have an
Account
with the name
Cash
and
User2
could have a different
Account
but with the same name
Cash
.

user.rb:

class User < ActiveRecord::Base
has_many :accounts

before_save { self.email = email.downcase }

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

validates :email, presence: true,
length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }

has_secure_password

validates :password, presence: true, length: { minimum: 6 }

# Returns the hash digest of the given string.
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
end


account.rb:

class Account < ActiveRecord::Base
belongs_to :user
has_many :balances

before_save { self.active = true }

validates :name, presence: true, length: { maximum: 250 },
uniqueness: { case_sensitive: false }

validates :user, presence: true
end


schema.rb:

....
create_table "accounts", force: :cascade do |t|
t.string "name"
t.boolean "credit"
t.boolean "active", default: true, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end

create_table "balances", force: :cascade do |t|
t.decimal "balance"
t.date "date"
t.integer "account_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "users", force: :cascade do |t|
t.string "email"
t.boolean "admin"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
end

add_index "users", ["email"], name: "index_users_on_email", unique: true
....

Answer

You can use scope:

in your account.rb

validates :name, uniqueness: { scope: :user_id}

four you actual validates:

  validates :name, presence: true, length: { maximum: 250 },
                  uniqueness: { case_sensitive: false, scope: :use_id }

active record validates