How to Handle CanCanCan Ability with Multiple Modules in an App?

This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.

Message originally sent by slack user U71TN2WF04X

Hello! I came to a problem that I am not sure how to solve and I figured someone here has probably thought about it.
How are you handling the CanCanCan Ability? In the app I am working there are several modules, so under app/models/ability/ we have many files that define permissions according to the module, and then are prepended to the main ability at app/models/ability.rb.

So if I have a packs/A, I’ll have the ability at packs/A/app/models/ability/a.rb and in the main ability.rb:

class Ability
  prepend Ability::A

  # many methods used in all abilities and in the app
end

So this causes a dependency violation on packs/A

I am making a core pack which seems right to add the main ability, but i want each pack to define its abilities and prepend them in the main… This causes a cyclic dependency.
Any thoughts? :thinking_face:

Dependency injection is your friend for these kinds of situations:
• Create an authorization package and give it a public API that has a register method allowing other packages to register their authorization configs (the method will append any registered rules to an enumerable)
• Create a method in your package that returns all the authorizations for that package. I haven’t used cancancan in a while, so I am not sure whether you have to prevent immediate execution: If so, define these things as procs.
• In your package, create an initializer that connects the two: [Rails.application.config.to](http://Rails.application.config.to)_prepare { YourPackage::Authorizations.register! }

Message originally sent by slack user U71TN2WF04X

Awesome, thanks Stephan. It turned out to be quite easy.
I have a core pack where I have my Ability class defined, so inside I created public/ability_api.rb in which I created a method that basically prepends a module into Ability.
Then on the other packs I created a config/initializers/inject_ability which calls the method for the ability of the pack. The only thing that I don’t like is having multiple initializers doing the same thing with different modules, but still very repetitive

@stephan <@U71TN2WF04X>

When you say, the method will append any registered rules to an enumerable), how are you doing that in code?

Ruby class variables?

module Core
  class Auth
     def self.register(policy)
        @policies << policy
     end
  end
end