为什么Rails允许双重渲染?

问题描述 投票:0回答:1
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中时,将不会执行操作。简而言之,不存在双重渲染的风险。

Rails Guide on controllers

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

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

以下面的代码为例。当用户可以访问foobarhello时,Rails将引发Double Render Exception。

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'完成时,为什么不立即响应并停止请求周期?这听起来更合理。

ruby-on-rails ruby rendering
1个回答
1
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.