Polymorhic assisiation and accessible by #418

dre-hh opened this Issue Jul 15, 2011 · 11 comments


None yet

dre-hh commented Jul 15, 2011


i have following ability defined:

can :manage, Resource, {:owner_id => @user.id, :concrete_resource => {:project_type => {:name => 'Schoolproject'}}}

The Resource class has a polymorphic assiciation:
belongs_to :concrete_resource, :polymorphic => true

When calling accessible_by on current_abiltiy there is an Exception, because CanCan is ignoring the polymorphic assisiation
and i guess it's calling ConreteResource.table_name somethere in the code.

Actually think is nothing for a hash condition because i can't figure out a way how you could join form a resource to all concrete_ressources wihout having duplicates (concrete_resource_id refers to a differnt table respective to concrete_resource_type) in such an accessible_by method.


ryanb commented Jul 23, 2011

The association logic for nested condition hashes like this is pretty basic, so it's no surprise Polymorphic associations breaks this. I'll try to research this to be fixed, but in the meantime you may want to use a block instead of a hash of conditions. To handle the searching you can either pass a scope into the 3rd argument or duplicate the permission logic in the controller.

Yup. Had the same problem. It assumes that polymorphic association name is a class and tries to constantize it:

class Post < ActiveRecord::Base
  belongs_to :target, :polymorphic => true

class Group < ActiveRecord::Base
  has_many :posts, :as => :target, :dependent => :destroy

I use accessible_by to fetch only the posts from groups user belongs to:

@posts = Post.newest.includes(:target).accessible_by(current_ability,:read).limit(10).all

And in ability.rb:

can :read, Post, :target => {:id => user.group_ids_user_belongs_to}

And all that results in "uninitialized constant Target" error.

EDIT: This works fine for can? method, though. Of course this is simplified case, because my posts can be added on Users' pages too.

Getting exact same behavior as pokonski with CanCan 1.6.7.

whather commented Apr 13, 2012

Also getting the same behavior. Any workaround to this?

amrnt commented Aug 25, 2012

I'm getting this also! Any on this @ryanb?

same problem here. would be nice to have that feature :)

+1, going to implement it with a block for now.

VitorHP commented May 10, 2013

I'm trying to find a solution to this and i was thinking of something like this is the Ability class:

following the example of @pokonski

can :read, Post, :target => { :id => user.group_id_user_belongs_to, :target_types => :group }

I think it makes sense from the point of authorization, knowing which types of polymorphic associations a user can access. We could have another type of target, like blogs for example, that we don't want users to access or something like that.

I forked the gem and i'm trying to do something like that.

If u can see any problems with this approach, i'd be very glad to hear.

One problem that i already can see is that if a user wants to query all types of polymorphic associations and wants to specify this as a :target_types => :all in the Ability class, I can't think of a way to query and join all kinds of targets without querying the Post model for all distinct target types there and i don't know if this would be a major performance issue.

VitorHP commented May 10, 2013

You also could do something like this in your ability:

can :read, Post, Post.where(:target_type => "Group", :target_id => user.group_ids_user_belongs_to)

@ryanb already told that in his comment up there, but since there were people asking anyway, i think i could clarify the solution

This PR rails/rails#10366 might be relevant for this bug.

xhoy commented Apr 10, 2014

Dear submitter, Since cancan/raynB hasn't been active for more than 6 months and no body else then ryam himself has commit permissions the cancan project is on a stand still.
Since cancan has several issues including missing support for rails 4 cancan is moving forward to cancancan. More details on: #994

If your feel that your pull request or bug is still applicable (and hasn't been merged in to cancan) it would be really appreciated if you would resubmit it to cancancan (https://github.com/cancancommunity/cancancan)

We hope to see you on the other side!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment