Proper way to add/include rules to Ability? #730

Closed
naps62 opened this Issue Aug 28, 2012 · 2 comments

Projects

None yet

2 participants

@naps62

I'm developing a set of engines for an app. One of the engines deals with authentication, and uses cancan to define some basic permissions (typical Admin & User roles)

Other engines, which depend on this one, will define new models, and possibly roles, and will need to add some rules to the Ability definition. Is there a way to handle this in cancan (somehow including the new rules in the ability definition), or will i have to just define all roles in the main Authentication engine, even though some of them are internal to that engine?

@mikepack
Collaborator

There's a number of ways to skin this cat. If you're looking for a lightweight solution that doesn't require you to change any CanCan defaults, use plain old Ruby:

Define your Ability class as usual in the Authentication engine:

class Ability
  include CanCan::Ability

  def initialize(user)
    puts 'Definining abilities...'
  end
end

Within your additional engines, reopen the ability class:

class Ability
  alias :old_init_engine_1 :initialize

  def initialize(user)
    old_init_engine_1(user)
    puts 'Defining more abilities...'
  end
end

Make sure to namespace your aliased initializer (eg old_init_engine_1) so that it does not conflict with other engines which also intend to open the Ability class:

class Ability
  alias :old_init_engine_2 :initialize

  def initialize(user)
    old_init_engine_2(user)
    puts 'Defining even more abilities...'
  end
end

This solution might not be a good fit if your additional engines intend to overwrite the abilities defined in your Authentication engine. If the order in which your abilities are defined across engines matters, this could potentially yield incorrect authorization. You could ensure your engines load in a certain order to alleviate this, but be aware.

@naps62

I don't think i will need to overwrite anything. The basic idea is, the authentication engine defines the more general rules, that might be required accross the entire application. Each engine might then need to add additional permissions, but those will be private to the engine itself

So i think this solution should work well. I didn't know about the alias method. Thanks for the quick answer

@naps62 naps62 closed this Aug 28, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment