我正在尝试使用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动作。希望有人有个主意。
答案 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
,您需要在过滤前在:class
或load_resource
中添加load_and_authorized_resource
选项:
https://github.com/ryanb/cancan/wiki/authorizing-controller-actions