【问题标题】:Rails 4 Validating email uniqueness without case_sensitiveRails 4 验证电子邮件唯一性而不区分大小写
【发布时间】:2026-01-20 09:10:02
【问题描述】:

使用 Ruby 2.1.0、Rails 4.0.2、MySQL 和 OS X,我无法让验证器 uniqueness: { case_insensitive: XXX } 正常工作。

是的,我意识到这与Rails 3. Validating email uniqueness and case sensitive fails 几乎或可能完全一样。但是那边的答案流是“不要那样做”的叉子,至少出于教学原因,我想真正回答这个问题。出于对那里接管的线路的尊重,我开始了一个新问题。对不起,如果这是辱骂。

我的困难在于 case_sensitive: truecase_sensitive: false 产生相同的结果,即使 (AFAICT) 他们不应该这样做。

models/user.rb 摘录:

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 摘录:

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

正如所写,测试通过(user_with_same_email 无效)。很酷。

但是,如果我将验证的 false 更改为 true,测试仍然通过(user_with_same_email 仍然无效,可能会发生冲突)。不酷。

我知道 MySQL/OSX 在表名方面不区分大小写(由于不区分大小写的底层文件系统),但这并没有扩展到值比较,是吗?

哦,刚刚注意到(未答复的)Ruby on Rails Tutorial - Michael Hartl - Test “User when email address is already taken”。我相信这些是完全重复的。

【问题讨论】:

    标签: mysql ruby-on-rails macos validation ruby-on-rails-4


    【解决方案1】:

    我不知道您具体的数据库设置,但是,我认为这很可能是问题所在。

    这是来自 Rails API 指南的引用:独特性:

    请注意,某些数据库已配置为执行不区分大小写的搜索。

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

    据我所知,目前还没有官方补丁。我能找到的最好的就是这些旧的讨论:

    两者都提到了各种解决方法。

    我会说你最好的选择是在你的生产环境中运行它。似乎它在不同平台上的行为不同。

    【讨论】:

    • 当我阅读这些问题时,(1)是的,这似乎是我的问题,(2)这似乎是一个不可调和的触发器,性能与大小写检查,以及(3)它是所有关于 MySQL,而不是我的操作系统本身(所以我实际上是在生产环境中测试)。所以我需要寻求其中一种或另一种解决方法。
    【解决方案2】:

    您的 VALID_EMAIL_REGEX 存在问题,您必须以 /i 结尾以不区分大小写。

    【讨论】:

    • 两件事:第一,是我的视力老化吗?我在 VALID_EMAIL_REGEX 中看到一个“/i”。也许你的意思是 /i 别的地方?其次,虽然我为这个问题剪掉了它们,但我有测试用例确认 VALID_EMAIL_REGEX 的 /i 工作正常(即,虽然正则表达式需要文字子字符串“akamai.com”,但程序也接受 AKAMAI.COM) .