1

Using Ruby 2.1.0, Rails 4.0.2, MySQL, and OS X, I can't get the validator uniqueness: { case_insensitive: XXX } to work right.

Yes, I realize this is almost, or perhaps precisely, identical to Rails 3. Validating email uniqueness and case sensitive fails. But the answer stream over there goes down a "don't do that" fork, and at least for pedagogic reasons I'd like to actually answer this question. Out of respect for the line taken over there, I've started a new question. Sorry if that's abusive.

My difficulty is that case_sensitive: true and case_sensitive: false produce the same results, even when (AFAICT) they oughtn't.

models/user.rb extract:

class User < ActiveRecord::Base
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@akamai\.com\z/i
  validates :email, presence: true, uniqueness: { case_sensitive: false }, format: {
        with: VALID_EMAIL_REGEX,
        message: "Must be an Akamai email address."
  }
end

spec/models/user_spec.rb extract:

require 'spec_helper'
describe User do
  before { @user = User.new(email: "giuseppe@akamai.com") }
  subject { @user }
  it { should be_valid }
  context "email" do
    describe "is already taken (caserifically)" do
      before do
        user_with_same_email = @user.dup
        user_with_same_email.email = @user.email.upcase
        user_with_same_email.save
      end
      it { should_not be_valid }
    end
  end
end

As written, the test passes (user_with_same_email is not valid). Cool.

However, if I change the validation's false to true, the test still passes (user_with_same_email is still invalid, presumably colliding). Uncool.

I know that MySQL/OSX is case-insensitive as regards table names (due to the case-insensitive underlying file system), but this doesn't extend to value comparisons, does it?

Ooo, just noticed the (unanswered) Ruby on Rails Tutorial - Michael Hartl - Test “User when email address is already taken”. I believe these are exact duplicates.

Community
  • 1
  • 1
jackr
  • 1,407
  • 1
  • 14
  • 29

2 Answers2

1

I don't know about your specific database setup, but yes, I would say that is most likely the issue.

This is a quote from the Rails API guide for :uniqueness:

Note that some databases are configured to perform case-insensitive searches anyway.

http://edgeguides.rubyonrails.org/active_record_validations.html#uniqueness

As far as I can tell, there isn't an official patch for this. Best I can find are these old discussions:

Both mention various ways around it.

I'd say your best bet is running it against what your production environment will be like too. Seems it behaves differently on different platforms.

Michael Martin
  • 693
  • 5
  • 8
  • As I read those issues, (1) yes this seems to be my problem, (2) it seems to be an irreconcilable flip-flop, performance vs. case-checking, and (3) it's all about MySQL, not my OS per se (so I actually am testing in the production context). So I need to pursue one or the other of those work-arounds. – jackr Jan 10 '14 at 23:20
0

There is an issue with your VALID_EMAIL_REGEX, you must end it with /i to be case insensitive.

Arkan
  • 6,196
  • 3
  • 38
  • 54
  • 1
    Two things: first, is it my aging vision? I see a "/i" in VALID_EMAIL_REGEX. Maybe you meant /i somewhere else? Second, although I cut them out for this question I have test cases that confirm that the /i of VALID_EMAIL_REGEX is working properly (i.e., although the regex requires a literal substring "akamai.com", the program accepts AKAMAI.COM as well). – jackr Jan 10 '14 at 22:44