Rails: DoubleRenderError - "Render and/or redirect were called multiple times in this action"
Asked Answered
V

3

8

I want to redirect by the role_ids of the user:

  • If it's equal to 2, redirect to workers_path.
  • if it's equal to 1, redirect to tasksadmins_path.

I defined the next things:

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

but when I sign in, I got errors:

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"}

This is my 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

and this is my 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
Vomiturition answered 3/2, 2013 at 8:7 Comment(0)
V
1

I added to 'create' the next lines:

in the beginning, I wrote:

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

and then I wrote in the end of the 'create' function:

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

so my create looks so:

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
Vomiturition answered 3/2, 2013 at 11:51 Comment(0)
A
19

You shouldn't return redirect_to in the after_sign_in_path_for. You should return url:

  def after_sign_in_path_for(user)
     if current_user.role_ids == [2]
       return workers_url
     else
       return tasksadmins_url
     end
  end
Acosmism answered 3/2, 2013 at 8:44 Comment(5)
@MikhalNikalyukin, I tried what you suggested and it redirects me to: localhost:3333/users/sign_inVomiturition
should always redirect to _url and not just _path; also the page you are redirecting is probably requiring authentication that you don't have, which then redirects back to signin page.Quirk
@PeppyHeppy, thank you but I have the requiring authentication. I tried to print the 'current_user.role_ids' in the first line of the function 'after_sign_in_path_for' and it prints '2'. in addition, just the application controller requires authentication (before_filter :authenticate_user!)Vomiturition
@AlonShmiel, its possible that you are comparing [2] == 2 and its false because its comparing an array with an integer. BTW, I would add methods to the user model like current_user.super_admin? and avoid using role ids in your app.Quirk
thank you again.. it worked me in the past, when I used: "rescue_from CanCan::AccessDenied do |exception|" and then checked the role_ids (so there is no a problem of Integer). these lines stopped working when I used the function: "after_sign_in_path_for" instead of "rescue_from CanCan::AccessDenied do |exception|". about your second suggestion, I prefer to stay using role_ids. thank you for your comments.Vomiturition
V
1

I added to 'create' the next lines:

in the beginning, I wrote:

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

and then I wrote in the end of the 'create' function:

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

so my create looks so:

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
Vomiturition answered 3/2, 2013 at 11:51 Comment(0)
H
0

I faced this issue while using devise gem for my admin account management, but mine was on a production server.

AbstractController::DoubleRenderError (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".):

The issue was that I wanted to sign_in into the admin dashboard, rather than entering the admin_dashboard URL into the browser, I put in the admin_sign_in URL in the browser, meanwhile, an admin account was already logged in. So when I tried to sign in it didn't work, because I can't sign-in 2 accounts at the same time to the admin dashboard.

Here's how I solved it:

  1. Enter the URL for the admin dashboard into the browser, which signed me into the previous account
  2. Log out from the account on the admin dashboard
  3. And then sign-in to the admin dashboard using the account that I want.

That's all.

I hope this helps

Hamburg answered 30/1, 2020 at 14:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.