3

在我的一个项目中,我开始使用 pundit gem,我有一个非常简单的策略,如下所示:

class CompanyPolicy < ApplicationPolicy
  def index?
    true if user.is_a? Administrator
  end

  def new?
    true if user.is_a? Administrator
  end

  def create?
    new?
  end

  def edit?
    true if user.is_a? Administrator
  end

  def update?
    edit?
  end
end

问题是我怎样才能避免重复这一点:

true if user.is_a? Administrator
4

4 回答 4

6

我做的伎俩看起来像这样:

class ApplicationPolicy

  private

  def self.permit_owner_to(*actions)
    actions.each do |action|
      define_method("#{action}?") do
        owner?
      end
    end
  end

  def owner?
    # owner logic
  end

end

并将其用于其他政策

class ItemPolicy < ApplicationPolicy

  permit_owner_to :show, :update, :destroy, :confirm

end
于 2015-02-16T12:15:02.853 回答
2

我实际上认为您不需要删除它。通过重复这一点,您明确表示此用户必须是管理员才能访问此方法。如果您确实想要,您可以创建一个私有方法。

class CompanyPolicy < ApplicationPolicy
  def index?
    admin?
  end

  def new?
    admin?
  end

  def create?
    new?
  end

  def edit?
    admin?
  end

  def update?
    edit?
  end

  private 
     def admin?
        user.is_a? Administrator
     end
end

猜猜这是个人喜好问题。

于 2015-02-16T09:37:42.713 回答
1

你可以使用alias_method.

class CompanyPolicy < ApplicationPolicy
  def index?
    user.is_a? Administrator
  end

  alias_method :create?, :index?
  alias_method :update?, :index?
end

您有一个ApplicationPolicy可能已经包含的基类:

def new?
  create?
end

def edit?
  update?
end

所以你不需要在你的子类中重复这些方法。

.is_a?返回true左右false不需要显式返回true if true

这样简洁很多吧?:)

于 2015-11-20T03:05:41.203 回答
0

我结合了上面的答案,得出了以下结论:

class ApplicationPolicy
  attr_reader :user

  def initialize(user)
    @user = user
  end

  def self.permit(roles, options)
    return if options[:to].none?

    options[:to].each do |action|
      define_method("#{action}?") do
        return @user.roles? Array.wrap(roles) if options[:when].blank?

        send(options[:when]) and @user.roles? Array.wrap(roles)
      end
    end
  end
end

这允许人们像这样使用它:

class CommentPolicy < ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @record = record
    super(user)
  end

  permit %i[admin member], to: %i[show edit destroy update], when: :created_by_user

  def created_by_user
    @record.user == @user
  end
end

permit :admin, to: %i[index update edit]

也可以

我的模型中的角色方法user如下所示:

def roles?(user_roles)
    user_roles.each do |role|
      return true if role?(role)
    end
    false
  end

  def role?(role)
    roles.any? { |r| r.name.underscore.to_sym == role }
  end
于 2021-12-08T11:36:29.997 回答