Rails: DoubleRenderError — рендеринг и/или перенаправление вызывались несколько раз в этом действии

Я хочу перенаправить 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"=>"[email protected]",
 "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

person Alon Shmiel    schedule 03.02.2013    source источник


Ответы (3)


Вы не должны возвращать redirect_to в after_sign_in_path_for. Вы должны вернуть URL:

  def after_sign_in_path_for(user)
     if current_user.role_ids == [2]
       return workers_url
     else
       return tasksadmins_url
     end
  end
person Mikhail Nikalyukin    schedule 03.02.2013
comment
@MikhalNikalyukin, я попробовал то, что вы предложили, и меня перенаправляет на: localhost:3333/users/sign_in - person Alon Shmiel; 03.02.2013
comment
всегда должен перенаправлять на _url, а не только на _path; также страница, которую вы перенаправляете, вероятно, требует аутентификации, которой у вас нет, что затем перенаправляет обратно на страницу входа. - person PeppyHeppy; 03.02.2013
comment
@PeppyHeppy, спасибо, но у меня есть требуемая аутентификация. Я попытался напечатать «current_user.role_ids» в первой строке функции «after_sign_in_path_for», и она напечатала «2». кроме того, аутентификацию требует только контроллер приложения (before_filter :authenticate_user!) - person Alon Shmiel; 03.02.2013
comment
@AlonShmiel, возможно, вы сравниваете [2] == 2 и его false, потому что он сравнивает массив с целым числом. Кстати, я бы добавил методы в пользовательскую модель, такие как current_user.super_admin?, и избегал использования идентификаторов ролей в вашем приложении. - person PeppyHeppy; 03.02.2013
comment
еще раз спасибо .. это работало в прошлом, когда я использовал: save_from CanCan::AccessDenied do |exception| а затем проверил role_ids (так что проблем с Integer нет). эти строки перестали работать, когда я использовал функцию: after_sign_in_path_for вместо Rescue_from CanCan::AccessDenied do |exception|. Что касается вашего второго предложения, я предпочитаю использовать role_ids. Спасибо за ваши Коментарии. - person Alon Shmiel; 03.02.2013

Я добавил для «создания» следующие строки:

в начале я написал:

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

а затем я написал в конце функции "создать":

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
person Alon Shmiel    schedule 03.02.2013

Я столкнулся с этой проблемой, когда использовал гем devise для управления моей учетной записью администратора, но мой был на рабочем сервере.

AbstractController::DoubleRenderError (В этом действии рендеринг и/или перенаправление вызывались несколько раз. Обратите внимание, что вы можете вызывать только рендеринг ИЛИ перенаправление и не более одного раза для каждого действия. Также обратите внимание, что ни перенаправление, ни рендеринг не завершают выполнение действия, поэтому если вы хотите выйти из действия после перенаправления, вам нужно сделать что-то вроде «redirect_to(...) and return».):

Проблема заключалась в том, что я хотел войти в панель администратора, а не вводить URL-адрес admin_dashboard в браузере. Я ввел URL-адрес admin_sign_in в браузере, тем временем учетная запись администратора уже была зарегистрирована. Поэтому, когда я попытался войти, это не сработало, потому что я не могу одновременно войти в 2 учетные записи на панели администратора.

Вот как я решил эту проблему:

  1. Введите URL-адрес панели администратора в браузер, который ввел меня в предыдущую учетную запись.
  2. Выйдите из учетной записи на панели администратора
  3. А затем войдите в панель администратора, используя учетную запись, которую я хочу.

Это все.

Надеюсь, это поможет

person Promise Preston    schedule 30.01.2020