2

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.

nope2023
  • 1,668
  • 1
  • 15
  • 28
  • Like the error message suggested if you have multiple `render` / `redirect_to` per `action` you have to use an early `return`, like `return redirect_to some_path`. The problem here is in the code you are showing, I can't see any mistake. – mtkcs Jan 22 '16 at 08:33
  • I've added the code from ProfilePage controller. Where would I put an early return? – nope2023 Jan 22 '16 at 08:41
  • Where the error occurs? `new` or `create` `action` – mtkcs Jan 22 '16 at 08:47
  • in the create action – nope2023 Jan 22 '16 at 08:49

1 Answers1

4

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
mtkcs
  • 1,696
  • 14
  • 27
  • Works! Ah, I must have moved it at some point without realising and that's why it suddenly stopped working. Cheers! – nope2023 Jan 22 '16 at 08:57