Reputation: 617
I'm using CanCanCan in my rails app for authorization. The routes and redirects work fine but I don't manage to display the AccessDenied error message (it worked before but I must have messed something up on the way and now it just won't show).
Here's my code:
controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, error: exception.message
end
...
end
(I changed the default :alert
to :error
as otherwise I was ending up with an alert from devise ('You are already logged in').
views/index.html.haml (root)
= flash[:error] if flash[:error]
...
Any ideas on how to get it to work again? Thanks in advance.
---EDIT---
Some more fixes I tried (without success):
Replacing error
with message
and notice
Removing the rescue_from CanCan::AccessDenied
method completely - it brought me to the standard CanCan error page (so I know the method itself is working).
Replacing the exception.message
with a regular string.
Adding a puts statement before redirection - it gets printed in the console as one would expect.
As @Anand Shah suggest in an answer to this question, I added the following in my view:
- if flash[:error].blank?
%p flash hash is blank
The hash was indeed empty, so it seems like the flash is not being saved at all. Then I added
flash.keep(:error)
in my controller but that didn't change anything.
Upvotes: 1
Views: 1470
Reputation: 617
The reason for this issue turned out to be my routes.rb
. In addition to defining the root for devise scope:
devise_scope :user do
root to: "devise/sessions#new"
end
authenticated :user do
root 'application#show', as: :authenticated_root
end
I also had an extra root defined (which basically caused double redirection and therefore loss of the alert):
root to: 'application#show'
The code from the documentation works just fine after the necessary modification (note I could bring it back from error
to alert
without breaking things):
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, alert: exception.message
end
Upvotes: 1
Reputation: 29318
Have you tried not handling this inline but rather something like:
rescue_from CanCan::AccessDenied do |exception|
flash[:error] = exception.message
redirect_to root_url
end
The reason it was working before is Rails understands :alert
and :notice
as flash messages during the redirect_to
otherwise you should use the "general purpose flash
bucket" as they call it via flash: {error: 'your message'}
However the Hash
passed to redirect_to
can also contain the http status code (:status
) and url query parameters (anything that is not :alert
, :notice
, :status
, or :flash
and it all just seems like too much noise (IMO) to put a flash message in there to save 1 line of explicit code.
Upvotes: 0
Reputation: 424
Have you tried it through a private browser in case the cookies have messed up?
Can you try this format?
redirect_to(root_url, {:flash => { :error => exception.message }})
Upvotes: 0