It seems that authorize! only works with one instance, not an array. Here's how I got around this with Rails 3.2.3 and CanCan 1.6.7.
The main idea is to count the total records that the user is trying to delete, count the accessible_by (current_ability, :destroy) records, and then compare the counts.
If you need an array of records that the user is allowed to destroy, you can use the array returned by accessible_by (current_ability, :destroy) . However, I use destroy_all , which works directly on the model, so I ended up with this solution to calculate the quantity and compare.
You should check the development log to see how the two SELECT COUNT look: the second should add WHERE phrases for the authorization restrictions imposed by CanCan.
My example deals with deleting multiple messages.
ability.rb
if user.role_atleast? :standard_user
messages_controller.rb
# Suppress load_and_authorize_resource for actions that need special handling: load_and_authorize_resource :except => :multidestroy # Bypass CanCan ApplicationController#check_authorization requirement: skip_authorization_check :only => :multidestroy ... def multidestroy # Destroy multiple records (selected via check boxes) with one action. @messages = Message.scoped_by_id(params[:message_ids]) # if check box checked to_destroy_count = @messages.size @messages = @messages.accessible_by(current_ability, :destroy) # can? destroy authorized_count = @messages.size if to_destroy_count != authorized_count raise CanCan::AccessDenied.new # rescue should redirect and display message else # user is authorized to destroy all selected records if to_destroy_count > 0 Message.destroy_all :id => params[:message_ids] flash[:success] = "Permanently deleted messages" end redirect_to :back end end
source share