Ruby on rails 为什么声明性_授权会破坏我的控制器的功能?-轨道3

Ruby on rails 为什么声明性_授权会破坏我的控制器的功能?-轨道3,ruby-on-rails,ruby-on-rails-3,declarative-authorization,Ruby On Rails,Ruby On Rails 3,Declarative Authorization,我有一个带有两个动作的优惠券控制器 class CouponsController < ApplicationController filter_resource_access def index @coupons = Coupon.all end #generates 10 new coupons on each call def generate plan_id = params[:plan_id] numdays = params[:n

我有一个带有两个动作的
优惠券
控制器

class CouponsController < ApplicationController
  filter_resource_access

  def index
    @coupons = Coupon.all
  end

  #generates 10 new coupons on each call
  def generate
    plan_id = params[:plan_id]
    numdays = params[:num_days]

    (1..10).each do |i|
      validChars = %w{ 1 2 3 4 5 6 7 9 a A b B d D e E f g G h H j J k K m M n N p P q Q r R t T }.to_a

      code = (0...6).map{ validChars[ rand(validChars.size) ] }.join

      coupon = Coupon.new
      coupon.code = code
      coupon.plan_id = plan_id
      coupon.active = false
      coupon.subdays = numdays
      coupon.save
    end
    redirect_to :coupons_path
  end

end
上述所有抛出的错误如下:

filter_access_to tried to find Coupon from params[:id] (nil), because attribute_check is enabled and @coupon isn't set, but failed: ActiveRecord::RecordNotFound: Couldn't find Coupon without an ID
Completed 404 Not Found in 245ms

ActiveRecord::RecordNotFound (Couldn't find Coupon without an ID):
但是,一旦我将
filter\u resource\u access
更改为
filter\u access\u改为:all,:except=>:generate
,它就不再给我错误,而且还可以正常工作

i、 e.它生成我正在寻找的一些优惠券代码,但它不包括视图输出中的计划id号或天数

为什么呢?我做错了什么


编辑1:顺便说一句,它确实限制了合适的人…即。只有指定的角色才能查看
优惠券索引视图
。因此,过滤器部分工作

我的猜测是,
filter\u resource\u access
将控制器中的所有操作视为处理单个资源,并尝试执行
优惠券.find(params[:id])
。将其更改为:

filter_access_to :all, :except => :generate

您告诉它在该操作之前不要运行该方法,这意味着它不会尝试查找优惠券。

声明性授权需要您将优惠券声明为实例变量


在控制器中,尝试将
优惠券=优惠券.new
更改为
@优惠券=优惠券.new
(显然要相应更改后续行)。

filter\u resource\u access尝试为您创建资源对象,因此您需要查看
:additional\u member
:additional\u collection
选项,或者如您所述,使用
选项

至于缺少的计划参数,您确定它们是作为
params[:plan\u id]
输入的吗?检查您的devel日志,查看传入参数的样子


您也没有检查
save
调用是否成功,因此如果有错误,您将无法知道。

filter\u resource\u访问触发声明性auth框架,以对资源的:id参数执行查找(在非集合/创建者方法中)

在您的示例中,它将执行@优惠券=优惠券.find(params[:id]),并为控制器设置该成员变量。但是,由于没有参数[:id]通过该路由进入该操作,因此该操作失败

解决这个问题的方法是,在保持控制器权限的同时,非常简单。只需将其放在控制器顶部的filter_resource_访问线上:

filter_resource_access :additional_collection => { :generate => :read } 
# I tried the two lines below but to no avail
#filter_resource_access :additional_collection => { :generate => :read }, :no_attribute_check => [ :generate ]
# filter_access_to :generate, :attribute_check => false
这将保持您对其他控制器操作以及“生成”操作的权限检查,但将“生成”方法从自动查找器查找中豁免

有关更多信息,请参阅:

问题在于,对于filter_resource_access,它假定控制器使用默认资源操作,并尝试为非标准crud的操作查找经销商if参数[:id]。 您需要做的是添加

filter_access_to :all
并将相应的规则:generate添加到authorization_rules.rb。 像


如果优惠券.started.nil?==正确
。只要
如果优惠券.started.nil?
就可以了.K。固定的!剩下的呢?:)那么,如何让它“正常运行”,但仍然仅限于我在
授权规则.rb
中指定的角色?read在这里做什么?我让它工作了,但有点不同。我使用了-filter\u resource\u access:collection=>[[:generate,:index],:index]
filter_resource_access :additional_collection => { :generate => :read } 
# I tried the two lines below but to no avail
#filter_resource_access :additional_collection => { :generate => :read }, :no_attribute_check => [ :generate ]
# filter_access_to :generate, :attribute_check => false
filter_access_to :all
role :someone do
    has_permission_on :coupon, :to => :generate
    ...
end