无法返回在模型上创建的错误

时间:2013-10-28 17:39:41

标签: ruby-on-rails ruby responders

我正在使用gem Responders,但我无法使用erros.add(:base, 'Error message')显示我在模型上创建的错误。

在我的控制器上,在respond_with @app之前,我调试了@app对象,错误@app.errors.any?返回true

在我看来,当我检查flash@app个对象时,没有错误

App控制器

# app_controllers.rb
def destroy
  @app = current_company.apps.find(params[:id])
  @app.destroy
  respond_with @app
end

App模型

# app.rb

before_destroy :destroy_on_riak

# ...

def destroy_on_riak
  # SOME CODE HERE
rescue Exception => e
  errors.add(:base, I18n.t("models.app.could_not_destroy", :message => e.message))
  return false
end

应用视图

# apps.html.haml
-flash.each do |name, msg|
  %div{:class => "flash #{name}"}
    =content_tag :p, msg if msg.is_a?(String)

这是@app对象之前 @app.destroy

"#<ActiveModel::Errors:0x00000004fa0510 @base=#<App id: 34, ...>, @messages={}>"

这是 @app.destroy

之后的@app对象
"#<ActiveModel::Errors:0x00000004fa0510 @base=#<App id: 34, ...>, @messages={:base=>[\"Não foi possível excluir a aplicação: undefined method `get_or_new' for #<App:0x00000004f824c0>\"]}>"

为了简单起见,我删除了@base=中的内容。

4 个答案:

答案 0 :(得分:2)

jefflunt是正确的,当一个人调用#valid?时,它会清除错误数组:请参阅https://github.com/rails/rails/blob/4a19b3dea650351aa20d0cad64bf2d5608023a33/activemodel/lib/active_model/validations.rb#L333

验证程序旨在 100%确定对象的有效性,而不是在您自己添加错误以供以后使用时。

虽然ActiveRecord会覆盖#valid?,但它仍会调用superhttps://github.com/rails/rails/blob/4a19b3dea650351aa20d0cad64bf2d5608023a33/activerecord/lib/active_record/validations.rb#L58

如果你想添加错误并坚持下去,我建议这样:

def failures
  @failures ||= []
end

validate :copy_failures_to_errors

def copy_failures_to_errors
  @failures.each { |f| errors.add(*f) }
end

然后修改您的rescue

def destroy_on_riak
  # SOME CODE HERE
rescue Exception => e
  failures.push([:base, I18n.t("models.app.could_not_destroy", :message => e.message)])
  return false
end

我知道这看起来很复杂,我知道网上甚至有人使用或推荐errors.add(:base, ...)的例子,但这不是一种安全存储和检索错误的方法。


另外,只是一个推荐,但我建议你拯救StandardError而不是Exception,除非你绝对必须。内存不足错误和类似的内容是Exception s,但是你想要解决的每个正常错误都应该从StandardError继承。仅供参考。

答案 1 :(得分:1)

这个谜似乎是(a)你可能没有调用正确的方法,或者(b).errors哈希不包含你认为它包含的内容。

错误的方法?

在您的控制器中,您正在调用@app.destroy,但添加错误的方法称为destroy_on_riak

你确定你不打算输入这个吗?

# app_controllers.rb
def destroy
  @app = current_company.apps.find(params[:id])
  @app.destroy_on_riak    # <= The offending line?
  respond_with @app
end

或者您的代码示例中是否缺少before_destroy回调,而这些回调又会​​调用destroy_on_riak?从包含的代码中我看不到destroy_on_riak方法被调用的任何地方,所以这只是猜测。

.errors hash的意外内容?

如果这不是问题,那么当@app.errors.any?返回true时,代码中的那一点会将@app.errors的内容打印到您的日志中,这样您就可以看到错误了。

答案 2 :(得分:1)

我会给你一些提示:

提示1

您的表单可能正在valid?对象上调用@appvalid?方法清除实例上的errors数组。

在验证上下文之外使用errors数组/构造是不正确的。但这是MHO。

提示2

根据Responders gem(我以前从未使用过),您的语言环境只需要具有正确的配置。例如:

flash:
  actions:
    create:
      notice: "{resource_name} was successfully created"
    update:
      notice: "{resource_name} was successfully updated"
    destroy:
      notice: "{resource_name} was successfully destroyed"
      alert: "{resource_name} could not be destroyed"

是吗?

答案 3 :(得分:0)

我必须同意@p.mastinopoulos。这应该通过内置验证来处理。听起来你需要建立一个自定义验证器。

http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validate

尝试将before_destroy替换为validate

validate :destroy_on_riak, on: :destroy

没有尝试过,但如果它不起作用,您可能需要考虑创建文档中引用的自定义Validator。