覆盖rails中的redirect_to

时间:2014-06-24 12:41:46

标签: ruby-on-rails ruby redirect override

我在我的rails应用程序中使用一个引擎来登录用户并重定向到服务参数(它是CAS引擎)。但是,从主机应用程序我想重定向用户(他/她已登录后)在不同的位置,有时取决于参数。目前我无法让它工作,因为rails只允许1次调用redirect_to / render。该引擎继承自我的rails app ApplicationController。

如何覆盖/重新定义redirect_to以多次调用它?

问题可能会以其他方式解决,但我真的不想要它们。我已经尝试了其中一些,但没有人可以与简单地让最后一个定义的redirect_to采取行动。

对涉及重新定义redirect_to的解决方案感兴趣,以便我可以多次调用它。

3 个答案:

答案 0 :(得分:0)

当然你可以"覆盖"它。您可以在Ruby中的任何位置重新定义任何对象中的任何方法。但是,这是一个可怕的想法。你应该解决你的问题,即你要两次调用redirect_to,而不是攻击Rails,以便让你的问题继续下去。

如果你仍然坚持"修复"这是错误的方法,找到源代码(这很容易做到),将其复制到您自己的初始化程序/库文件中,然后进行修改。

module ActionController::Redirecting
  def redirect_to(options = {}, response_status = {})
    raise ActionControllerError.new("Cannot redirect to nil!") unless options
    raise AbstractController::DoubleRenderError if response_body

    self.status        = _extract_redirect_to_status(options, response_status)
    self.location      = _compute_redirect_to_location(options)
    self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.h(location)}\">redirected</a>.</body></html>"
  end
end

如果你真的想要这样做,尽管被预先警告它是你的问题的错误的解决方案,并且你从根本上改变其他东西可能依赖的Rails的行为,评论超出引发DoubleRenderError的行。

答案 1 :(得分:0)

这似乎比我想象的容易得多。您需要做的就是显式修改响应对象。 因此,您可以在ApplicationController中声明以下函数:

def re_redirect_to(location, status = 303)
  response.location = location
  response.status = status
end

基本上就是这样。优雅而简单。

正如我在第一篇文章中所说:

  

我在我的rails应用程序中使用一个引擎来登录用户并重定向到服务参数(它是CAS引擎)。但是,从主机应用程序我想重定向用户(他/她已登录后)在不同的位置,有时取决于参数。目前我无法让它工作,因为rails只允许1次调用redirect_to / render。该引擎继承自我的rails app ApplicationController。

所以基本上我没有别的选择,只能在ApplicationController的after_action中覆盖引擎的redirect_to。我相信它比修改引擎的源代码更好,更易于维护。

我想在此注意遵循惯例是绝对好的。在99%的情况下,应该避免不止一次调用redirect_to。但很高兴知道有一种方法可以解决其他1%的问题。公约只是惯例。

答案 2 :(得分:0)

这对我有用,在应用程序控制器中,重写重定向,执行您的操作,然后调用super:

class ApplicationControler < ... #depends on your rails version
    def redirect_to(options = {}, response_status = {})
        # do your custom thing here
        super # and call the default rails redirect

希望这会有所帮助, 凯文