Ruby on rails 3 为更新和销毁而引发的CanCan AccessDenied错误

Ruby on rails 3 为更新和销毁而引发的CanCan AccessDenied错误,ruby-on-rails-3,rspec,cancan,Ruby On Rails 3,Rspec,Cancan,我试图让一些控制器测试通过,但当它们点击更新和删除操作时,CanCan继续抛出拒绝访问错误,尽管在功能中设置了。这些错误似乎只发生在成员身上,因为管理员工作正常 能力。rb def initialize(user) if user.has_role? :admin can :manage, :all elsif user.has_role? :member can :manage, PaymentMethod, :user_id => user.id end e

我试图让一些控制器测试通过,但当它们点击更新和删除操作时,CanCan继续抛出拒绝访问错误,尽管在功能中设置了。这些错误似乎只发生在成员身上,因为管理员工作正常

能力。rb

def initialize(user)
  if user.has_role? :admin
    can :manage, :all
  elsif user.has_role? :member
    can :manage, PaymentMethod, :user_id => user.id
  end
end
describe "PUT /api/users/:user_id/payment_method/:id" do
    before(:each) do
      @user = FactoryGirl.create(:member)
      sign_in_user @user

      @payment_method = FactoryGirl.create(:credit_card, {:user_id => @user.id})
    end

    it "updates a users payment method" do
      attr_to_change = {
        brand: "mastercard",
        user_id: @user.id, 
        id: @payment_method.id
      }
      put :update, attr_to_change
      response.status.should == 200
      JSON.parse(response.body)["payment_method"]["brand"]
        .should == "mastercard"
    end
  end

  describe "DELETE /api/users/:user_id/payment_methods/:id" do
    before(:each) do
      @user = FactoryGirl.create(:member)
      sign_in_user @user

      @payment_method = FactoryGirl.create(:credit_card, {:user_id => @user.id})
    end

    it "destroys a users payment method" do
      delete :destroy, {:user_id => @user, :id => @payment_method.id}
      response.status.should == 200
    end
  end
用户\工厂

FactoryGirl.define do
  factory :user do 
    sequence(:first_name) { |n| "John_#{n}" }
    sequence(:last_name) { |n| "Rambo_#{n}" }
    sequence(:email) { |n| "john_rambo_#{n}@example.com" }
    sequence(:username) { |n| "john_rambo_#{n}" }
    date_of_birth "03/12/1982"
    password 'password'
    password_confirmation 'password'
    picture_url File.open('spec/support/pictures/test.png')

    address

    factory :member do
      sequence(:last_name) { |n| "Member_#{n}" }
      roles :member
    end
  end
end
控制器规范rb

def initialize(user)
  if user.has_role? :admin
    can :manage, :all
  elsif user.has_role? :member
    can :manage, PaymentMethod, :user_id => user.id
  end
end
describe "PUT /api/users/:user_id/payment_method/:id" do
    before(:each) do
      @user = FactoryGirl.create(:member)
      sign_in_user @user

      @payment_method = FactoryGirl.create(:credit_card, {:user_id => @user.id})
    end

    it "updates a users payment method" do
      attr_to_change = {
        brand: "mastercard",
        user_id: @user.id, 
        id: @payment_method.id
      }
      put :update, attr_to_change
      response.status.should == 200
      JSON.parse(response.body)["payment_method"]["brand"]
        .should == "mastercard"
    end
  end

  describe "DELETE /api/users/:user_id/payment_methods/:id" do
    before(:each) do
      @user = FactoryGirl.create(:member)
      sign_in_user @user

      @payment_method = FactoryGirl.create(:credit_card, {:user_id => @user.id})
    end

    it "destroys a users payment method" do
      delete :destroy, {:user_id => @user, :id => @payment_method.id}
      response.status.should == 200
    end
  end
控制器

class Api::PaymentMethodsController < Api::ApiController
  before_filter :clean_params, only: [:update, :create]

  def index
    @user = User.find(params["user_id"])
    render json: @user.payment_methods
  end

  def update
    pm_id = params.delete("id")
    params.delete("user_id")
    @payment_method = PaymentMethod.find(pm_id)
    if @payment_method.update_attributes(params)
      return render status: 200, json: @payment_method, root: :payment_method
    else
      return render status: 422, json: {success: false, errors: @payment_method.errors.full_messages.map{|error|{error: error}}}
    end
  end

  def create
    @payment_method = PaymentMethod.create_payment_method(params)
    if @payment_method
      render json: @payment_method, root: :payment_method
    else
      return render status: 422, json: {success: false, errors: @payment_method.errors.full_messages.map{|error|{error: error}}}
    end
  end

  def destroy
    @payment_method = PaymentMethod.find(params["id"]) 
    if @payment_method.destroy
      return render status: 200, json: {:message => "PaymentMethod Destroyed"}
    else
      return render status: 422, json: {success: false, errors: @payment_method.errors.full_messages.map{|error|{error: error}}}
    end
  end

  def clean_params
    ["controller", "action"].each do |delete_me|
      params.delete(delete_me)
    end
    params
  end
