如何在更新属性之前添加错误?

时间:2016-01-31 22:16:29

标签: ruby-on-rails validation delayed-job

我正在尝试处理用户输入错误信息的情况,因此我的路径大致如下:

class Thing < AR
  before_validation :byebug_hook
  def byebug_hook
    byebug
  end
end

thing = Thing.find x
thing.errors.add(:foo, "bad foo")
# Check byebug here, and errors added
if thing.update_attributes(params)
  DelayedJobThatDoesntLikeFoo.perform
else
  flash.now.errors = #...
end

byebug for byebug_hook> errors.messages #=> {}

最初我认为可能模型正在运行自己的验证并覆盖我添加的那些,但正如你所看到的那样,即使我添加了前钩子,错误也会丢失,而且我不确定是什么导致它

实际解决方案 所以,@ SteveTurczyn是正确的,错误需要在某个地方发生,在这种情况下是在我的控制器中调用的服务对象

我所做的改变是

class Thing < AR
validate :includes_builder_added_errors
    def builder_added_errors
      @builder_added_errors ||= Hash.new { |hash, key| hash[key] = [] }
    end

  def includes_builder_added_errors
    builder_added_errors.each {|k, v| errors.set(k, v) }
  end
end

and in the builder object
thing = Thing.find x
# to my thinking this mirrors the `errors.add` syntax better
thing.builder_added_errors[:foo].push("bad foo") if unshown_code_does_stuff?
if thing.update_attributes(params)
  DelayedJobThatDoesntLikeFoo.perform
else
  flash.now.errors = #...
end

1 个答案:

答案 0 :(得分:1)

update_attributes将验证模型...这包括清除所有现有错误,然后运行任何before_validation回调。这就是为什么before_validation

的pont上没有任何错误的原因

如果要向&#34;正常&#34;添加错误条件验证错误,您可以更好地将其作为模型中的自定义验证方法。

class Thing < ActiveRecord::Base
  validate :add_foo_error

  def add_foo_error
    errors.add(:foo, "bad foo")
  end
end

如果您只想在某些控制器或条件下进行某些验证,可以通过在模型上设置attr_accessor值并在直接运行验证(有效?)或间接运行验证之前设置值来实现。 (:更新,:保存)。

class Thing < ActiveRecord::Base
  attr_accessor :check_foo
  validate :add_foo_error

  def add_foo_error
    errors.add(:foo, "bad foo") if check_foo
  end
end

在控制器......

thing = Thing.find x
thing.check_foo = true
if thing.update_attributes(params)
  DelayedJobThatDoesntLikeFoo.perform
else
  flash.now.errors = #...
end