【问题标题】:Rails 3. Validating email uniqueness and case sensitive failsRails 3. 验证电子邮件唯一性和区分大小写失败
【发布时间】:2011-09-19 07:34:44
【问题描述】:

我正在 Rails 3 中开发一个应用程序,在注册时我需要用户输入他们的电子邮件地址,并且我需要它是唯一的并且区分大小写。 IE。当数据库中已经存在 MyEmail@yahoo.com 时,应该没有人能够使用 myEmail@yahoo.com 进行注册。

这是我的代码,它使应用程序崩溃:

validates :email, :presence => true, :uniqueness => true, :case_sensitive => true,
                      :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}

这有什么问题?

【问题讨论】:

    标签: ruby-on-rails-3 validation


    【解决方案1】:

    请不要在此处使用区分大小写的方式!!!。它将获取所有用户!因此,如果您有 100.000 个用户。首先它会用LOWER(电子邮件)获取它们。这可能非常慢,并且不会使用您在电子邮件中的索引。

    这是我刚刚找到的一篇关于这个主题的文章:http://techblog.floorplanner.com/post/20528527222/case-insensitive-validates-uniqueness-of-slowness

    我的建议是:运行查询以使所有电子邮件小写,并在验证前过滤器以小写电子邮件属性,这样您就不会在该列中包含任何大写字符。

    User.update_all('email = LOWER(email)')
    

    过滤前:

    before_validation :downcase_email
    
    private
    
    def downcase_email
      self.email = email.downcase if email.present?
    end
    

    【讨论】:

    • 好主意!非常感谢,它不知道这一点,我可以看到它会导致的问题。
    • 这是一种旧方法。正如 Geoff Evason 所写,Rails 3 允许使用哈希验证 :email, :uniqueness => { :case_sensitive => false }。
    • 此答案中列出的帖子链接似乎已损坏,这是一个有效的链接:techblog.floorplanner.com/post/20528527222/…
    • 不确定这个问题在 Rails 4 中是否仍然存在,我很想知道是否有人有答案:)
    • 如果表中的条目较少怎么办?
    【解决方案2】:

    对于 Rails 3 类型的验证,您需要像这样嵌套不区分大小写的块

    validates :email, :uniqueness => { :case_sensitive => false }
    

    【讨论】:

    • 正如@Michael Koper 所指出的那样,这与不使用电子邮件索引是否具有相同的效果?
    • postgres 数据库允许在函数上建立索引,所以一般情况下不会。
    【解决方案3】:

    我没有对接受的答案发表评论的声誉,但@medBo 询问了它在 Rails 4 中的行为方式。作为参考,在使用 Rails 4.2 + MySQL 时,如果我指定

    validates :username, uniqueness: { case_sensitive: true }
    

    ActiveRecord 执行此查询:

    SELECT  1 AS one FROM `users` WHERE `users`.`username` = 'TEST_USER' LIMIT 1
    

    在这种情况下,搜索不区分大小写。但是当我设置时:

    validates :username, uniqueness: { case_sensitive: false }
    

    它执行:

    SELECT  1 AS one FROM `users` WHERE `users`.`username` = BINARY 'TEST_USER'
    

    BINARY 运算符ensures the search is case sensitive 没有获取所有用户,这意味着至少对于我的设置而言,case_sensitive 标志不会受到@Michael Koper 为早期版本指出的性能问题的影响导轨。我无法评论 ActiveRecord 对其他数据库设置的执行情况。

    【讨论】:

    • 如果我没记错的话,你的例子中的两种情况都是一样的。 validates :username, uniqueness: { case_sensitive: false }
    【解决方案4】:

    我不确定是否可以使用该语法进行不区分大小写的验证(至少,我还没有找到任何文档)。

    您应该能够像这样验证不区分大小写的唯一性:

    validates_uniqueness_of :email, :case_sensitive => false
    

    如果没有更多关于你得到的崩溃的详细信息,我无能为力。

    【讨论】:

      【解决方案5】:

      您可以在模型中使用回调,例如电子邮件属性上的“before_validation”,使其小写如下:

        before_validation { self.email = email.downcase }
      

      这将使电子邮件输入小写,然后尝试不区分大小写的唯一性验证:

      validates :email, uniqueness: true
      

      有关回调的更多信息:这里是 ruby​​ 指南 https://guides.rubyonrails.org/active_record_callbacks.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        相关资源
        最近更新 更多