I've found a way a little DRYer, by using the inheritance of ApplicationPolicy. I alias access methods and I tie a superuser test before invoking any of them. If user is a super user, I simply return true. I do that at initialization before I need the instance method to be defined to be aliased.
ALIAS_PREFIX = '__original_'
def initialize(user, record)
@user = user
@record = record
[:index?,:show?,:create?,:new?, :update?, :edit?, :destroy?].each do |access_method|
alias_name = ALIAS_PREFIX+access_method.to_s
aliasing_original_method(access_method,alias_name)
self.class.send(:define_method, access_method) do |*args|
superuser? ? (return true) : send(alias_name, *args)
end
end
end
private
def superuser?
#whatever you want to define a super user
end
def aliasing_original_method(old_name, new_name)
self.class.send(:alias_method, new_name, old_name)
self.class.send(:private, new_name)
end
And in [AnyFile]Policy I do:
def initialize(user, record)
super(user, record)
end
This will ensure the true return for each method in sub-policy.
[UPDATE]
The first solution is a little messy, and my knowledge in ruby (and deadlines) doesn't permit me to push it farther. Anyway, I've found another way. As I was always switch-casing the roles of users, I've implemented in ApplicationPolicy a for_roles method.
def for_roles(*args,&block)
return true if superuser?
if args.include?(:all) || (@user.role_symbols & args).any?
block.call
else false
end
end
Then, in any policy, you can do for example
for_roles(:client_admin,:technician) do
#any rule computation, DB request you want
end
#or
for_roles(:all) do
#any rule computation, DB request you want
end