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