狂欢订购CanCan

时间:2012-12-12 15:16:05

标签: ruby-on-rails ruby-on-rails-3 cancan spree

我正在尝试使用cancan修改spree的管理/订单网站。在我的商店,产品从不同的供应商处销售。注册用户拥有vendor_id,产品也有vendor_id。下订单后,订单中的LineItem会有Product,因此会有vendor_id

我想要实现的是,当用户登录并访问管理面板中的订单页面时,他只能看到订购产品的订单。用户不应该看到其他供应商/用户的其他订单。

我试图通过设置一些能力来实现这一点:

  def initialize(user)
    if user.has_spree_role?("shop_manager") && !user.vendor.nil?
      can :admin, Spree::Order
      can :index, Spree::Order, :line_items => { :product => { :vendor_id => user.vendor_id } }
      can :show, Spree::Order, :line_items => { :product => { :vendor_id => user.vendor_id } }
      can :manage, Spree::LineItem, :product => { :vendor_id => user.vendor_id }
      can :read, Spree::Order
    end
  end

正如您所看到的,用户应该只在:line_items => { :product => { :vendor_id => user.vendor_id } }的索引页面上看到订单,并且只能看到LineItems :product => { :vendor_id => user.vendor_id }的位置。

但我得到的行为是,我无权查看订单的索引页面,并且每个LineItem都会显示在订单的show动作中。

对于第二项任务,我认为修改视图是个好主意。我尝试从spree核心更改_order_details.html.erb并更改了显示所有LineItems的循环:

<% @order.line_items.accessible_by(@current_ability).each do |item| %>

但这给了我一个Uninitialized constant Product(我认为它应该是Spree::Product)。所以,我不知道该怎么做,索引也不知道LineItems的show动作。希望有人有个主意。

2 个答案:

答案 0 :(得分:1)

为什么你同时设置限制:read,:show和:index?

:读取假设:index和:show以及任何别名方法。

然后,如果您传递相关条件,则必须:join或:include it。

def initialize(user)
  if user.has_spree_role?("shop_manager") && !user.vendor.nil?
    can :admin, Spree::Order
    can :read, Spree::Order, Spree::Order.includes(:line_items).where(:line_items => { :product => { :vendor_id => user.vendor_id } })
    can :manage, Spree::LineItem, Spree::LineItem.includes(:product).where(:product => { :vendor_id => user.vendor_id })
  end
end

对于第二个问题,再试一次,但如果你在控制器中的ActionView运行时之前的任何地方收集记录会好得多。无论如何它会快得多。

更新

def initialize(user)
  if user.has_spree_role?("shop_manager") && !user.vendor.nil?
    can :admin, Spree::Order
    can :read, Spree::Order, Spree::Order.includes(:line_items).where(:line_items => { :product => { :vendor_id => user.vendor_id } }) do |order|
      order.line_items.includes(:product).exists?(:vendor_id => user.vendor_id)
    end
    can :manage, Spree::LineItem, Spree::LineItem.includes(:product).where(:product => { :vendor_id => user.vendor_id })
  end
end

什么通过该块。当你定义:read时,第一个AR :: Relation语句过滤:index(列表),而block子句过滤:show并赋予你用户能否的能力?不能吗?。

答案 1 :(得分:1)

要解析Uninitialized constant Product issue,您需要在过滤前在:classload_resource中添加load_and_authorized_resource选项:

https://github.com/ryanb/cancan/wiki/authorizing-controller-actions