Определение правильного объёма соединений для Pundit - PullRequest
0 голосов
/ 16 октября 2019

В настоящее время я внедряю pundit, где пытаюсь определить, есть ли у пользователя роль администратора.

Выпуск

Я пытаюсь избежать создания join_table между скидками и пользователями, используя взаимосвязь между

  • скидками и привлечением(скидка принадлежит аттракциону)
  • аттракционы и парк (парк имеет_ множество аттракционов)
  • парки и пользователи (отношения многие ко многим, через join_table).

-> Однако я получаю сообщение об ошибке: undefined local variable or method `attraction' for #<DiscountPolicy::Scope:0x00007fa012ec6b70>

Вопрос

Мне было интересно:

  1. если даже возможно, что я пытаюсь сделать, и если да
  2. как я смогу получить доступ к пользователю?

код

контроллер скидок

def index
    @user = current_user
    if params[:attraction_id]
      @attraction = Attraction.find(params[:attraction_id])
      @discounts = @attraction.discounts
      @discounts = policy_scope(@discounts)
    else
      @discounts = []
    end
end

политика скидок

class DiscountPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      if user.admin?
        # scope.where(user: user)
        scope.joins(attraction: :discounts).where(discounts: { attraction_id: attraction.id }).joins(park: :attractions).where(attractions: { park_id: park.id }).joins(park: :user_parks).where(user_parks: { user_id: user.id })
      else
        raise Pundit::NotAuthorizedError
      end
    end
  end

  def index?
    user.admin?
  end
end

модели

class Discount < ApplicationRecord
  belongs_to :attraction
  has_many :reservations
end

class Attraction < ApplicationRecord
  belongs_to :park
  has_many :discounts, dependent: :destroy
  accepts_nested_attributes_for :discounts, allow_destroy: true
end

class Park < ApplicationRecord
  has_many :attractions, dependent: :destroy
  has_many :discounts, through: :attractions
  has_many :user_parks, dependent: :destroy
  has_many :users, through: :user_parks
  accepts_nested_attributes_for :users, allow_destroy: true, reject_if: ->(attrs) { attrs['email'].blank? || attrs['role'].blank?}
end

class UserPark < ApplicationRecord
  belongs_to :park
  belongs_to :user
end

class User < ApplicationRecord
  has_many :user_parks, dependent: :destroy
  has_many :parks, through: :user_parks
  enum role: [:owner, :admin, :employee, :accountant]
  after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :admin
  end

  devise :invitable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :invitable
end

1 Ответ

1 голос
/ 16 октября 2019

Вы должны иметь вложенные объединения ассоциаций. Вот как должна выглядеть ваша область:

scope.joins(attraction: [park: :user_parks]).where(user_parks: { user_id: user.id })

Чтобы лучше понять, вы можете просмотреть документацию .

...