【发布时间】:2017-04-26 23:01:39
【问题描述】:
我正在尝试学习如何在我的 Rails 5 应用中使用 pundit。
我正在尝试遵循本文中的方法。
https://learn.co/lessons/devise_pundit_readme
我正在努力从这种方法中找到有效的结果。具体来说,我尝试使用定义范围的索引中的行是:
<% policy_scope(@user.proposals).each do |prop| %>
正在返回此错误:
undefined method `proposals' for nil:NilClass
我的设置是:
我有用户模型和提案模型。这些关联是:
用户:
has_many :proposals
建议:
belongs_to :user
应用控制器:
include Pundit
提案控制器:
def index
@proposals = Proposal.all
# @bips = @proposal.bips
authorize @proposals
end
提案政策:
class ProposalPolicy < ApplicationPolicy
class Scope < Scope
def resolve
if user.has_role?(:admin)
scope.all
else
scope.where(:current_state == :draft)
end
end
end
def index?
true
end
提案索引:
<% policy_scope(@user.proposals).each do |prop| %>
<%= prop.title %>
<%= prop.user.full_name %>
<%= prop.created_at %>
<%= link_to 'More', proposal_path(prop) %>
<% end %>
当我尝试这个时,我收到一个错误 - 突出显示我的索引这行的问题:
<% policy_scope(@user.proposals).each do |prop| %>
鉴于这与我链接的文章完全一样,我不知道为什么它不起作用。
错误提示:
undefined method `proposals' for nil:NilClass
我链接的文章和 Pundit 文档之间的主要区别在于 Pundit 自述文件说:
-
关于 Scope 类 - 自述文件只有:
类作用域
即它没有额外的“ 自述文件在 Post Policy 中有这个(我在我的应用程序策略中有它 - 但也尝试将它添加到 Proposal Policy 中): attr_reader :user, :scope 自述文件在 Post Policy 中有这个(我在我的应用程序策略中有它 - 但也尝试将它添加到 Proposal Policy 中): def 初始化(用户,范围)
@user = 用户
@范围 = 范围
结束 我尝试按照权威文档中的自述文件显示的方式进行操作 - 但我收到与尝试阅读文章时相同的错误。 我尝试更改解析方法,使其始终返回 scope.all: 但我仍然遇到同样的错误。 谁能看到我需要做什么才能使用 Pundit 范围? 回顾我今年早些时候的相关问题 - 我可以看到权威人士 gem 上的自述文件和我链接的教程文章似乎都不正确:Rails 4 - Pundit - scoped policy for index 我无法从链接的 SO 帖子中获得任何解决方案 - 但这些答案中的概念比 gem 自述文件和教程更全面。 下一次尝试 权威发现用户的方式有些可疑。 我将解析方法更改为非常简单的方法 - 检查用户的名字值是否等于字符串(这是我的用户表中我登录的用户的名字的记录): 当我尝试这个时,我收到一条错误消息: 我认为专家不知道如何找到用户。 当我在我的提案索引操作中添加一个 byebug 时,我得到: 所以 - 我试图让权威人士识别用户的方式有问题。我梳理了 GitHub 上的数百个存储库,试图找到人们如何让它工作的示例。我找不到与我在链接帖子中尝试的所有选项不同的地方。 我不确定这是否奇怪,但我可以做到: user_id 43 有一个 first_name 属性,它是 Jane。我认为这可能表明某些东西正在运行,但是当我将解析方法更改为请求“John”而不是“Jane”时,我得到了相同的结果: 显然,这次不正确,因为该提案所属的用户的名字不是 John。 谁能看到我需要做什么才能让 Pundit 识别用户?
def resolve
if user.has_role?(:admin)
scope.all
else
scope.all
end
class ProposalPolicy < ApplicationPolicy
class Scope #< Scope
# class Scope
attr_reader :user, :scope
def initialize(user, scope)
user = user
scope = scope
end
def resolve
if user.first_name == "Jane"
scope.all
else
scope.where(:current_state == :draft)
end
end
end
undefined method `first_name' for nil:NilClass
user.inspect
*** NameError Exception: undefined local variable or method `user' for #<ProposalsController:0x007fa3e8cf8698>
(byebug) @user
nil
(byebug) current_user
#<User id: 43, first_name: "Jane",
(byebug) policy_scope(Proposal)
Proposal Load (0.4ms) SELECT "proposals".* FROM "proposals"
#<ActiveRecord::Relation [#<Proposal id: 17, user_id: 43, title: "asdf", description: "adsf", byline: "asdf", nda_required: true, created_at: "2016-11-16 00:28:31", updated_at: "2016-11-28 01:16:47", trl_id: 1>]>
(byebug) policy_scope(Proposal)
Proposal Load (0.8ms) SELECT "proposals".* FROM "proposals"
#<ActiveRecord::Relation [#<Proposal id: 17, user_id: 43, title: "asdf", description: "adsf", byline: "asdf", nda_required: true, created_at: "2016-11-16 00:28:31", updated_at: "2016-11-28 01:16:47", trl_id: 1>]>
【问题讨论】:
-
undefined method 'proposals' for nil:NilClass表示用户是nil,你能raise user.inspect并显示输出吗 -
在
policy的index上,在控制器中定义之前如何获得@user?要么在此处定义它,要么如果您使用过任何身份验证 gem,例如 devise,请尝试使用current_user而不是@user。 -
我不确定你的意思。 user 是传递给应用程序策略中范围方法的两个属性之一。
-
@MihalkoFarhat: user.inspect NameError: undefined local variable or method `user' for main:Object
-
@Mel 他的意思是您的策略对象中有
@uservar,但视图中没有它。你必须先在控制器动作中初始化它,或者使用一些辅助方法,比如current_user
标签: ruby-on-rails ruby authorization pundit scopes