Pundit 提出了一个错误,否则我不会有
Pundit raises an error, which I wouldn't have otherwise
我遇到了我没想到的专家回应,我想知道是否有人可以告诉我发生了什么事。
问题
在我的索引操作中,我想显示公园下方的景点。目前,这导致了以下意外行为(至少对我而言):
- 养博学之前,一个公园的景点都是秀的。这是用 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>]>
- 包括专家后,它会引发错误。这是用 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 })
我遇到了我没想到的专家回应,我想知道是否有人可以告诉我发生了什么事。
问题
在我的索引操作中,我想显示公园下方的景点。目前,这导致了以下意外行为(至少对我而言):
- 养博学之前,一个公园的景点都是秀的。这是用 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>]>
- 包括专家后,它会引发错误。这是用 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 })