Search code examples
cancan

How do you deal with a :create permission in cancan that's defined by the parent object?


Let's say you're writing the software for Blogger.

Each user can create a blog post only if they are the owner of the blog. CanCan would normally define an ability check in this circumstance as:

user.can? :create, Post

However the user can only create the post if they are the owner of the current blog and there's no way to reference the current blog using only its classname. What I really need to be able to do is:

user.can? :create, Post, @current_blog

such that in the cancan definitions I can say

can :create, Post do |post, blog|
  user == blog.owner
end

Is that possible or am I confused in how I'm approaching this?


Solution

  • Define an ability based on the parent of the current object:

    can :create, Post, :blog => { :user => user }
    

    This will make sure the current user can only create a new Post record for a blog that they are an owner of.

    • uses Post.blog_id to find parent Blog record
    • compares Blog.user_id field to current_user.id field

    Also make sure that you are using a :through declaration when loading and authorizing your Post resource, so CanCan knows who the parent record is.

    PostsController:
    
    load_and_authorize_resource :through => :blog
    

    See the CanCan wiki on GitHub for more detail.