看来我在artists_controller.rb 中调用authorize @artist 的次数太多了
老实说,我认为你所拥有的一切都很好。
您可以通过几种方法尝试对此进行巧妙处理,并为每个控制器操作“自动调用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 是登录用户,用于创建操作!因此,您可以进一步简化:
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