我试图让一些控制器测试通过但是当他们点击更新和删除操作时,尽管设置在能力中,CanCan仍然会抛出拒绝访问错误。这些错误似乎只发生在成员身上,因为管理员工作正常。
Abilities.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
User_Factory
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
Controller_Spec.rb
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
ApiController
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
在测试中调用删除操作的结果:
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=
其他操作似乎有效,但对于Update和Destroy,我一直收到AccessDenied错误。知道我可能做错了吗?
答案 0 :(得分:1)
您的ApiController似乎是命名空间,您需要将before_filter更改为以下内容:
before_filter :authenticate_api_user!
然后,您需要调整Cancan以使用current_api_user而不是current_user:
def current_ability
@current_ability ||= ::Ability.new(current_api_user)
end
这些链接有助于: