Search code examples
ruby-on-railsrubyruby-on-rails-4rubygemscancan

Rails CanCan gem refactoring Ability class


I have a around 13 models in my rails app, I use ability on all of them. My ability class has grown huge. I have different ability conditions on different CRUD actions which is making it hard to manage.

Can someone guide me on how I can refactor this..? Like, using modules or classes for making my ability class look neat.


Solution

  • Simple escenario: If you can split the permissions in several mutually exclusive sets, then you should check this proposal from @ryanb, CanCan creator, in which he splits the abilities into several different classes and then overwrites the current_ability method in the ApplicationController

    How you can break up large Ability class in CanCan - Gists

    More complex scenario: if you have several different overlapping permissions sets, you can try this approach:

    # app/models/ability.rb
    
    class Ability
      include CanCan::Ability
    
      def initialize(user)
        self.merge Abilities::Everyone.new(user)
    
        if user
          self.merge Abilities::Admin.new(user) if user.admin?
          self.merge Abilities::Authenticated.new(user)
        else
          self.merge Abilities::Guest.new(user)
        end
      end
    end
    
    # app/models/abilities/admin.rb
    module Abilities
      class Admin
        include CanCan::Ability
    
        def initialize(user)
          # define abilities here ...
        end
      end
    end
    
    # app/models/abilities/everyone.rb
    ...
    

    And so on for the rest of the files.