Ruby on rails 如何用权威解决命名错误
我不知道我是不是做错了什么,但看起来好像是 我使用Pundit进行授权,现在我已经用它建立了一些模型 我有一个类别模型,只能由管理员创建。此外,我也不希望用户看到显示/编辑/销毁视图。我只希望管理员可以访问它。到目前为止还不错 将在下面添加一些代码: 类别_policy.rbRuby on rails 如何用权威解决命名错误,ruby-on-rails,ruby,pundit,Ruby On Rails,Ruby,Pundit,我不知道我是不是做错了什么,但看起来好像是 我使用Pundit进行授权,现在我已经用它建立了一些模型 我有一个类别模型,只能由管理员创建。此外,我也不希望用户看到显示/编辑/销毁视图。我只希望管理员可以访问它。到目前为止还不错 将在下面添加一些代码: 类别_policy.rb class CategoryPolicy < ApplicationPolicy def index? user.admin? end def create? user.admin?
class CategoryPolicy < ApplicationPolicy
def index?
user.admin?
end
def create?
user.admin?
end
def show?
user.admin?
end
def new?
user.admin?
end
def update?
return true if user.admin?
end
def destroy?
return true if user.admin?
end
end
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def create?
create?
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope.all
end
end
end
我的应用程序控制器中包含了Pundit,并且从Pundit::NotAuthorizedError中解救出了Pundit,在那里也设置了::forbidden
如果我使用管理员帐户登录,则授权本身有效,我可以访问/categories/*。如果我注销,我会得到以下信息:NoMethodError at/categories
nil:NilClass的未定义方法`
在写问题的时候,我想我发现了问题所在——我猜Pundit寻找的是一个为零的用户,因为我没有登录。解决这个问题的正确方法是什么
最常用的方法是从未登录用户无法访问的页面重定向用户。只需在控制器中添加一个before操作:
class CategoriesController < ApplicationController
before_action :redirect_if_not_logged_in
<...>
private
def redirect_if_not_logged_in
redirect_to :home unless current_user
end
end
class CategoriesController
(这里我假设您有current\u user
方法,该方法返回用户实例或nil。请更改:home to where you want redirect users)有多种方法可以实现您想要的
最明显(但有点脏)和直观的方法是在每种情况下都添加一个用户状态检查:
user&&user.admin?
它不会因nil
错误而失败,因为条件的第二部分不会执行。但它看起来不太好看,对吗?特别是如果您必须将其复制到CategoryPolicy
中的所有方法中
相反,您可以做的是创建一个GuestUser
类,用false
响应admin?
方法(),让专家“认为”您传递了一个User
:
在面向对象的计算机编程中,空对象是没有引用值或具有定义的中性(“空”)行为的对象。空对象设计模式描述了此类对象的使用及其行为(或缺少)
当user
为nil
时使用它。实际上,它将如下所示:
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user || GuestUser.new
@record = record
end
# ...
end
class GuestUser
def admin?
false
end
end
这样,您就不必修改任何其他代码,因为您传递的模型响应策略所期望的方法(admin?
)。您可能希望在其他地方(不在策略文件中)定义此GuestUser
,具体取决于您是否希望应用程序的其他部分重用该行为
您还可以继续使用p.Boro answer中的重定向方法。从某种意义上讲,它的灵活性较低,但如果您除了重定向所有未登录的用户之外不需要任何其他东西,那么它完全可以正常工作
谢谢你的快速回答。这正是我想要的。我真的不知道为什么我没有提出重定向。
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user || GuestUser.new
@record = record
end
# ...
end
class GuestUser
def admin?
false
end
end