For the (in reality) minimal annoyance that comes from retyping a method name a couple dozen times through the life of the project, I think the maybe not-so-obvious benefit is worth it.
First, you could save a few keystrokes by defining a super?
method on your ApplicationPolicy
def super?
user.is_super_admin?
end
And then your delete?
and other methods could be simplified just a bit.
def delete?
super? || user.id == record.user_id # super admin or owner of the resource
end
Pundit policies are simple enough. If I have never worked in your code before, I can look at the above method and know exactly who can perform the deletion.
Sure, it might save you a couple keystrokes to have some meta-programmed functionality to call super?
automagically, with delete?
appearing as
def delete?
user.id == record.user_id # super admin or owner of the resource
end
but now the clarity is lost. Also, what if there is a method down the road you do not want the super admin to have access to? Reworking your already more complicated solution would make things even more prone to bugs and more difficult to understand. All so ~10 keystrokes per method could be saved.
Update
Opinions on code readability aside, here is one implementation that does what you seem to be after. You might also look into hooking the method calls instead of removing the ?
from the method names as I've done below to make sure method_missing
picks them up.
#
# Classes
#
User = Struct.new(:id, :name)
Foo = Struct.new(:id, :title, :user_id)
class SuperUser < User; end
ApplicationPolicy = Struct.new(:user, :record) do
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def method_missing(name)
raise NoMethodError, "No method `#{name}` for #{self}" if (name =~ /\?$/).nil?
user.is_a?(SuperUser) || send(name.to_s.sub(/\?$/, ""))
end
end
class FooPolicy < ApplicationPolicy
private
def edit
user.id == record.user_id
end
end
#
# Fixtures
#
user = User.new(1, "Deefour")
foo = Foo.new(1, "A Sample Foo", 1)
super_user = SuperUser.new(2, "FireDragon")
#
# Examples
#
FooPolicy.new(user, foo).edit? #=> true
FooPolicy.new(super_user, foo).edit? #=> true