Rails“validates_uniqueness_of”区分大小写
Posted
技术标签:
【中文标题】Rails“validates_uniqueness_of”区分大小写【英文标题】:Rails "validates_uniqueness_of" Case Sensitivity 【发布时间】:2010-10-15 23:53:14 【问题描述】:这是模型(我使用的是 SQLLite3):
class School < ActiveRecord::Base
validates_uniqueness_of :name
end
例如,在我添加“耶鲁”之后,我无法添加“耶鲁”,但可以添加“耶鲁”。如何使验证不区分大小写?
编辑:找到了 - Active Record Validations
【问题讨论】:
【参考方案1】:validates_uniqueness_of :name, :case_sensitive => false
可以解决问题,但您应该记住,如果您有多个服务器/服务器进程(例如运行 Phusion Passenger、多个 Mongrel 等),validates_uniqueness_of
确实不保证唯一性或多线程服务器。那是因为你可能会得到这个事件序列(顺序很重要):
-
进程 A 收到创建名为“foo”的新用户的请求
进程 B 做同样的事情
进程 A 通过询问数据库该名称是否存在并且数据库说该名称尚不存在来验证“foo”的唯一性。
进程 B 执行相同的操作并获得相同的响应
进程A为新记录提交
insert
语句并成功
如果您有一个要求该字段唯一性的数据库约束,进程 B 将提交新记录的 insert
语句,并且 失败 并带有一个从 SQL 适配器返回的丑陋的服务器异常。如果您没有数据库约束,则插入将成功,并且您现在有两行以 'foo' 作为名称。
另请参阅validates_uniqueness_of
Rails 文档中的“并发性和完整性”。
来自Ruby on Rails 3rd Edition:
...尽管它的名字, validates_uniqueness_of 并不能真正保证列值是唯一的。它所能做的就是验证没有列与执行验证时正在验证的记录中的值相同。有可能同时创建两条记录,每条记录都有相同的值作为应该唯一的列,并且两条记录都通过验证。强制唯一性最可靠的方法是使用数据库级别的约束。”
另请参阅 this programmer's experience 和 validates_uniqueness_of
。
这种情况通常发生的一种情况是在创建新帐户时从网页意外重复提交。这是一个很难解决的问题,因为用户将得到的是第二个(丑陋的)错误,这会让他们认为他们的注册失败,而实际上它成功了。我发现防止这种情况的最好方法就是使用 javascript 来防止重复提交。
【讨论】:
请注意——这是我提交给 Rails 的一个补丁,试图通过使用 db 级别的约束来解决这个问题:rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/… 另外,还有常年出现的“用户双击提交按钮”问题,但这更多的是使用 :disable_with【参考方案2】:在 Rails 3 中,您可以在模型中执行此操作:
validates :name, :uniqueness => true
或不区分大小写
validates :name, :uniqueness => :case_sensitive => false
【讨论】:
这正是我想要的。 我做 Rails 已经 10 多年了。我不敢相信我只是在学习这个选项。在 Rails 中总有新的东西要学……无论一个人的技能水平如何。【参考方案3】:有一个选项可以指定不区分大小写
validates_uniqueness_of :name, :case_sensitive => false
【讨论】:
【参考方案4】:有一个类似的问题,但答案更有趣:https://***.com/a/6422771
基本上,使用:case_sensitive => false
执行的数据库查询效率非常低。
【讨论】:
这可能曾经是真的,但现在(至少在 rails 6,如果不是更早的话)它执行了一个非常有效的 EXISTS 查询。验证期间的查询将无法利用name
上的常规索引,但为了保证并发性,无论如何,lower(name)
上应该有一个唯一索引,并且查询确实可以使用它.以上是关于Rails“validates_uniqueness_of”区分大小写的主要内容,如果未能解决你的问题,请参考以下文章
markdown [rails:devise] Ruby on Rails的身份验证gem。 #ruby #rails
Rails:如何在 Rails 中为 Devise 设置密钥?