【问题标题】:rails 4: AbstractController::DoubleRenderError with formatrails 4: AbstractController::DoubleRenderError with format
【发布时间】:2016-01-28 14:05:24
【问题描述】:

我正在通过 Ajax 请求创建组记录,并收到此错误(在这两种情况下,@group 有效或无效)

Started POST "/groups" for ::1 at 2015-10-28 17:47:08 +0100
Processing by GroupsController#create as JS

AbstractController::DoubleRenderError - Render and/or redirect were called multiple times in this action. Please.....

我不明白为什么,因为重定向和渲染不在同一个块中......

这是我的控制器

类 GroupsController

def create
    @group = Group.new(company_id: current_user.company_id, name: params[:name] )
    if @group.save?
      respond_to do |format|
        format.html { redirect_to groups_path, notice: 'Group was successfully created.'}
        format.js
      end
    else 
      respond_to  do |format|
        format.html { redirect_to new_group_path }
        format.js
      end
    end
end
...

在尝试渲染 create.js 时似乎发生了错误

 Rendered groups/create.js.erb (6.5ms)
 Completed 500 Internal Server Error in 48784ms (Views: 46.2ms |    ActiveRecord: 4.7ms)

这是一个非常标准的 .js.erb 文件

    <% if  @group.errors.blank? -%> 
      $('#groupModal').modal('hide');
    <% else %>
      $( "#modalGroupAlert" ).removeClass('alert-info');
      $( "#modalGroupAlert" ).addClass('alert-danger');
      $( "#modalGroupAlert span" ).replaceWith( "<span><%= nicer_display_errors(@group.errors) %></span>" );
      $( "#modalGroupAlert" ).show();
    <% end %>

发生了什么事?为什么?感谢反馈

更新 1 =======

根据 Pavan cmets,我更新了我的创建代码,还添加了响应程序 gem(rails 版本 4.2.4:不兼容性发布说明 - 3.2 respond_with / Class-Level respond_to)

respond_with 和相应的类级 respond_to 已移至响应者 gem。将 gem 'responders', '~> 2.0' 添加到您的 Gemfile 以使用它:

我的 :new 和 :create 代码现在是

    def new
      @group = Group.new()
      authorize @group
      respond_with @group
    end

    def create
      @group =  Group.new(group_params)
      respond_to do |format|
        if @group.save #remove ? here
          format.html { redirect_to groups_path }
          format.js
        else 
          format.html { redirect_to new_group_path }
          format.js
        end
      end
    end

:new.js 被正确处理

 Started GET "/groups/new.js?_=1446101853822" for ::1 at 2015-10-29 07:57:40 +0100
 Processing by GroupsController#new as JS
 ...
 Rendered groups/_new_modal_content.html.erb (15.8ms)
 Rendered groups/new.js.erb (23.6ms)
 Completed 200 OK in 84ms (Views: 65.7ms | ActiveRecord: 3.7ms)

但是 :create 仍然出现同样的错误

 Started POST "/groups" for ::1 at 2015-10-29 07:57:48 +0100
 Processing by GroupsController#create as JS
 ...
 Rendered groups/create.js.erb (0.4ms)

 Completed 500 Internal Server Error in 71ms (Views: 31.6ms | ActiveRecord: 21.2ms)
 AbstractController::DoubleRenderError - Render and/or redirect were called multiple times in this action. Please...

【问题讨论】:

  • 您是否有可能调用渲染或重定向的 before_filter 或 after 过滤器?
  • 感谢 Simon,我有前后过滤器,但它们不会影响渲染...只有身份验证、变量设置和权限 before_filter :authenticate_user! before_action :set_group, 除了: [:index, :new, :create] after_filter :verify_authorized, :except => :index, 除非: :devise_controller? after_filter :verify_policy_scoped, :only => :index
  • 对不起...我错了,你是对的!!!过滤后的权威是问题!评论他们使我的代码运行!请添加它作为答案,这样我就可以投票支持它,也许可以帮助运行 Pundit & Rails 4.2.4 的 debs

标签: ruby-on-rails-4 rendering


【解决方案1】:

正如问题的cmets中解释的那样,动作的代码没有问题。

但是,其中一个 after_filter 正在调用 render/redirect_to,这会导致 AbstractController::DoubleRenderError 错误。

就作者的问题而言,它似乎来自 Pundit after_filters。

一种可能的解决方案是将这些过滤器用作 before_filters 而不是 after_filters。事实上,当 before_filter 调用 render 或 redirect_to 时,动作代码并没有被执行,不可能得到AbstractController::DoubleRenderError 错误。

【讨论】:

  • 完成你的答案......仍然可以使用 Pundit after_filter 和 js 响应:after_filter :verify_authorized 通过在 format.js 响应块中跳过它:format.js { skip_authorization }
  • 我有一个类似的案例,其中操作创建了一个父项,然后更新了子记录。授权是罪魁祸首。
【解决方案2】:

AbstractController::DoubleRenderError - 渲染和/或重定向是 在此操作中多次调用

您应该将您的 create 操作更改为以下

def create
  @group = Group.new(company_id: current_user.company_id, name: params[:name] )

  respond_to do |format|
    if @group.save #remove ? here
      format.html { redirect_to groups_path, notice: 'Group was successfully created.'}
      format.js
    else 
      format.html { redirect_to new_group_path }
      format.js
    end
  end
end

在您使用 Rails 4 时,您应该使用 strong 参数

private

def group_params
  params.require(:group).permit(:name).merge(company_id: current_user.comapany_id)
end

然后改变

@group = Group.new(company_id: current_user.company_id, name: params[:name] )

@group = Group.new(group_params)

【讨论】:

  • 感谢 Pavan...我根据您的 cmets 更新了代码,但我仍然遇到同样的错误。在运行 Rails 4.2.4 时,我还添加了响应者 gem,以更好地处理respond_with,respond_to,但它不会改变行为......呈现create.js.erb正在引发错误......
  • @erwin 尝试从控制器中删除 respond_to :html, :js
  • 发现了问题:查看我对 Simon 评论的回答...... Pundit after_filter 是有罪的......评论它使我的代码运行......所以它没有被响应者对待......
  • @erwin 太好了!如果你觉得有帮助,请接受我的回答:)
  • 我不明白为什么这个答案被标记为接受。它没有为当前问题提供解决方案。
猜你喜欢
  • 1970-01-01
  • 2015-11-27
  • 2014-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多