【问题标题】:Override redirect_to in rails在rails中覆盖redirect_to
【发布时间】:2014-06-24 12:41:46
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你试图破坏 Rails。不要那样做。只需修复您的应用程序,您只需拨打一次redirect_to。你说你不会真的想要“其他方式”,但你的方式是错误
  • 您添加到问题末尾的内容不属于那里。请不要重新编辑它。
  • 您不能在您的问题中添加“请不要反对”。这不是本网站的运作方式。
  • 你还在尝试破坏 Rails。作为一名软件开发人员,把你的手指放在耳朵里并忽视那些真正知道他们在说什么的人的建议不会让你走得太远。你仍然试图以完全错误的方式解决你的问题。
  • @meagar 完全正确。说“我想这样做,没有其他方法会被接受”不是你能逃脱很长时间的事情。最好听取比你更熟悉问题的人的建议,并用它来改进你的代码和编码习惯。

标签: ruby-on-rails ruby redirect overriding


【解决方案1】:

当然,您可以“覆盖”它。您可以在 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 的行。

【讨论】:

  • 感谢您的回答!为什么这是一个可怕的想法?顺便说一句,我的解决方案之一是显式设置 response.location 和 response.status 以覆盖我认为更优雅的 redirect_to。
  • @Filippos 这是一个糟糕的主意,因为它很可能会在代码的其他部分产生意想不到的后果。修改redirect_to 代码就像在需要精确刀时对问题采取斧头。修复您的代码,使其不再尝试通过将重定向包装在 if/else 语句或 case 语句中来进行双重渲染。
  • 感谢您的回答,但除非我编辑引擎的代码,否则我看不到任何其他方式。
  • @Filippos 如果您发布了代码示例,我们可能会提供更好的方法。
  • 修改引擎的代码比修改 Rails 的代码好多
【解决方案2】:

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

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

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

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

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

所以基本上除了在 ApplicationController 的 after_action 中覆盖引擎的 redirect_to 之外,我别无选择。我相信它比修改引擎的源代码更好且更易于维护的解决方案。

我想在这里指出,遵守约定绝对是好的。在 99% 的情况下,绝对应该避免多次调用 redirect_to。但很高兴知道有一种方法可以处理另外 1%。约定只是约定。

【讨论】:

    【解决方案3】:

    这对我有用,在应用程序控制器中,覆盖重定向,做你的事情,然后调用 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
    

    希望这会有所帮助, 凯文

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-31
      • 2010-12-22
      • 1970-01-01
      • 2010-09-10
      • 2011-02-04
      相关资源
      最近更新 更多