ActiveRecord有效吗?即使存在错误,方法也返回true

时间:2016-06-16 17:29:14

标签: ruby-on-rails activerecord

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

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视为有效。

2 个答案:

答案 0 :(得分:1)

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

删除before_create,然后添加:

validate :allow_unique_only

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

答案 1 :(得分:0)

要回答您为什么会发生这种问题(因为这也令我感到惊讶),所以我查看了源代码。在版本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