我在这里有一个令人头疼的问题,我确信这很简单,我只是在俯视。考虑以下模型:
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视为有效。
答案 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存储库无法为我加载,因此原始的“为什么”可能会迷失在时光中。