【问题标题】:ActiveRecord valid? method returning true even with errors presentActiveRecord 有效吗?即使存在错误,方法也会返回 true
【发布时间】:2021-05-04 08:29:35
【问题描述】:

我在这里有一个令人头疼的问题,我确信它很简单,我只是在俯瞰。考虑以下模型:

class Flag < ActiveRecord::Base
  belongs_to :user
  belongs_to :flaggable, polymorphic: true

  validates :reason, presence: true
  validates :flaggable_id, presence: true
  validates :flaggable_type, presence: true

  before_create :allow_unique_only

private
  def allow_unique_only
    errors.add(:base, "You have already flagged this.") if self.user.flagged?(self.flaggable)

    Rails.logger.debug("Errors: #{errors.full_messages}")
    Rails.logger.debug("Valid: #{valid?}")
  end
end

非常简单。除非我执行此操作,否则它会将错误添加到 base 并在控制台中按应有的方式向我提供错误输出,但它也表明该对象是有效的。

Errors: ["You have already flagged this."] Valid: true

而且它可以节省!什么给了?

编辑:我知道我可以通过在该方法的末尾添加类似errors.empty? 的内容来使其工作,我只是想了解为什么它是ActiveRecord 认为有效。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    为了回答您为什么会发生这种情况的问题(因为这也让我感到惊讶),我查看了源代码。在版本 4.8.2(我正在使用的版本也表现出这种行为)中,ActiveModel#valid? 的定义清除现有错误,然后运行“真实”验证。

    def valid?(context = nil)
      current_context, self.validation_context = validation_context, context
      errors.clear
      run_validations!
    ensure
      self.validation_context = current_context
    end
    

    我试图追查这种行为的历史,但它已经 12 年没有改变,显然是从 SVN 迁移的项目的一部分;旧的 SVN 存储库不会为我加载,所以原来的“为什么”可能会丢失在时间的流沙中。

    https://github.com/rails/rails/blob/8ee716182df410052707c3d1eabf8bfd8e0e1c5e/activemodel/lib/active_model/validations.rb#L335-L343

    【讨论】:

      【解决方案2】:

      您应该将该方法添加为验证器,验证器完成后,您可以检查valid?

      去掉 before_create 然后添加:

      validate :allow_unique_only
      

      http://guides.rubyonrails.org/active_record_validations.html#custom-methods

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-08
        • 1970-01-01
        • 1970-01-01
        • 2020-04-02
        • 1970-01-01
        • 1970-01-01
        • 2017-07-25
        相关资源
        最近更新 更多