【问题标题】:Does the Rails model validate method check the current data as part of the validation process, before the save is attempted?在尝试保存之前,Rails 模型的验证方法是否会在验证过程中检查当前数据?
【发布时间】:2012-05-25 07:54:43
【问题描述】:

我正在查看 Michael Hartl 的 [Rail Tutorial] 的第 6 章中的一些 RSpec 代码:http://ruby.railstutorial.org/chapters/modeling-users#code:validates_uniqueness_of_email_test。它是为了测试用户模型的电子邮件属性的唯一性验证方法而编写的。它看起来像这样:

清单 6.18。拒绝重复电子邮件地址的测试。 (*spec/models/user_spec.rb*)

require 'spec_helper'

describe User do

  before do
    @user = User.new(name: "Example User", email: "user@example.com")
  end
  subject { @user }
  .
  .
  .
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
end

这是用户模型验证代码:

validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true

我的问题是:验证实际上是如何工作的? 有一个用户的电子邮件地址已保存到数据库中,并且 @user 实例上的 Rails 验证在我之前返回为无效甚至试图拯救它? Rails 验证器是否使用当前数据来验证用户实例,即使它们只是存储在内存中并且当前没有尝试添加到数据库中?

【问题讨论】:

  • 为什么大家突然开始在 rspec 中使用隐式接收者和主题?好的 ole it "does something" 和显式变量有什么问题?就是吐槽。无法弄清楚你的测试对象是谁?新用户?还是缺少一些代码?顺便说一句,我会定期与Active Record Validations and Callbacks联系,这可能对您有所帮助。
  • @ArtShayderov,作者没有提供这段代码:subject { @user }。您可以点击他的链接亲自查看。
  • 你说得对,如果代码丢失了。对不起;)

标签: ruby-on-rails


【解决方案1】:

be_valid@user 上调用valid?。这就是 rspec 的工作原理。而valid? 调用run_validations!,后者又调用run_callbacks :validate。您可以通过源代码跟踪方法链:valid?activerecord / lib / active_record / validations.rb 中定义,它在 activemodel / lib / active_model / validations.rb 中调用super valid?

这就是它的工作原理。即使模型未保存,模型也可能有效或无效。如果它从未被保存(new_record? 返回true),因为在您的情况下,:create 上的验证被调用。基本上,如果模型有效,则可以保存。如果已保存(new_record? 返回 false 但它可以包含未保存的更改),则调用 :update 上的验证。

【讨论】:

  • 这是一个很好的解释,艺术。但只是为了(也许过分)简化问题及其答案,我想了解这一点:“Rails 验证器是否使用当前数据来验证 [唯一性]?”根据定义,要测试唯一性,您需要将要验证的对象与现有 对象/记录进行比较。因此,在不追踪源头的情况下,我强烈怀疑数据库(或其他对象存储)正在在验证期间被检查(至少是为了唯一性,这是定义所要求的)。
  • 当然会检查数据库。这是 Rails 文档3.10 uniqueness 的相关链接。您可以在 Rails 控制台中调用 valid? 并查看添加到 development.log 文件中的 SQL 查询。
猜你喜欢
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多