我试图学习如何在我的Rails 4应用程序中使用pundit。
我有一个潜在的使用政策。潜在的使用表有一个名为:user_id。
的属性我希望允许用户在创建实例时更新实例。我试图找出如何使更新操作起作用。
我目前的尝试如下所示。
class PotentialUsePolicy < ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
true if user.is_admin?
end
def show?
true
end
def new?
true
end
def create?
new?
end
def update?
if @user.id == @potential_use.user_id
# if user.id == potential_use.user_id
true
else
false
end
end
def destroy?
update?
end
def edit?
true
end
def potential_use
record
end
end
当我尝试这些时,我不断收到错误说:
undefined method `user_id' for nil:NilClass
我不明白为什么收到这条消息。当我查看控制台时,我可以看到一个具有用户ID的条目。
p = PotentialUse.where(project_id: 26)
PotentialUse Load (0.5ms) SELECT "potential_uses".* FROM "potential_uses" WHERE "potential_uses"."project_id" = $1 [["project_id", 26]]
=> #<ActiveRecord::Relation [#<PotentialUse id: 9, comment: "adsfsfdadfasdddxxddbbdd", project_id: 26, created_at: "2016-08-18 23:16:06", updated_at: "2016-08-24 01:06:00", user_id: 1, private_comment: false>]>
2.3.0p0 :016 >
当我查看视图时(不尝试使用权威策略),页面呈现所有正确的内容,包括用户名(由user_id访问)。
我的潜在使用控制器中的更新操作有:
def update
authorize @potential_use
respond_to do |format|
if @potential_use.update(potential_use_params)
format.html { redirect_to @project, notice: 'Potential use was successfully updated.' }
format.json { render :show, status: :ok, location: @potential_use }
else
format.html { render @project }
format.json { render json: @potential_use.errors, status: :unprocessable_entity }
end
end
end
任何人都可以看到我做错了吗?
答案 0 :(得分:1)
要检查用户是否有权从视图中对策略执行操作:
<% if policy(@post).update? %>
<%= link_to "Edit post", edit_post_path(@post) %>
<% end %>
答案 1 :(得分:0)
您的错误是因为您调用了@potential_use.user_id
,但是策略类中从未声明@potential_use
。您将potential_use
定义为一种方法,但是在该方法中您调用record
而不是@record
。
因此,要解决此问题,您应该调用potential_use
而不是@potential_use
并将方法更改为:
def potential_use
@record
end
或者简单地,调用@record.user_id
而不是@potential_use.user_id
。
此外,正如您在Pundit readme中看到的那样,从ApplicationPolicy
继承时,无需声明:
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
因为它已经在父类中。
答案 2 :(得分:-1)
您可以使用访问者访问授权对象。在你的例子中,你可以称之为
authorize @potential_use
在您的控制器更新操作中。更新?控制器上的方法如下所示:
def update?
user.id == record.user_id
end