Кажется, что authorize!
работает только для одного экземпляра, а не для массива.Вот как я справился с этим с Rails 3.2.3 и CanCan 1.6.7.
Основная идея состоит в том, чтобы подсчитать общее количество записей, которые пользователь пытается удалить, подсчитать записи, которые accessible_by (current_ability, :destroy)
, а затем сравнить их.
Если вы просто хотели получить массив иззаписи, которые пользователь имеет право уничтожать, вы можете использовать массив, возвращаемый accessible_by (current_ability, :destroy)
.Однако я использую destroy_all
, который работает непосредственно с моделью, поэтому я решил использовать это решение для подсчета и сравнения.
Стоит проверить журнал разработки, чтобы увидеть, как два SELECT COUNT
операторы выглядят следующим образом: во втором должны быть добавлены WHERE
фразы для ограничений авторизации, наложенных CanCan.
Мой пример касается удаления нескольких сообщений.
способность.rb
if user.role_atleast? :standard_user
# Delete messages that user owns
can [:destroy, :multidestroy], Message, :owner_id => user.id
end
messages_controller.rb
# Suppress load_and_authorize_resource for actions that need special handling:
load_and_authorize_resource :except => :multidestroy
# Bypass CanCan's 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