Для (на самом деле) минимального раздражения, которое возникает из-за повторного ввода имени метода пару десятков раз в течение жизни проекта, я думаю, что, возможно, не столь очевидная выгода того стоит.
Во-первых, вы можете сэкономить несколько нажатий клавиш, определив метод super?
на вашем ApplicationPolicy
def super?
user.is_super_admin?
end
И тогда ваш delete?
и другие методы можно было бы немного упростить.
def delete?
super? || user.id == record.user_id # super admin or owner of the resource
end
Политика Pandit достаточно проста. Если я никогда раньше не работал в вашем коде, я могу посмотреть на приведенный выше метод и точно знать, кто может выполнить удаление.
Конечно, это может сэкономить вам пару нажатий клавиш, чтобы иметь некоторые метапрограммированные функции для автоматического вызова super?
, при этом delete?
отображается как
def delete?
user.id == record.user_id # super admin or owner of the resource
end
но теперь ясность потеряна. Кроме того, что, если в будущем появится метод, к которому вы не хотите предоставлять доступ суперадминистратору? Переработка вашего уже более сложного решения сделает его еще более подверженным ошибкам и более трудным для понимания. Таким образом, можно сэкономить ~10 нажатий клавиш на метод.
Обновлять
Помимо мнений о читабельности кода, вот одна реализация, которая делает то, что вам, кажется, нужно. Вы также можете изучить перехват вызовов метода вместо удаления ?
из имен методов, как я сделал ниже, чтобы убедиться, что method_missing
подбирает их.
#
# 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
person
deefour
schedule
08.05.2015