【问题标题】:Why Rails allows double rendering?为什么 Rails 允许双重渲染?
【发布时间】:2018-04-26 05:17:42
【问题描述】:
class SomeController < ApplicationController
  before_action :api_limit

  def new
    if user.can_access_foo?
      render 'foo'
    end

    if user.can_access_bar?
      render 'bar'
    end

    if user.can_access_hello?
      render 'hello'
    end
  end

  def api_limit
    render 'exceed_limit_error'
    # code in action will not be executed.
  end
end

renderredirect_to存在于before_filter时,action不会被执行。总之,不存在双重渲染的风险。

Rails Guide on controllers

如果“之前”过滤器呈现或重定向,则该操作将不会运行。如果有其他过滤器计划在该过滤器之后运行,它们也会被取消。

但是,为什么 Rails 允许在一个动作中进行双重渲染?

以下面的代码为例。当用户可以访问 foobarhello 时,Rails 将引发双重渲染异常。

class SomeController < ApplicationController
  before_action :callback

  def new
    if user.can_access_foo?
      render 'foo' 
      # From my understanding, following render should 
      # be ignored if this step is successfully performed.
    end

    if user.can_access_bar?
      render 'bar'
    end

    if user.can_access_hello?
      render 'hello'
    end
  end
end

为什么不立即响应并在render 'foo' 完成时停止请求周期?这听起来更合理。

【问题讨论】:

  • “为什么 Rails 允许在一个动作中进行双重渲染?” - 也许你应该问问 Rails Core 团队。
  • 我认为第二个render 会引发错误。但是,要回答您的问题,Rails 不能跳出您的方法,例如引发异常,因为这将放弃任何等待运行的非render 行。
  • 因为渲染!=返回。只需对这些情况使用保护子句
  • 好点@Philip - 您可能希望在渲染后在控制器中运行更多代码,但是 before_action 回调不让动作运行似乎不一致。

标签: ruby-on-rails ruby rendering


【解决方案1】:

动作中的render 语句不返回代码执行的原因是,在动作中渲染之后还有更多(非渲染)代码要执行是一个合理的用例。

before_action 回调中的渲染不允许代码执行进入操作的原因是因为这会假设您的操作具有既不渲染也不重定向的代码路径(否则您会得到一个双渲染错误)。动作中的这个代码路径是一个不太合理的用例,因为它会依赖“之前”过滤器来触发并执行渲染。

Rails 在控制器中的动作和过滤器结构的意图是它们不是紧密耦合的。通常,过滤器不会知道在它之后会运行什么动作,并且动作也不知道在它运行之前触发了什么过滤器。因此,让它们协调哪个在进行渲染会破坏这种松散耦合。每个动作都必须假定渲染是其角色的重要组成部分,这就是为什么如果过滤器已经渲染,则运行动作没有意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    相关资源
    最近更新 更多