Кажется, я звоню authorize @artist
слишком много раз в artists_controller.rb
Честно говоря, я думаю, что у вас там все в порядке.
Есть несколько способов, которыми вы могли бы попытаться быть умными в этом и "автоматически вызывать authorize
" для каждого действия контроллера, но (предупреждение: основанный на мнении ответ) из прошлогоОпыт, который я обнаружил, что такие попытки сделать его более СУХИМ добавляет значительную путаницу.Особенно когда вы заканчиваете тем, что пишете некоторые действия контроллера, которые не нуждаются в авторизации или требуют авторизации необычным способом.
В моем artist_policy.rb
много дублирования кода
Один шаг за раз ... Вот оригинал:
class ArtistPolicy < ApplicationPolicy
attr_reader :user, :artist
def initialize(user, artist)
@user = user
@artist = artist
end
def create?
if user.admin? || user.moderator? || user.contributor?
true
elsif user.banned?
false
end
end
def update?
if user.admin? || user.moderator? || user.contributor? && user.id == @artist.user_id
true
elsif user.banned?
false
end
end
def destroy?
if user.admin? || user.moderator? || user.contributor? && user.id == @artist.user_id
true
elsif user.banned?
false
end
end
end
Нет необходимости определять свой собственный метод initialize
таким образом, если вы будете рады ссылаться на болееуниверсальное имя переменной: record
вместо artist
(которое должно быть определено в ApplicationPolicy
):
class ArtistPolicy < ApplicationPolicy
def create?
if user.admin? || user.moderator? || user.contributor?
true
elsif user.banned?
false
end
end
def update?
if user.admin? || user.moderator? || user.contributor? && user.id == record.user_id
true
elsif user.banned?
false
end
end
def destroy?
if user.admin? || user.moderator? || user.contributor? && user.id == record.user_id
true
elsif user.banned?
false
end
end
end
Далее, в подобных ситуациях хорошо ссылаться на одно правило политики из другого- при условии, что они в равной степени относятся к типам пользователей:
class ArtistPolicy < ApplicationPolicy
def create?
if user.admin? || user.moderator? || user.contributor?
true
elsif user.banned?
false
end
end
def update?
if user.admin? || user.moderator? || user.contributor? && user.id == record.user_id
true
elsif user.banned?
false
end
end
def destroy?
update?
end
end
Далее, обратите внимание, что record.user_id
- это зарегистрированный пользователь для действия create!Таким образом, вы можете упростить это еще больше:
class ArtistPolicy < ApplicationPolicy
def create?
if user.admin? || user.moderator? || user.contributor? && user.id == record.user_id
true
elsif user.banned?
false
end
end
def update?
create?
end
def destroy?
create?
end
end
И, наконец, логика в этом методе на самом деле немного неправильна.(Вы могли бы поднять это с помощью тестов ...) Если пользователь является администратором , а они забанены, то вы все еще, вероятно, хотите, чтобы это вернуло false
, а не true
.Имея это в виду, мы можем исправить + снова упростить код до:
class ArtistPolicy < ApplicationPolicy
def create?
return false if user.banned?
user.admin? || user.moderator? || user.contributor? && user.id == record.user_id
end
def update?
create?
end
def destroy?
create?
end
end