GithubHelp home page GithubHelp logo

Comments (12)

chubchenko avatar chubchenko commented on June 13, 2024 1

The error occurs in this line in the #parent_child_conditions method during iteration though reflect_on_all_associations(:belongs_to).

If change the order of the association definition from:

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
  belongs_to :user
end

to:

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :commentable, polymorphic: true
end

the issue will be resolved but it's just a temporary life hack 😄

from cancancan.

WriterZephos avatar WriterZephos commented on June 13, 2024 1

Here it is for convenience: #814

from cancancan.

gryphon avatar gryphon commented on June 13, 2024

This will only fix the issue if you check user attribute in your case.
But if you check Comment model field (can :read, Comment, private: true), it will fail in any case

from cancancan.

javinto avatar javinto commented on June 13, 2024

I got this error with the devise_invitable gem which adds the belongs_to :invited_by, polymorphic: true association in Rails 6.1. Downgrading to Cancancan 3.3.0 solved it for me.

from cancancan.

mobilutz avatar mobilutz commented on June 13, 2024

The issue seems to be caused by this change:
d0ea89a#diff-468c7fa6110fedf2a4ae5259ca4d209daea99810746321092dac9cf373b87fdd

from cancancan.

martijn10kb avatar martijn10kb commented on June 13, 2024

I have the same issue, downgraded for now to 3.3.0

from cancancan.

bowtiesolutions avatar bowtiesolutions commented on June 13, 2024

The issue seems to be caused by this change: d0ea89a#diff-468c7fa6110fedf2a4ae5259ca4d209daea99810746321092dac9cf373b87fdd

Can confirm, the new offending behaviour is:

def parent_child_conditions(parent, child, all_conditions)
  child_class = child.is_a?(Class) ? child : child.class
  foreign_key = child_class.reflect_on_all_associations(:belongs_to).find do |association|
                  association.klass == parent.class
                end&.foreign_key&.to_sym
  foreign_key.nil? ? nil : all_conditions[foreign_key]
end

For ActiveRecord::Reflection::BelongsToReflection, 'klass' cannot be calculated for polymorphic associations so if one is utilised on the child class, the finder will error. As 'find' halts on the first instance, the temporary fix above to reoder polymorphic associations solves the issue for some.

Suggestion would be to add 'unless association.polymorphic?' to the finder to ensure polymorphic associations are ignored.

from cancancan.

WriterZephos avatar WriterZephos commented on June 13, 2024

Any luck with this? I am currently facing this issue and not finding a good work around so far.

from cancancan.

javinto avatar javinto commented on June 13, 2024

Unfortunately I did not implement any Work around except for downgrading to version 3.3.0.

However, with a little experimenting I found some workaround for my situation, although not ideal.

My original Ability code was:

can [:read, :update, :destroy], User, account_id: current_user.account_id

So, this one triggers the above exception with version 3.4.0.

I can rewrite it to

can [:read, :update, :destroy], User do |user|
  user.account_id==current_user.account_id
end

Now the exception is gone away and the right authorization is applied to the individual records BUT there is one drawback:

now the :read does not apply to the listing anymore. In other words: @users gives me all users and not just that of the account they belong to. So, I should apply an extra filter in my controller to make it work. But that could be acceptable.

Hopes this helps for your situation.

from cancancan.

caseyli avatar caseyli commented on June 13, 2024

I ran into this same issue and I think I can explain why changing the order of the association works, but I don't know what the long term fix is.

The issue seems to stem from lib/cancan/model_adapters/active_record_adapter.rb#parent_child_conditions. Look at this snippet of code:

def parent_child_conditions(parent, child, all_conditions)
  ...
  foreign_key = child_class.reflect_on_all_associations(:belongs_to).find do |association|
    association.klass == parent.class
  end&.foreign_key&.to_sym
  ...
end

When you do something like load_and_authorize_resource through: :current_user, it eventually ends up calling this method. This method loops through all your belongs_to associations on the resource you're trying to use.

On each of the belongs_to associations, it calls association.klass and sees if it matches the parent class you're trying to load through.

The problem is this rails/rails@fb86ecd doesn't allow you to call association.klass on polymorphic associations. So when it hits that association, the app throws an exception.

The reason the code will work if you re-arrange your associations, is that if the association you're dealing with happens to be near the top and matches BEFORE it hits a polymorphic association, the loop stops. I'm assuming .find just stops after it's found a match. So you never hit the error of calling .klass on a polymorphic association.

So re-arranging your associations may work - but it's quite brittle and won't work in a lot of cases.

Long term fix would be to update this loop code to handle polymorphic associations.

from cancancan.

WriterZephos avatar WriterZephos commented on June 13, 2024

@caseyli please see my PR linked above. It does just as you suggest and adds support for polymorphic associations.

from cancancan.

coorasse avatar coorasse commented on June 13, 2024

Closed on 3.5.0. Thank you!

from cancancan.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.