Как использовать области челюсти?

Я только что перешел на Pundit из CanCan. Я не уверен в парочке вещей и о том, как лучше всего использовать Пандит. Например.

Если у вас есть ресурс, который может иметь несколько родительских объектов, например, можно сказать, что цель принадлежит ученику и преподавателю. Поэтому у ученика может быть много голов, и у инструктора может быть много целей. В действии указателя контроллера вы можете:

if params[:student_id].present?
  @account = Student.find(params[:student_id])
  @goals = @account.goals
elsif params[:instructor_id].present?
  @account Instructor.find(params[:instructor_id])
  @goals = @account.goals
end

параметры не используются внутри политик, поэтому здесь нужно сделать логику. Я думаю. Для того, что я могу сказать, если вы пропустите policy_scope, вы получите несанкционированную ошибку при просмотре страницы индекса для целей.

Вы:

@goals = policy_scope(@account.goals)

ИЛИ

@goals = policy_scope(Goal.scoped).where( account_id: @account.id)

Что происходит, когда вы бросаете кучу включений в микс?

  @example = policy_scoped(@school.courses.includes(:account => :user, :teacher ))

Или когда нужно заказать... это правильно?    policy_scope (Issue.scoped).order( "created_at desc" )

При использовании областей: Что такое: область здесь? Является ли: scope экземпляр модели оценивается? Я попытался получить доступ к своим атрибутам через: scope, но не работал.

  class Scope < Struct.new(:user, :scope)

Ответ 1

Прочитав это с точки зрения безопасности, я вижу пару вещей, которые упоминаются. Например, если вы разрешаете пользователям указывать поля параметров student_id и instructor_id, что мешает им переходить в идентификатор для кого-то, кроме себя? Вы никогда не хотите, чтобы пользователь указывал, кто они, особенно когда вы основываете политики на типе пользователей.

Для начала я бы выполнил Devise и добавил дополнительное логическое поле под названием instructor, которое было бы true, когда пользователь был инструктором, но по умолчанию для false для студентов.

Тогда ваш User будет автоматически иметь метод instructor?, который будет возвращать true, если значение в столбце instructor равно true.

Затем вы можете добавить помощника для студентов:

def student?
  !instructor?
end

Теперь, используя Devise (который дает нам доступ к переменной current_user), мы можем делать такие вещи, как current_user.instructor?, который вернет true, если они являются инструкторами.

Теперь о самой политике. Я только начал использовать Pundit несколько недель назад, но это то, что я сделал бы в вашей ситуации:

class GoalPolicy < ApplicationPolicy
  class Scope < GoalPolicy
    attr_reader :user, :scope

    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve
      @scope.where(user: @user)
    end
  end
end

Тогда ваш метод (я предполагаю GoalsController и метод index) может выглядеть так:

def index
  policy_scope(Goal) # To answer your question, Goal is the scope
end

Если вы хотите заказать, вы также можете сделать

def index
  policy_scope(Goal).order(:created_at)
end

Я только понял, что вы задали этот вопрос полгода назад, но эй! Возможно, он ответит на некоторые вопросы, которые есть у других людей, и, возможно, я получу некоторые отзывы о моих собственных начинающих навыках Pundit.