gpt4 book ai didi

ruby-on-rails - Railstutorial.org 验证唯一的电子邮件

转载 作者:行者123 更新时间:2023-12-04 06:06:24 25 4
gpt4 key购买 nike

在 Ruby on Rails 3 教程的 6.2.4 节中,Michael Hartl 描述了一个关于检查电子邮件地址唯一性的警告:如果两个相同的请求及时接近,请求 A 可以通过验证,然后 B 通过验证,然后 A 被保存,然后B 被保存,你会得到两个具有相同值的记录。每个在检查时都是有效的。

我的问题与解决方案无关(对数据库设置唯一约束,以便 B 的保存不起作用)。这是关于编写测试以证明解决方案有效。我尝试编写自己的,但无论我想出什么,结果都只是模仿常规的、简单的唯一性测试。

作为 rspec 的新手,我天真的方法是只编写场景:

it 'should reject duplicate email addresses with caveat' do
A = User.new( @attr )
A.should be_valid # always valid

B = User.new( @attr )
B.should be_valid # always valid, as expected

A.save.should == true # save always works fine

B.save.should == false # this is the problem case
# B.should_not be_valid # ...same results as "save.should"
end

但是这个测试在与常规唯一性测试完全相同的情况下通过/失败; B.save.should == false在编写我的代码时通过,以便常规唯一性测试通过并在常规测试失败时失败。

所以我的问题是“我如何编写一个 rspec 测试来验证我正在解决这个问题?”如果答案是“它很复杂”,那么我应该查看不同的 Rails 测试框架吗?

最佳答案

情况很复杂。种族条件之所以如此恶劣,正是因为它们很难重现。内部,save是这样的:

  • 证实。
  • 写入数据库。

  • 因此,要重现计时问题,您需要安排两个 save像这样重叠的调用(伪Rails):
    a.validate    # first half of a.save
    b.validate # first half of b.save
    a.write_to_db # second half of a.save
    b.write_to_db # second half of b.save

    但是你打不开 save方法并很容易地摆弄它的内部结构。

    但是(这是一个很大的但是), you can skip the validations entirely :

    Note that save also has the ability to skip validations if passed :validate => false as argument. This technique should be used with caution.



    所以如果你使用
    b.save(:validate => false)

    你应该只得到 b 的“写入数据库”的一半的 save并在未经验证的情况下将您的数据发送到数据库。这应该会触发数据库中的约束违规,我很确定这会引发 ActiveRecord::StatementInvalid异常所以我认为您需要查找异常,而不仅仅是来自 save 的错误返回:
    b.save(:validate => false).should raise_exception(ActiveRecord::StatementInvalid)

    您也可以收紧它以查找特定的异常消息。我没有任何方便的东西来测试这个测试,所以在 Rails 控制台中尝试一下并适本地调整你的规范。

    关于ruby-on-rails - Railstutorial.org 验证唯一的电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8722541/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com