Ruby on rails Ruby教程和;“独特性”;
我一直在关注这个教程,我觉得很好,但它提到了一些关于唯一性属性的东西,我没有得到。 这是迄今为止的mu用户文件:Ruby on rails Ruby教程和;“独特性”;,ruby-on-rails,Ruby On Rails,我一直在关注这个教程,我觉得很好,但它提到了一些关于唯一性属性的东西,我没有得到。 这是迄今为止的mu用户文件: class User < ActiveRecord::Base #these attributes can be modified by the users attr_accessible :name, :email; #validation testing validates :name, presence: true, length: {
class User < ActiveRecord::Base
#these attributes can be modified by the users
attr_accessible :name, :email;
#validation testing
validates :name, presence: true, length: { maximum: 50 }
#regular expression (there is an official one)
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
#and add it..
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
end
class用户
它说:
“使用验证:唯一性并不保证唯一性
Alice无意中点击了两次“提交”,很快连续发送了两个请求。
发生以下顺序:请求1在内存中创建通过验证的用户,请求2执行相同操作,请求1的用户保存,请求2的用户保存。
结果:两个用户记录具有完全相同的电子邮件地址,尽管存在唯一性验证。“
我尝试使用控制台(以及User.create方法)创建两个具有相同电子邮件地址的用户,唯一性似乎很好,因为只有第一个用户进入了sqlite3。那么,什么会导致错误或唯一性失败呢?我相信本教程试图说明的一点是,唯一性验证是由应用程序层实施的,而不是由数据库实施的。如果您有一个可以同时处理多个请求的系统,那么:唯一性验证会受到竞争条件的影响 唯一性的工作方式是(1)查询数据库中的匹配记录。如果未找到匹配的记录,则验证通过,(2)该记录保存到数据库。在步骤(1)和(2)之间,从理论上讲,另一个请求突入并向数据库添加匹配记录是可能的,尽管可能性不大
这个问题也可以通过在数据库中强制唯一性来避免。如何做到这一点取决于您使用的数据库;Rails并不能帮助您这样做。我相信本教程试图说明的一点是,唯一性验证是由应用程序层而不是数据库强制执行的。如果您有一个可以同时处理多个请求的系统,那么:唯一性验证会受到竞争条件的影响 唯一性的工作方式是(1)查询数据库中的匹配记录。如果未找到匹配的记录,则验证通过,(2)该记录保存到数据库。在步骤(1)和(2)之间,从理论上讲,另一个请求突入并向数据库添加匹配记录是可能的,尽管可能性不大
这个问题也可以通过在数据库中强制唯一性来避免。如何做到这一点取决于您使用的数据库;Rails不会帮助您这样做。如果您有两个RoR实例与同一台SQL server对话,可能会出现以下情况:
process A reads, no email like 'foo@bar'
process B reads, no email like 'Foo@BAR'
process A writes new User with 'foo@bar'
process B writes new User with 'Foo@BAR'
Ruby一次不支持多个线程
,因此需要两个单独的RoR进程
如果您使用SQL编写唯一性强制,或者使用
DataMapper
而不是ActiveRecord
可以解决此问题如果您有两个RoR实例与同一SQL server对话,则可能会出现以下情况:
process A reads, no email like 'foo@bar'
process B reads, no email like 'Foo@BAR'
process A writes new User with 'foo@bar'
process B writes new User with 'Foo@BAR'
Ruby一次不支持多个线程
,因此需要两个单独的RoR进程
如果使用SQL编写唯一性强制,或者使用
DataMapper
而不是ActiveRecord
,当两个并行进程试图保存冲突对象时,约束失败,则可以解决此问题
Process 1 Process 2
1. Create Object in Memory
2. Create Object in Memory
3. Check DB -> valid
4. Check DB -> valid
现在,两个进程都认为已经验证了其唯一性约束,并继续保存对象
5. save
6. save
现在的问题是,两个进程在保存其对象之前都要检查唯一性。因此,两个过程都可以看到在检查时没有冲突。冲突仅在步骤5之后才开始存在。现在的问题是,在步骤6中未对其进行检查,因此流程6会保存一个不遵循唯一约束的无效对象
为了缓解这种情况,您可以在数据库上创建一个唯一的索引。这将确保您不能在数据库中插入无效数据,因为约束是由数据库以原子方式检查的,因此竞争条件不再发生
现在你只能依靠那个唯一的索引了。但是,您会注意到,如果在那里发生错误,您将不会得到很好的错误消息。所以在实践中,你应该同时使用这两种方法。因此,在大多数情况下,您可以依赖rails良好集成的独特约束。对于少数情况下的竞争条件,您可以依靠唯一索引来确保数据100%保存。当两个并行进程试图保存冲突对象时,约束将失败
Process 1 Process 2
1. Create Object in Memory
2. Create Object in Memory
3. Check DB -> valid
4. Check DB -> valid
现在,两个进程都认为已经验证了其唯一性约束,并继续保存对象
5. save
6. save
现在的问题是,两个进程在保存其对象之前都要检查唯一性。因此,两个过程都可以看到在检查时没有冲突。冲突仅在步骤5之后才开始存在。现在的问题是,在步骤6中未对其进行检查,因此流程6会保存一个不遵循唯一约束的无效对象
为了缓解这种情况,您可以在数据库上创建一个唯一的索引。这将确保您不能在数据库中插入无效数据,因为约束是由数据库以原子方式检查的,因此竞争条件不再发生
现在你只能依靠那个唯一的索引了。但是,您会注意到,如果在那里发生错误,您将不会得到很好的错误消息。所以在实践中,你应该同时使用这两种方法。所以