I want to show login form instead of cancan access denied flash message. this is my controller
#app/controllers/oferts_controller.rb
class OfertsController < ApplicationController
before_action :set_ofert, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource :only => [:new, :edit, :destroy]
before_filter :authenticate_user!, :except => [:show, :index]
# GET /oferts
# GET /oferts.json
def index
@oferts = Ofert.areactive
end
# GET /oferts/1
# GET /oferts/1.json
def show
end
# GET /oferts/new
def new
@ofert = current_user.oferts.new
@ofert.purchasing_group = PurchasingGroup.new
end
# GET /oferts/1/edit
def edit
end
# POST /oferts
# POST /oferts.json
def create
....
end
# PATCH/PUT /oferts/1
# PATCH/PUT /oferts/1.json
def update
....
end
# DELETE /oferts/1
# DELETE /oferts/1.json
def destroy
...
end
private
# Use callbacks to share common setup or constraints between actions.
def set_ofert
@ofert = Ofert.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def ofert_params
params.require(:ofert).permit(:title, :short_title, :description, :price, :normal_price, :ends_at, :ends_at_date, :ends_at_time)
end
end
For some reason when I try to access an action that requires login, for example, "create", I only get the access denied message from CanCan, but Im not redirected to the login page as it should, since I have the :authenticate_user! before_filter in the controller.
How can prioritize the devise redirection to login page instead of the cancan access denied flash message?
Thanks
Update: This is my Gemfile
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.9'
# Use mysql as the database for Active Record
gem 'mysql2'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'money-rails', '~> 1.2.0'
gem 'money', '~> 6.5.0'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
gem 'foundation-rails'
gem 'font-awesome-rails', '~>4.3.0.0'
gem 'devise'
gem "cancan"
gem "rolify"
gem "paperclip", "~> 4.2"
gem 'rails-i18n', '~> 4.0.0'
gem 'jquery-ui-rails'
gem 'whenever', :require => false
gem 'jquery-countdown-rails'
# Use unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
group :development do
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'quiet_assets', '~>1.1'
end
group :development, :test do
gem 'rspec-rails', '~> 3.0.0'
gem 'rspec-expectations'
gem 'factory_girl_rails', '~> 4.0'
end
group :test do
gem 'capybara', '~> 2.3.0'
gem 'capybara-email'
gem 'shoulda-matchers', '~> 2.7.0'
gem 'rspec-its'
gem 'rspec-activemodel-mocks', '~> 1.0.1'
end
For the record, here's the conventional and DRY way to do it:
class ApplicationController < ActionController::Base
# ...
rescue_from CanCan::AccessDenied, with: :access_denied
# ...
private
def access_denied(exception)
store_location_for :user, request.path
redirect_to user_signed_in? ? root_path : new_user_session_path, alert: exception.message
end
end
This will store the requested location in a session and render Devise
login form if user is currently not signed in. Stored location will trigger redirect to the requested location after successful sign in.
Placing the code in ApplicationController
will define such behavior globally.
If you don't need this for the every controller, you are free to put rescue_from CanCan::AccessDenied, with: :access_denied
line where you want it, OfertsController
in your case. You'll also need to list access_denied
method as protected
rather than private
.