CanCanCommunity / cancancan

The authorization Gem for Ruby on Rails.
MIT License
5.54k stars 633 forks source link

Association is renamed in SQL and results in unknown column error #790

Open 23tux opened 2 years ago

23tux commented 2 years ago

Steps to reproduce

I tried to use the gist from here to reproduce the issue, but it throws an error CanCan::NotImplemented: This model adapter does not support fetching records from the database. when using Rails 6.1.6. So I try to explain it as good as I can:

My ability has this line

can :index, Spree::EventImage, event: { time_item: { city_zone_id: user.city_zone_ids } }

The models look like this:

module Spree
  class EventImage < ApplicationRecord
    belongs_to :event
  end
end
module Spree
  class Event < ApplicationRecord
    has_one :time_item, as: :timeable, dependent: :destroy
  end
end
module Spree
  class TimeItem < ApplicationRecord
    belongs_to :timeable, polymorphic: true
    belongs_to :city_zone
  end
end

Expected behavior

When I use EventImage.accessible_by(current_ability) it generates this SQL:

SELECT `spree_event_images`.* FROM `spree_event_images` WHERE `spree_event_images`.`id` IN (
  SELECT `spree_event_images`.`id` FROM `spree_event_images` 
    LEFT OUTER JOIN `spree_events` ON `spree_events`.`id` = `spree_event_images`.`event_id` 
    LEFT OUTER JOIN `spree_time_items` `time_items_spree_events` ON `time_items_spree_events`.`timeable_type` = 'Spree::Event' AND `time_items_spree_events`.`timeable_id` = `spree_events`.`id` 
    WHERE `spree_time_items`.`city_zone_id` IN (123, 987)
)

And this results in this error

Mysql2::Error: Unknown column 'spree_time_items.city_zone_id' in 'where clause'

Actual behavior

I guess there is something wrong with the renaming of the table, but I'm not sure if it is a problem at rails or cancancan. The problematic part is this:

LEFT OUTER JOIN `spree_time_items` `time_items_spree_events`

It seems that somehow the spree_time_items table gets renamed to time_items_spree_events, but is later referenced by it's original name in the query, thus resulting in the error above.

When using Rails 6.0.4.8 this generates the following SQL which works as expected:

SELECT `spree_event_images`.* FROM `spree_event_images` WHERE `spree_event_images`.`id` IN (
  SELECT `spree_event_images`.`id` FROM `spree_event_images` 
    LEFT OUTER JOIN `spree_events` ON `spree_events`.`id` = `spree_event_images`.`event_id` 
    LEFT OUTER JOIN `spree_time_items` ON `spree_time_items`.`timeable_type` = 'Spree::Event' AND `spree_time_items`.`timeable_id` = `spree_events`.`id` 
    WHERE `spree_time_items`.`city_zone_id` IN (123, 987)
)

System configuration

Rails version: 6.1.6

Ruby version: 2.7.2

CanCanCan version: 3.3.0

23tux commented 1 year ago

Unfortunately, I still have no solution to this and the update to cancancan 3.4.0 didn't resolve it either. Can someone help me, figuring this out?

23tux commented 1 year ago

I just tried cancancan 3.5.0 and I still have the same issue. Was hoping that this fix would also fix my issue https://github.com/CanCanCommunity/cancancan/pull/814

Can someone from the team help me figure out what's wrong here?