AbstractController :: DoubleRenderError错误并使用redirect_to

时间:2014-03-22 23:04:41

标签: ruby-on-rails ruby

我有一个更新方法,它使用具有自己的渲染调用的保存和删除方法。以下是代码:

更新方法:

def update_book
  self.delete_book
  params[:Name] = params[:NewName]
  self.save_book
end

删除方法:

def delete_book
 # Do something
 rescue BookDoesNotExist => exception
    render status: 404
    return
 end
 head 200
end

保存方法:

def save_book
 # Do something
 rescue BookDoesNotExist => exception
    render status: 404
    return
 end
 rescue BookAlreadyExist => exception
    render status: 409
    return
 end
 head 200
end

当我使用某些输入运行时,系统会抛出“AbstractController::DoubleRenderError”错误以及一些消息“Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return

我理解这是因为在我传递的输入中,删除和保存方法都抛出了异常。我该如何处理这种情况?

进行一些研究我了解到我需要使用重定向。所以我理解当我的delete方法抛出异常/渲染时我应该返回并且不应该调用save方法。

以下是我使用redirect_to尝试的内容:

更新方法:

def update_book
  redirect_to action: self.delete_book and return if status=404 end
  params[:Name] = params[:NewName]
  self.save_book
end

我做得对吗还是还有其他最好的方法来处理重定向吗?

1 个答案:

答案 0 :(得分:2)

当您的delete_booksave_book方法收到异常后,他们会呈现内容然后返回,这是正确的。

但是return会将执行返回给调用者方法,即update_book。此调用方法不知道发生的异常,因此将完成其工作并呈现它必须呈现的内容。

要解决此问题,您的delete_booksave_book方法需要向调用方返回成功状态,如下所示:

def delete_book
  # ... Do something

  rescue BookDoesNotExist => exception
    render status: 404
    return false
  end

  head 200
  true
end

然后您的调用方法将检查此状态:

def update_book
  return unless self.delete_book
  params[:Name] = params[:NewName]
  return unless self.save_book
end

另一种可以让您的代码远离那些繁重的异常测试的替代方法是使用您的控制器rescue_from

ApplicationController

class ApplicationController < ActionController::Base
  rescue_from BookDoesNotExist, with: :redirect_book_not_existing

  private 

  def redirect_book_not_existing
    render status: 404
  end
end

从现在开始,当控制器收到BookDoesNotExist异常时,执行将停止并执行render status: 404行。当然,您不能rescue其他方法中的例外情况,例如:

def delete_book
 # Do something

 head 200
end

您的代码将更加清晰