Search code examples
ruby-on-railsruby-on-rails-4cancan

Situationally specific cancan roles


:user has_many :books
:book belongs_to :user
:book has_many :contributions
:user has_many :contributions
:contribution belongs_to :book
:contribution belongs_to :user

I want to be able to control behaviour in /books/show depending on whether the user is a contributor to the book. In cancan I'm aiming to have something like -

can :contribute, Book if @book.contributions.include?(user_id)

That line of code is wrong, (undefined method `contributions' for nil:NilClass) but is there a right way of putting it, or am I trying to cram to much into this?


Solution

  • When defining abilities you should be using hash of conditions or block of code. In your case this should work:

    can :contribute, Book do |book|
      book.contributions.include?(user_id)
    end
    

    Then when you define your authorisation in controller or view, like stated in readme, you can pass @book variable which will be passed to block in you ability definition like:

    authorize! :contribute, @book
    

    or

    <% if can? :contribute, @book %>