我有一个User
,Product
和一个Subscription
模型。基本上,订阅是针对特定产品的,产品可以具有多个订阅,并且每个产品属于用户(即,作者)。用户可以是管理员或普通用户。
我的问题是:如果我想让我的普通用户为他们创作的产品创建仅订阅,我将如何使用cancan实现此功能?
这就是我目前的能力.rb。
class Ability
include CanCan::Ability
def initialize(user)
if user
if user.admin?
can :manage, :all
else # not an admin
can :read, User
can :manage, User, id: user.id
cannot :create, User
can :read, Product
can :manage, Product, user: user
can :read, Subscription
# this is sort of what I want, but now nobody can create subscriptions
can :create, Subscription, product: { user: user }
can :manage, Subscription, product: { user: user }
end
else # not a user, just a guest
can :create, User
can :read, User
can :read, Product
can :read, Subscription
end
end
end
我是否完全错了?我应该在控制器中执行此操作还是使用某种验证?
答案 0 :(得分:2)
CanCan是解决您问题的合法解决方案。
当您询问是否应该在控制器中执行此操作时,答案是您应该使用控制器内的CanCan权限来检查是否允许给定用户执行请求的操作。
通常,您可以通过调用控制器中的authorize_resource
来完成此操作,但也可以使用authorize! :create, @subscription
。
此外,您可以通过不向他们提供他们未获得许可的操作的链接来帮助您的用户。
在你看来,你可以这样做:
<% if can? :create, @product.subscriptions.build %>
<%= link_to new_product_subscription_path(@product) %>
<% end %>
除此之外,你的ability.rb文件还有一个小问题。
can :manage, Subscription, product: { user: user }
应该是
can :manage, Subscription, product: { user_id: user.id }
至少就是在CanCan维基页面上记录它的方式。
这是我想要的,但现在没人能创造 订阅。
在尝试授权之前,您是否确定订阅包含product_id?
如果没有product_id,您的订阅授权将失败,因为它依赖于它的产品。
您可以写@product.subscriptions.build
而不是Subscription.new
来确保它有product_id。如果您使用load_and_authorize_resource,请确保使用嵌套变体,如https://github.com/ryanb/cancan/wiki/Nested-Resources所示。