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?
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! }
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