Answers:
validates_uniqueness_of :name, :case_sensitive => false
可以解决问题,但请记住,如果您有多个服务器/服务器进程(例如,运行Phusion Passenger,多个Mongrels等)或多线程服务器,validates_uniqueness_of
则不能保证唯一性。那是因为您可能会得到以下事件序列(顺序很重要):
insert
新记录的语句并成功insert
新记录的语句,并因SQL适配器返回的丑陋服务器异常而失败。如果您没有数据库约束,则插入将成功,并且您现在有两行以'foo'作为名称。另请参见validates_uniqueness_of
Rails文档中的“并发性和完整性” 。
...尽管其名称有效,validates_uniqueness_of并不能真正保证列的值是唯一的。它所能做的就是验证在执行验证时没有列的值与要验证的记录中的值相同。可以同时创建两个记录,每个记录具有相同的唯一列值,并且两个记录都可以通过验证。强制执行唯一性的最可靠方法是在数据库级别进行约束。”
又见这个程序员的经验与validates_uniqueness_of
。
这种情况通常发生的一种方式是在创建新帐户时从网页意外两次提交。这是一个很难解决的问题,因为用户会得到的是第二个(丑陋的)错误,这会使他们认为注册失败,而实际上却是成功。我发现防止这种情况的最好方法就是使用javascript尝试防止重复提交。
在rails 3中,您可以在模型中执行以下操作:
validates :name, :uniqueness => true
或不区分大小写
validates :name, :uniqueness => {:case_sensitive => false}
有一个类似的问题,但答案更有趣:https : //stackoverflow.com/a/6422771
基本上,使用:case_sensitive => false
执行效率非常低的数据库查询。