Pundit 提出了一个错误,否则我不会有

Pundit raises an error, which I wouldn't have otherwise

我遇到了我没想到的专家回应,我想知道是否有人可以告诉我发生了什么事。

问题

在我的索引操作中,我想显示公园下方的景点。目前,这导致了以下意外行为(至少对我而言):

  1. 养博学之前,一个公园的景点都是秀的。这是用 1 测试的。停止应用程序的文本

--> 结果 >> @attractions => #<ActiveRecord::Associations::CollectionProxy [#<Attraction id: 185, park_id: 109, name: "Spider", description: "", status: nil, persons_max: 4, persons_min: 4, persons_included: 4, attraction_count: 4, enabled_attraction_count: nil, thumb: nil, included_services: nil, created_at: "2019-10-10 11:00:07", updated_at: "2019-10-12 07:31:27", photo: nil>, #<Attraction id: 189, park_id: 109, name: "Throwing balls at cans", description: nil, status: nil, persons_max: 1, persons_min: 1, persons_included: 1, attraction_count: 1, enabled_attraction_count: nil, thumb: nil, included_services: nil, created_at: "2019-10-15 14:29:28", updated_at: "2019-10-15 14:29:28", photo: nil>]>

  1. 包括专家后,它会引发错误。这是用 2 测试的。停止应用程序的文本

--> 结果 >> @attractions ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column attractions.user does not exist LINE 1: ...ERE "attractions"."park_id" = AND "attracti... ^ : SELECT "attractions".* FROM "attractions" WHERE "attractions"."park_id" = AND "attractions"."user" = LIMIT from /Users/xx/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:677:in `prepare' from /Users/xx/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:677:in `block in prepare_statement'[]

我做错了什么,我怎样才能确保在专家之后只显示公园的景点?

代码 景点管理员

  def index
    @user = current_user
    if params[:park_id]
      @park = @user.parks.find(params[:park_id])
      @attractions = @park.attractions

      1. text to stop app

      @attractions = policy_scope(@attractions)

      2. text to stop app
    end
  end

policies/attraction_policy.rb

class AttractionPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      if user.admin?
        scope.where(user: user)
      else
        raise Pundit::NotAuthorizedError
      end
    end
  end

  def index?
    user.admin?
  end
end

型号

class Attraction < ApplicationRecord
  belongs_to :park
end

class Park < ApplicationRecord
  has_many :attractions, dependent: :destroy
  has_many :user_parks, dependent: :destroy
  has_many :users, through: :user_parks
end

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  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

class UserPark < ApplicationRecord
  belongs_to :park
  belongs_to :user
end

您尝试通过 user 来限定 Attraction 的范围:

scope.where(user: user)

但是您的 attractions table 中既没有 user 也没有 user_id 列,所以这显然行不通。如果你想在attraction模型上设置user关联,你需要做:

rails g migration add_user_id_to_attractions user:references

并添加

belongs_to :user

Attraction 型号。

如果你想坚持你的间接关联,你也可以通过稍微修改你的范围来实现你的目标,使用 joins:

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

您没有与用户的直接关联,因此您当前的范围将不起作用。

相反,您可以修改范围:

scope.joins(park: :users).where(users: {id: user.id })