I recently integrated cancan (1.6.9) into my Rails (3.2.10) project for authorization, and I'm having an issue with manually loading a resource in a before_filter. Here's a brief description of my scenario.
In config/routes.rb, I have the following entries...
resources :users
match '/profile', :to => 'users#show'
Here's what my users_controller.rb looks like...
class UsersController < ApplicationController
before_filter :load_show_resource, :only => :show
load_and_authorize_resource
...
def show
end
...
private
def load_show_resource
@user = params[:id] ? User.find(params[:id]) : current_user
end
end
If my current_user's id is 1, this code will let me access localhost:3000/users/1 but not localhost:3000/profile.
The entry in my cancan ability.rb class that's blocking this access is seen below - it's the cannot section. If I comment out the cannot entry, both urls work.
...
can [:show, :update], User, :id => user.id
cannot [:show, :update, :destroy], User do |u|
u.site_id != user.site_id
end
....
Shouldn't cancan use the resource that's being manually loaded in the before_filter for the show action regardless of whether or not params[:id] is present?
Interestingly enough, if I modify my users controller (see below) to use skip_load_and_authorize_resource :only => :show and manually calling authorize! in the show action, both urls work. Also, if I remove cancan altogether both urls work.
class UsersController < ApplicationController
load_and_authorize_resource
skip_load_and_authorize_resource :only => :show
...
def show
@user = params[:id] ? User.find(params[:id]) : current_user
authorize! :show, @user
end
...
private
def load_show_resource
@user = params[:id] ? User.find(params[:id]) : current_user
end
end
So, my question is why does what's explained in the Override loading in the cancan documentation, not work in this situation?
Thanks!
before_filterwith theskip_load_and_authorize_resourceworkflow? - drewinglis