我想,以測試Farm
模型中的用戶身份驗證的不同反應,在這種情況下,對於具有讀訪問時被登錄的所有農場的:user
角色(如來賓用戶aka。anonymous也有)。慘慘accessibly_by返回規範和控制
# /models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
# Create guest user aka. anonymous (not logged in) when user is nil.
user ||= User.new
if user.has_role? :admin
can :manage, :all
else # guest user aka. anonymous
can :read, :all
# logged in user
if user.has_role? :user
can :create, Farm
can :manage, Farm, :user_id => user.id
end
end
end
end
...
# /controllers/api/v1/farms_controller.rb
class Api::V1::FarmsController < ActionController::Base
load_and_authorize_resource
rescue_from CanCan::AccessDenied do |exception|
redirect_to farms_path, alert: exception.message
end
respond_to :json
def index
# Next line might be redundant refering to the CanCan wiki. See below..
@farms = Farm.accessible_by(current_ability, :read)
respond_with(@farms)
end
end
...
# /spec/api/v1/farm_spec.rb
require "spec_helper"
describe "/api/v1/farms" do
let(:user) { create(:user) } # lets call this user1 in the discussion
let(:token) { user.authentication_token }
before do
user.add_role :user
create(:farm, user: user, name: "Testfarm")
create(:farm, name: "Access denied")
@ability = Ability.new(user)
end
context "farms viewable by this logged-in user" do
let(:url) { "/api/v1/farms" }
it "json" do
get "#{url}.json"
farms_json = Farm.accessible_by(@ability, :read).to_json
assert last_response.ok?
last_response.body.should eql(farms_json)
last_response.status.should eql(200)
farms = JSON.parse(last_response.body)
farms.any? do |farm|
farm["name"] == "Testfarm"
end.should be_true
farms.any? do |farm|
farm["name"] == "Access denied"
end.should be_true
end
end
end
問題
當我檢查farms_json
我可以看到它包含只的Testfarm
。當我檢查last_response
我可以看到它包含都的Testfarm
和Access denied
。這很奇怪,因爲我在規範和index
操作中都使用了相同的accessible_by
方法。我使用的設置在名爲Fetching Records的CanCan gem的wiki中描述。
無用的解決辦法
當我添加用戶user
農場Access denied
,如...
create(:farm, user: user, name: "Access denied")
...然後測試成功。
的問題
- 爲什麼是「拒絕訪問」農場不返回儘管它可以被任何用戶(包括來賓用戶)來讀取?
get "#{url}.json"
實際上是否考慮用戶的狀態?這是否全部由load_and_authorize_resource
完成FarmsController
?- 的wiki mentions是
@farms = Farm.accessible_by(current_ability, :read)
可以,因爲「這是自動load_resource
該指數一蹴而就」被排除在外。這是否適用於我的情況?
實驗
我創造了另一個用戶「用戶2」和另一場「我的小農場」。我把這些聯繫起來。這樣,在本例中的數據庫包含產品總數三個農場:
- 農場「Testfarm」相關的user1
- 農場「拒絕訪問」相關聯沒有相關user2的用戶
- 農場「我的小農場」。
當我運行Farm.accessible_by(Ability.new(user1), :read)
我仍然只收到「Testfarm」。