003: Rails Sexy Validations Gotcha — Validating Uniqueness

Note It’s not very safe to only have the unique constraint in your code. It should be in your database to avoid a situation where two instances of the application write to the database with the same value at the same time.

WHAT

Rails 3 brought about sexy validations. These are ways to more intuitively define what is and is not valid for the attributes of your models. When trying to validate unique records, I was surprised to find that it was case sensitive (‘Case’ and ‘case’ are considered unique).

WHY

The new syntax supports lots of interesting things like

validates :name, :presence => true, :uniqueness => true

While using the fantastic shoulda gem from thoughtbot, I quickly found out that one cannot currently validate case-insensitivity the new way without writing a custom validation.

LESSON

For the attributes I need to be unique regardless of case, I’ve stuck with the older syntax.

validates_uniqueness_of :name, :case_sensitive => false

The new, lighter syntax is more fun and readable to use when it works for your needs. All functionality doesn’t yet appear to be there.

SUPPORTING EVIDENCE

Rails 3 API Docs

Shoulda Test

require 'test_helper'

class UserTest < ActiveSupport::TestCase
  context "user creation" do
    subject { Factory(:charles) }
    should validate_presence_of :name
    should validate_uniqueness_of(:name).case_insensitive
  end
end

Shoulda Result Without case_sensitive => false

Expected errors to include “has already been taken” when name is set to “cHARLES”, got no errors.Expected block to return true value.


Published Sep 17, 2010