nope2023
nope2023

Reputation: 1788

Render and/or redirect called multiple times in action

I'm using Devise and Pundit. To create a new profile page, the user has to be authorized to do so. This has been working fine since I first implemented it, but today it just started acting up with an error message:

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

Here's my code from my Application controller:

    rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
    ...

    private

    def user_not_authorized(exception)
        flash[:alert] = "Sorry, you are not authorized to perform this action."
        redirect_to(request.referrer || root_path)
    end

Here's my ProfilePage controller:

def new
  @profile_page = ProfilePage.new
  authorize @profile_page
end

def create
  @profile_page = ProfilePage.new(profile_page_params)
    respond_to do |format|
      if @profile_page.save
        format.html { redirect_to @profile_page, notice: 'Profile page was successfully created.' }
        format.json { render :show, status: :created, location: @profile_page }
      else
        format.html { render :new }
        format.json { render json: @profile_page.errors, status: :unprocessable_entity }
      end
    end
    authorize @profile_page
  end

Someone suggested that I add this line of code below flash[:alert]:

self.response_body = nil

But now my user is redirected to the 'new profile' page again, rather than the successful profile page. It also tells the user that they are not authorized to complete this action, despite the fact that it HAS authorized them to do so.

Upvotes: 2

Views: 4278

Answers (1)

mtkcs
mtkcs

Reputation: 1716

In the create action you have to put the authorization logic before saving the record:

You have to move

authorize @profile_page

at the top of your create action, after initializing the @profile_page, like so:

def create
  @profile_page = ProfilePage.new(profile_page_params)
    authorize @profile_page

    respond_to do |format|
      if @profile_page.save
        format.html { redirect_to @profile_page, notice: 'Profile page was successfully created.' }
        format.json { render :show, status: :created, location: @profile_page }
      else
        format.html { render :new }
        format.json { render json: @profile_page.errors, status: :unprocessable_entity }
      end
    end
end

Upvotes: 4

Related Questions