为什么Rails允许双重渲染?

时间:2018-04-26 05:17:43

标签: ruby-on-rails ruby rendering

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

在before_filter中存在renderredirect_to时,不会执行操作。简而言之,不存在双重渲染的风险。

请参阅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'完成时停止请求周期?这听起来更合理。

1 个答案:

答案 0 :(得分:1)

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

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

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