首页 > 解决方案 > CanCanCan 拒绝为 :create 加载集合

问题描述

在我的PromoCodesController我有这个代码:

load_and_authorize_resource :restaurant, find_by: :permalink
load_resource :discount, through: :restaurant
load_resource :promo_code, collection: [:create], through: :discount

它应该很好#index,因为它会加载集合@promo_codes并在#create其中加载@promo_code

但它不会将集合加载@promo_codes#create. 问题出在哪里?在文档中它说:

:collection 参数:指定除了 :index 之外哪些动作是资源收集动作。

谢谢

标签: ruby-on-railscancancancancan

解决方案


它不起作用,因为 Cancancan 的方法load_resource( controller_resource_loader.rb ) 假定一次只设置一个资源变量:要么resource_instance要么collection_instance

您可以通过猴子补丁load_resource collection: [:create]加载@promo_codes到:#createCanCan::ControllerResourceLoader

# config/initializers/cancan.rb
 
module CanCan
  module ControllerResourceLoader
    def load_resource
      return if skip?(:load)

      # Original condition has been split into two separate conditions

      if load_instance?
        self.resource_instance ||= load_resource_instance
      end

      if load_collection?
        self.collection_instance ||= load_collection
      end
    end
  end
end

此补丁的常见工作方式是集成到索引操作中的创建表单:

class TicketsController < ActionController::Base
  load_and_authorize_resource collection: [:create]

  def index
    @ticket = Ticket.new    
  end

  def create
    if @ticket.valid?
      @ticket.create_for_user! params[:message]
      redirect_to ticket_path(@ticket)
    else
      # @tickets are also defined here
      render :index
    end
  end
end

推荐阅读