我的 Ruby on Rails 应用程序遇到以下情况:
我有一个包含帖子的博客。每个帖子可以有 1 到 n 作者,并且每个帖子都与多个评论相关联:
class Post < ApplicationRecord
has_many :comments, dependent: :destroy
has_many :authors
class Comment < ApplicationRecord
belongs_to :post
我正在使用 CanCanCan 进行授权。目前,每个人都可以对帖子发表评论。我想通过在我的
lock_comments
模型上引入 post
属性并相应地更改授权来更改此设置,使其功能如下:
:create
如果其父帖子上的lock_comments
为假:create
如果其父帖子上的 lock_comments
为假,或者登录用户是该帖子的作者之一基本上,作者应该能够禁用对其文章的评论,但他们仍然应该能够对自己的文章发表评论,即使其他人的评论被禁用。
我在这里有点不知所措,在文档中找不到任何内容。我必须如何定义我的
Ability
才能使其发挥作用?
我认为您无法在“能力”中执行此操作,因为当您尝试访问
create
时,您不知道父帖子是什么。如果 create_comment
是 PostsController
方法,你可以这样做...
can :create_comment, Post do |post|
!post.lock_comments || user.in?(post.authors)
end
但是如果它是
create
中的 CommentsController
,您需要使用 before_action
来完成此操作
class CommentsController < ApplicationController
before_action :create_allowed, only: [:create]
private
def create_allowed
post = Post.find(params[:comment][:post_id])
return if post && (!post.lock_comments || current_user.in?(post.authors))
flash[:error] = 'You are not allowed to do this'
redirect_to root_path
end
end
我们也一直在努力解决如何轻松配置这样的功能,并找到了使用 额外参数 的解决方案,您可以将其与
can
和 can?
函数一起使用。这样您就可以传入可以执行必要检查的父对象。
那么在检查授权时,您的解决方案将变成这样:
can? :create, Comment.new, @post
然后能力配置看起来像这样:
can :create, Comment do |comment, post|
!post.lock_comments || user.in?(post.authors)
end