I have the following situation in my Ruby on Rails application:
I have a blog with posts. Each post can have 1 to n authors, and each post is associated with several comments:
class Post < ApplicationRecord
has_many :comments, dependent: :destroy
has_many :authors
class Comment < ApplicationRecord
belongs_to :post
I am using CanCanCan for authorization. Currently everyone is able to create comments on a post. I want to change this by introducing a lock_comments
-attribute on my post
model, and changing the authorization accordingly, so that it functions as follows:
:create
if lock_comments
on it's parent post is false:create
if lock_comments
on it's parent post is false, OR the logged in user is one of the authors of the postBasically the authors should be able to disable comments on their articles, but they should still be able to write comments on their own articles, even if the comments are disabled for others.
I am a bit at a loss here and could not find anything in the documentation. How do I have to define my Ability
for this to work?
I don't think you can do this in Ability because at the time you're trying to access create
you don't know what the parent post is. You COULD do this if create_comment
was a PostsController
method...
can :create_comment, Post do |post|
!post.lock_comments || user.in?(post.authors)
end
But if it's create
in a CommentsController
you'd need to do this with a 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