end
class Api::ApiController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource

  rescue_from CanCan::AccessDenied do |exception|
    return render :status => 401, :json => {:success => false, :errors => [exception.message]}
  end
end
class Api::PaymentMethodsController“PaymentMethod已销毁”}
其他的
返回呈现状态:422,json:{success:false,errors:@payment_method.errors.full_messages.map{error}{error:error}
结束
结束
def清洁参数
[“控制器”,“操作”]。每个都删除我|
参数删除(删除我)
结束
params
结束
结束
ApiController

class Api::PaymentMethodsController < Api::ApiController
  before_filter :clean_params, only: [:update, :create]

  def index
    @user = User.find(params["user_id"])
    render json: @user.payment_methods
  end

  def update
    pm_id = params.delete("id")
    params.delete("user_id")
    @payment_method = PaymentMethod.find(pm_id)
    if @payment_method.update_attributes(params)
      return render status: 200, json: @payment_method, root: :payment_method
    else
      return render status: 422, json: {success: false, errors: @payment_method.errors.full_messages.map{|error|{error: error}}}
    end
  end

  def create
    @payment_method = PaymentMethod.create_payment_method(params)
    if @payment_method
      render json: @payment_method, root: :payment_method
    else
      return render status: 422, json: {success: false, errors: @payment_method.errors.full_messages.map{|error|{error: error}}}
    end
  end

  def destroy
    @payment_method = PaymentMethod.find(params["id"]) 
    if @payment_method.destroy
      return render status: 200, json: {:message => "PaymentMethod Destroyed"}
    else
      return render status: 422, json: {success: false, errors: @payment_method.errors.full_messages.map{|error|{error: error}}}
    end
  end

  def clean_params
    ["controller", "action"].each do |delete_me|
      params.delete(delete_me)
    end
    params
  end
end
class Api::ApiController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource

  rescue_from CanCan::AccessDenied do |exception|
    return render :status => 401, :json => {:success => false, :errors => [exception.message]}
  end
end
class Api::ApicController401,:json=>{:success=>false,:errors=>[exception.message]}
结束
结束
在测试中调用删除操作的结果:

delete :destroy, {:user_id => @user, :id => @payment_method.id}

#<ActionController::TestResponse:0x007fb999cf0080
 @blank=false,
 @block=nil,
 @body=
  ["{\"success\":false,\"errors\":[\"You are not authorized to access this page.\"]}"],
 @cache_control={},
 @charset="utf-8",
 @content_type=application/json,
 @etag=nil,
 @header={"Content-Type"=>"application/json; charset=utf-8"},
 @length=0,
 @request=
delete:destroy,{:user\u id=>@user,:id=>@payment\u method.id}
#“application/json;charset=utf-8”},
@长度=0,
@请求=

除了更新和销毁之外,其他操作似乎都很有效,我一直收到AccessDenied错误。知道我可能做错了什么吗?

您的ApiController似乎有名称空间,您需要将before\u过滤器更改为以下内容:

before_filter :authenticate_api_user!
然后,您需要调整Cancan以使用当前的_api_用户,而不是当前的_用户:

def current_ability
  @current_ability ||= ::Ability.new(current_api_user)
end
这些链接将有助于:


您的ApiController似乎有名称空间,您需要将before\u过滤器更改为以下内容:

before_filter :authenticate_api_user!
然后,您需要调整Cancan以使用当前的_api_用户,而不是当前的_用户:

def current_ability
  @current_ability ||= ::Ability.new(current_api_user)
end
这些链接将有助于:


如果对
@user
一无所知,就不可能进行推测。您可以在控制台中验证您的用户能力,作为一项健全性检查。请复制并粘贴所有输出以及控制器的源代码rspec文件。我添加了更多代码库以帮助澄清。如果不了解
@user
,就无法推测。您可以在控制台中验证您的用户能力,作为一项健全性检查。请复制并粘贴所有输出以及控制器的源代码rspec文件。我添加了更多代码库以帮助澄清。