How can I correctly authorize a resource that is nested with devise and cancan? I have implemented the suggested procedure from the documentation but without success.
This issue involves the ability model not getting the user id from the tertiary layer of a nested resource using devise and cancan gems. I am able to get the user id from the secondary layer, however. Any help is greatly appreciated!
I have a nested resource like so:
resources :users do
resources :clients do
resources :positions
end
end
resources :clients do
resources :positions
end
resources :users do
resources :positions
end
resources :users
resources :clients
resources :positions
With the position model controller using the following:
class PositionsController < ApplicationController
before_filter :grab_client_from_client_id
load_and_authorize_resource :user
load_and_authorize_resource :client, through: :user, shallow: true
load_and_authorize_resource :position, through: :client, except: [:index], shallow: true
...
end
The ability.rb file:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.has_role? :admin
can :manage, :all
elsif user.has_role? :management
can [:create, :read, :update], :all
else
can :read, :all, user_id: user.id
end
end
end
This results in a non-admin/non-management user receiving the following error:
undefined method 'user_id' for #<User:0x5227d40>
Clearly something is not set up correctly. I have gone through the documentation over and over for each gem, as well as searching everywhere looking for a solution.
I will also provide my model relationships below.
class User < ActiveRecord::Base
has_many :clients
has_many :positions, through: :clients
resourcify
...
end
class Client < ActiveRecord::Base
resourcify
has_many :checklogs
has_many :positions
belongs_to :user
end
class Position < ActiveRecord::Base
resourcify
belongs_to :client
delegate :user, to: :client, allow_nil: true
end