rails4 + Pundit 模型实例未在策略中定义
rails4 + Pundit model instance not defined in policy
我定义了一个 Pundit 策略 "CompanyPolicy" 如文档中所述,scopez 给出了预期的结果(在 :index 上)但是我在尝试使用公司模型实例时遇到异常:
*** NameError Exception: undefined local variable or method `company' for #<CompanyPolicy:
这里是 CompanyPolicy.rb
class CompanyPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.system_admin?
scope.all
else
Company.none
end
end
end
def new?
user.system_admin? ? true : false
end
def edit?
user.system_admin? ? true : false
end
def show?
user.system_admin? ? true : false
end
def destroy?
internal_name = Rails.application.secrets.internal_company_short_name
# do not destroy the internal company record
user.system_admin? && (company[:short_name] != internal_name ) ? true : false
end
end
我从公司控制者那里查看
def destroy
authorize @company
#@company.destroy
....
end
为什么(公司[:short_name]错了?
如果我查看 Pundit 文档,带有 PostPolicy 、范围和 post.published 的示例是相似的...
class PostPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(:published => true)
end
end
end
def update?
user.admin? or not post.published?
end
end
刚刚发现应该使用@record 而不是公司
(阅读与范围相关的问题:Implementing scopes in Pundit)
但我不明白为什么 Pundit 文档没有提到它,并且仍然使用像 'post' 这样的模型实例作为 PostPolicy ...
有人可以启发我们吗?
看看 documentation:
Pundit makes the following assumptions about this class:
- The class has the same name as some kind of model class, only suffixed with the word "Policy".
- The first argument is a user. In your controller, Pundit will call the current_user method to retrieve what to send into this
argument
- The second argument is some kind of model object, whose authorization you want to check. This does not need to be an
ActiveRecord or even an ActiveModel object, it can be anything
really.
- The class implements some kind of query method, in this case update?. Usually, this will map to the name of a particular
controller action.
That's it really.
Usually you'll want to inherit from the application policy created by
the generator, or set up your own base class to inherit from:
class PostPolicy < ApplicationPolicy
def update?
user.admin? or not record.published?
end
end
In the generated ApplicationPolicy, the model object is called record
.
我定义了一个 Pundit 策略 "CompanyPolicy" 如文档中所述,scopez 给出了预期的结果(在 :index 上)但是我在尝试使用公司模型实例时遇到异常:
*** NameError Exception: undefined local variable or method `company' for #<CompanyPolicy:
这里是 CompanyPolicy.rb
class CompanyPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.system_admin?
scope.all
else
Company.none
end
end
end
def new?
user.system_admin? ? true : false
end
def edit?
user.system_admin? ? true : false
end
def show?
user.system_admin? ? true : false
end
def destroy?
internal_name = Rails.application.secrets.internal_company_short_name
# do not destroy the internal company record
user.system_admin? && (company[:short_name] != internal_name ) ? true : false
end
end
我从公司控制者那里查看
def destroy
authorize @company
#@company.destroy
....
end
为什么(公司[:short_name]错了?
如果我查看 Pundit 文档,带有 PostPolicy 、范围和 post.published 的示例是相似的...
class PostPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
if user.admin?
scope.all
else
scope.where(:published => true)
end
end
end
def update?
user.admin? or not post.published?
end
end
刚刚发现应该使用@record 而不是公司 (阅读与范围相关的问题:Implementing scopes in Pundit)
但我不明白为什么 Pundit 文档没有提到它,并且仍然使用像 'post' 这样的模型实例作为 PostPolicy ... 有人可以启发我们吗?
看看 documentation:
Pundit makes the following assumptions about this class:
- The class has the same name as some kind of model class, only suffixed with the word "Policy".
- The first argument is a user. In your controller, Pundit will call the current_user method to retrieve what to send into this argument
- The second argument is some kind of model object, whose authorization you want to check. This does not need to be an ActiveRecord or even an ActiveModel object, it can be anything really.
- The class implements some kind of query method, in this case update?. Usually, this will map to the name of a particular
controller action.That's it really.
Usually you'll want to inherit from the application policy created by the generator, or set up your own base class to inherit from:
class PostPolicy < ApplicationPolicy def update? user.admin? or not record.published? end end
In the generated ApplicationPolicy, the model object is called
record
.