2

我有一个Coupons有两个动作的控制器。

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

在我的视图中调用生成操作,如下所示:

<h2 class="page-title">Coupons</h2>
<div class="main">
   <%= form_tag "coupons/generate" do -%>
        <%= hidden_field_tag 'user[plan_id]', "1" %>
        <%= hidden_field_tag 'user[num_days]', "150" %>
      <%= submit_tag "Generate 10 Coupons!", :class => "primary button" %>
   <% end -%>
    <table border="0" class="list">
        <thead>
            <tr>
                <th>Code</th><th>Plan</th><th>Duration</th><th>Activated</th>
            </tr>
        </thead>
        <tbody>
        <% if !@coupons.nil? %>
            <% @coupons.each do |coupon| %>
            <tr class="<%#= list_entry or list_entry_alt %>">
                <td><%= coupon.code %></td>
                <td><%= coupon.plan_id  %></td>
                <td><%= coupon.subdays %> days</td>
                <td><% if coupon.started.nil? == true  %>
                    <%= 'Not yet' %>
                    <% else %>
                    <%= time_ago_or_time_stamp coupon.started %>
                    <% end %>
                    </td>
            </tr>
            <% end %>
        <% end %>
        </tbody>
     </table>
</div>

我的config/authorization_rules.rb样子是这样的:

has_permission_on [:coupons], :to => [:index, :show, :step, :new, :create, :edit, :update, :destroy, :generate]

以上所有抛出的错误都是这样的:

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_resource_accessfilter_access_to :all, :except => :generate它就不会再给我错误并且有点工作。

即它会生成一些我正在寻找的优惠券代码,但它不包括视图输出中的plan_id 编号或天数。

这是为什么?我究竟做错了什么?

编辑1:顺便说一句,它确实限制了正确的人......即只有指定的角色才能查看coupons index view. 所以过滤器部分起作用。

4

5 回答 5

2

filter_resource_access 触发声明性身份验证框架以对资源的 :id 参数执行查找(在非集合/创建者方法中)。

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

绕过它的方法,同时仍然保留您的控制器权限非常容易。只需将其放在您的控制器顶部 filter_resource_access 行:

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

这将维护您对其他控制器操作以及“生成”操作的权限检查,但将“生成”方法从自动查找器查找中排除。

有关更多信息,请参阅: http ://rubydoc.info/github/stffn/declarative_authorization/master/Authorization/AuthorizationInController/ClassMethods

于 2012-02-23T05:38:56.303 回答
1

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

filter_access_to :all

并将 :generate 的相应规则添加到您的 authorization_rules.rb 中。喜欢

role :someone do
    has_permission_on :coupon, :to => :generate
    ...
end
于 2012-06-12T19:38:38.303 回答
1

我的猜测是,filter_resource_access将控制器中的所有操作都视为处理单个资源并尝试执行Coupon.find(params[:id]). 通过将其更改为:

filter_access_to :all, :except => :generate

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

于 2011-08-26T06:57:52.163 回答
0

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

在您的控制器中,尝试更改coupon = Coupon.new@coupon = Coupon.new(显然相应地更改后续行。)

于 2011-09-02T03:56:38.343 回答
0

filter_resource_access 尝试为您创建资源对象,因此您需要查看:additional_memberor:additional_collection选项,或者except按照您的说明使用选项。

至于缺少的计划参数,您确定它们以params[:plan_id]? 检查您的开发日志以查看传入参数的外观。

您也没有检查save呼叫是否成功,因此如果有错误,您将不知道。

于 2011-09-02T04:20:31.470 回答