cancancan: Possible regression with draper when updating from 1.12

Hi!

I’m using devise + cancancan along with draper gem, and until 1.12 the behavior was that calling can? on a decorated model used the decorated model for checking authorization instead of the decorator class. Maybe I can better explain myself with an example:

 # in my ability.rb
 can :read, User do |user|
   true
 end

 # in a view
 @user = User.last.decorate # instance of UserDecorator
 can? :show, @user 
 #=> true, since the ability for User was used

After updating to 1.13, this is no longer the case, and calling can? :show, @user on a decorated user will not use User ability at all.

Is this intended behavior or is it a regression? If this is intended, how can I get that bahaviour back, maybe with an extension or configuration in my decorators / ability.rb?

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 35 (17 by maintainers)

Commits related to this issue

Most upvoted comments

I think this issue can be closed @Senjai

At least for me, it was beautifuly solved with @robmathews’s draper-cancancan.

Thanks a bunch and 🍻 for you!

Ok, so it’s actually https://github.com/GoodMeasuresLLC/draper-cancancan b/c of a naming conflict, and its ready to go.

Just put

gem ‘draper-cancancan’ in your gemfile and put this in your CanCan Ability class:

class Ability
    include CanCan::Ability
    prepend Draper::CanCanCan

On Thu, Nov 5, 2015 at 5:31 PM, Robert Mathews < rob@justsoftwareconsulting.com> wrote:

Turns out it works as written, but we were mocking too aggressively locally.

So I’ll be taking out the puts and pushing tomorrow.

On Thu, Nov 5, 2015 at 4:36 PM, Robert Mathews < rob@justsoftwareconsulting.com> wrote:

Not a problem. I’ve got it working in my little gem test right now, but it’s failing to actually prepend the can? method correctly in my real app. Probably something trivial.

It’s here if you want to take a look: https://github.com/GoodMeasuresLLC/draper-cancan

Otherwise I’ll poke you later if it works.

Rob.

On Thu, Nov 5, 2015 at 4:24 PM, Richard Wilson notifications@github.com wrote:

@robmathews https://github.com/robmathews If you do come up with something that works for you as a gem, I’d be happy to fork it from you as part of the organization as well.

— Reply to this email directly or view it on GitHub https://github.com/CanCanCommunity/cancancan/issues/255#issuecomment-154197018 .

Stumbled over the same problem when upgrading to 1.13. Some warning (while bundle install) would be enough for now.

@dgilperez a workaround would be to use some wrapper method or monkey-patch like

def can_do?(action, object)
  if object.decorated?
     object = object.model
  end
  can? action, object
end

Then just replace every usage of can? with can_do?

@jaredbeck We never explicitly supported draper in the first place. The only thing I can find in the Wiki is a reference to https://github.com/anlek/draper-cancan. I took over the project a couple months ago, did cancan explicitly support draper before it was cancancan?

I may be wrong, if you can identify where it was stated there was explicit support for Draper I’ll definitely eat my words. Again, this is still in discussion and I want to hear other peoples’ opinion on the matter as well.

Do you have any comments on the extension point I made earlier?

If you’re dropping support for draper, you’re going to break a lot of apps. Draper has two million downloads (https://rubygems.org/gems/draper). So, if you’re dropping support for draper, maybe add a boot-time warning?

if defined?(::Draper)
  warn "cancancan 1.13 dropped support for Draper. " +
    "Checking abilities against decorated objects will no longer work. " + 
    "Please make sure to check against un-decorated objects."
end

Alternatively, a runtime warning should also be possible.