【问题标题】:Rails: DoubleRenderError - "Render and/or redirect were called multiple times in this action"Rails:DoubleRenderError - “在此操作中多次调用渲染和/或重定向”
【发布时间】:2013-02-03 08:07:40
【问题描述】:

我想通过用户的role_ids 重定向:

  • 如果等于2,重定向到workers_path
  • 如果等于1,重定向到tasksadmins_path

我定义了接下来的事情:

class ApplicationController < ActionController::Base
  include ApplicationHelper

  protect_from_forgery
  before_filter :authenticate_user!

  def stored_location_for(user)
    nil
  end

  def after_sign_in_path_for(user)
     if current_user.role_ids == [2]
       return redirect_to(workers_path)
     else
       return redirect_to (tasksadmins_path)
     end
  end
end

但是当我登录时,我得到了错误:

AbstractController::DoubleRenderError in UserSessionsController#create

Render and/or redirect were called multiple times in this action. Please note 
that you may only call render OR redirect, and at most once per action. Also 
note that neither redirect nor render terminate execution of the action, so 
if you want to exit an action after redirecting, you need to do something 
like "redirect_to(...) and return".
Rails.root: /home/alon/alon/todolist

Application Trace | Framework Trace | Full Trace
app/controllers/user_sessions_controller.rb:5:in `create'
Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"jRNZkIXvToEhl9YVxaQoa2hLJiSaHI6JAdfpUNAQMJI=",
 "user"=>{"email"=>"worker216@gmail.com",
 "password"=>"[FILTERED]",
 "remember_me"=>"0"},
 "commit"=>"Sign in"}

这是我的user_session_controller.rb

class UserSessionsController < Devise::SessionsController
  include ApplicationHelper

  def create
      response = super

      require "uri"
      require "net/http"

      ## get the user id from the database
      user_id = session['warden.user.user.key'][1][0];

      ## get the row by id
      user = User.find(user_id)

      # ============================
      # Ensure that a user exists
      # ============================

      code, body = http_request(Net::HTTP::Put.new("/api/v1/users/external/#{user_id}"), email: user.email);
      if code != 200
         Rails.logger.error("Unable to register user #{current_user.email} at Licensario");
      end

      response
   end
end

这是我的routes.rb

TODOLIST::Application.routes.draw do

    devise_for :users, :controllers => { :sessions => 'user_sessions'} do
        get '/users/sign_out' => 'devise/sessions#destroy'
    end

    resources :tasksadmins
    resources :workers
    root to: "workers#index"
end

【问题讨论】:

    标签: ruby-on-rails redirect devise super internal-server-error


    【解决方案1】:

    您不应在after_sign_in_path_for 中返回redirect_to。你应该返回网址:

      def after_sign_in_path_for(user)
         if current_user.role_ids == [2]
           return workers_url
         else
           return tasksadmins_url
         end
      end
    

    【讨论】:

    • @MikhalNikalyukin,我尝试了你的建议,它把我重定向到:localhost:3333/users/sign_in
    • 应该总是重定向到_url 而不仅仅是_path;您正在重定向的页面也可能需要您没有的身份验证,然后重定向回登录页面。
    • @PeppyHeppy,谢谢,但我有要求的身份验证。我试图在函数'after_sign_in_path_for'的第一行打印'current_user.role_ids',它打印'2'。另外,只有应用控制器需要认证(before_filter :authenticate_user!)
    • @AlonShmiel,您可能正在比较 [2] == 2 并且它是错误的,因为它将数组与整数进行比较。顺便说一句,我会向用户模型添加方法,例如 current_user.super_admin?,并避免在您的应用中使用角色 ID。
    • 再次谢谢你..它在过去对我有用,当我使用:“rescue_from CanCan::AccessDenied do |exception|”然后检查了role_ids(所以不存在Integer的问题)。当我使用以下函数时,这些行停止工作:“after_sign_in_path_for”而不是“rescue_from CanCan::AccessDenied do |exception|”。关于你的第二个建议,我更喜欢继续使用 role_ids。谢谢你们的cmets。
    【解决方案2】:

    我添加到“创建”下一行:

    一开始,我写道:

    resource = warden.authenticate!(:scope => resource_name)
    

    然后我在'create'函数的末尾写了:

    sign_in(resource_name, resource)
    
    if current_user.role_ids == [2]
       respond_with resource, :location => workers_path
    else
       respond_with resource, :location => tasksadmins_path
    end
    

    所以我的创作看起来是这样的:

    class UserSessionsController < Devise::SessionsController
        include ApplicationHelper
    
        def create
    
            resource = warden.authenticate!(:scope => resource_name)
    
            require "uri"
            require "net/http"
    
            ## get the user id from the database
            user_id = session['warden.user.user.key'][1][0];
    
            ## get the row by id
            user = User.find(user_id)
    
            # ============================
            # Ensure that a user exists
            # ============================
    
            code, body = http_request(Net::HTTP::Put.new("/api/v1/users/external/#{user_id}"), email: user.email);
            if code != 200
               Rails.logger.error("Unable to register user #{current_user.email} at Licensario");
            end
    
            sign_in(resource_name, resource)
    
            if current_user.role_ids == [2]
               respond_with resource, :location => workers_path
           else
               respond_with resource, :location => tasksadmins_path
           end
    
        end
    end
    

    【讨论】:

      【解决方案3】:

      我在使用 devise gem 管理我的管理员帐户时遇到了这个问题,但我的是在生产服务器上。

      AbstractController::DoubleRenderError(在此操作中多次调用渲染和/或重定向。请注意,您只能调用渲染或重定向,每个操作最多调用一次。另请注意,重定向和渲染都不会终止执行动作,所以如果你想在重定向后退出动作,你需要做一些类似“redirect_to(...) and return”的操作。):

      问题是我想登录管理仪表板,而不是在浏览器中输入 admin_dashboard URL,而是在浏览器中输入 admin_sign_in URL,同时,一个管理员帐户已经登录。所以当我尝试登录时它不起作用,因为我无法同时登录 2 个帐户到管理仪表板。

      我是这样解决的:

      1. 在浏览器中输入管理仪表板的 URL,这使我登录到以前的帐户
      2. 从管理仪表板上的帐户注销
      3. 然后使用我想要的帐户登录到管理仪表板。

      就是这样。

      我希望这会有所帮助

      【讨论】:

        猜你喜欢
        • 2019-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多