Last active
August 13, 2024 15:54
-
-
Save dominikb/83adb5465222c6b0b224df7bada48931 to your computer and use it in GitHub Desktop.
CanCanCan illegal table alias
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # frozen_string_literal: true | |
| require 'bundler/inline' | |
| gemfile(true) do | |
| source 'https://rubygems.org' | |
| gem 'activerecord', '~> 7.1.0' | |
| gem 'sqlite3', '~> 1.4' | |
| gem 'cancancan', '~> 3.6.0', require: false | |
| # Potential fix mentioned in https://github.com/CanCanCommunity/cancancan/issues/696 but does not work either | |
| # gem 'cancancan', '~> 3.4.0', require: false, git: 'https://github.com/daveallie/cancancan', branch: 'fix/conditions-extractor-aliases' | |
| end | |
| require 'active_record' | |
| require 'cancancan' | |
| ActiveRecord::Base.logger = Logger.new(STDOUT) | |
| ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:') | |
| ActiveRecord::Schema.define do | |
| create_table :teams, force: true do |t| | |
| end | |
| create_table :team_accesses, force: true do |t| | |
| t.integer :privileged_team_id | |
| t.integer :accessible_team_id | |
| end | |
| create_table :memberships, force: true do |t| | |
| t.integer :team_id | |
| end | |
| create_table :appreciations, force: true do |t| | |
| t.integer :receiver_id | |
| t.integer :sender_id | |
| t.string :visibility | |
| end | |
| end | |
| class Team < ActiveRecord::Base | |
| has_many :memberships | |
| has_many :privileged_for_team_accesses, class_name: 'TeamAccess', foreign_key: :privileged_team_id, | |
| dependent: :destroy, inverse_of: :privileged_team | |
| has_many :accessible_teams, class_name: 'Team', through: :privileged_for_team_accesses | |
| has_many :accessible_by_team_accesses, class_name: 'TeamAccess', foreign_key: :accessible_team_id, | |
| dependent: :destroy, inverse_of: :accessible_team | |
| has_many :privileged_teams, class_name: 'Team', through: :accessible_by_team_accesses | |
| end | |
| class TeamAccess < ActiveRecord::Base | |
| belongs_to :privileged_team, class_name: 'Team' | |
| belongs_to :accessible_team, class_name: 'Team' | |
| end | |
| class Membership < ActiveRecord::Base | |
| belongs_to :team | |
| has_many :accessible_teams, through: :team | |
| end | |
| class Appreciation < ActiveRecord::Base | |
| belongs_to :receiver, class_name: 'Membership' | |
| enum visibility: { | |
| team: 'team', | |
| receiver: 'receiver', | |
| }, _default: 'team' | |
| end | |
| class WorkingAbility | |
| include ::CanCan::Ability | |
| def initialize | |
| can :read, Appreciation, { receiver: { team: { id: 1 } }, visibility: 'team' } | |
| can :read, Appreciation, { receiver: { team: { privileged_teams: { id: 1 } } }, visibility: 'team' } | |
| end | |
| end | |
| class BrokenAbility | |
| include ::CanCan::Ability | |
| def initialize | |
| can :read, Appreciation, { receiver: { team: { privileged_teams: { id: 1 } } }, visibility: 'team' } | |
| can :read, Appreciation, { receiver: { team: { id: 1 } }, visibility: 'team' } | |
| end | |
| end | |
| working_query = Appreciation.accessible_by(WorkingAbility.new) | |
| broken_query = Appreciation.accessible_by(BrokenAbility.new) | |
| puts(working_query.to_sql) | |
| puts(broken_query.to_sql) | |
| puts(working_query.load) | |
| puts(broken_query.load) | |
| # OUTPUT | |
| # SELECT "appreciations".* FROM "appreciations" WHERE "appreciations"."id" IN (SELECT "appreciations"."id" FROM "appreciations" LEFT OUTER JOIN "memberships" ON "memberships"."id" = "appreciations"."receiver_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "memberships"."team_id" LEFT OUTER JOIN "team_accesses" ON "team_accesses"."accessible_team_id" = "teams"."id" LEFT OUTER JOIN "teams" "privileged_teams_team_accesses" ON "privileged_teams_team_accesses"."id" = "team_accesses"."privileged_team_id" WHERE (("privileged_teams_team_accesses"."id" = 1 AND "appreciations"."visibility" = 'team') OR ("teams"."id" = 1 AND "appreciations"."visibility" = 'team'))) | |
| # SELECT "appreciations".* FROM "appreciations" WHERE "appreciations"."id" IN (SELECT "appreciations"."id" FROM "appreciations" LEFT OUTER JOIN "memberships" ON "memberships"."id" = "appreciations"."receiver_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "memberships"."team_id" LEFT OUTER JOIN "team_accesses" ON "team_accesses"."accessible_team_id" = "teams"."id" LEFT OUTER JOIN "teams" "privileged_teams_team_accesses" ON "privileged_teams_team_accesses"."id" = "team_accesses"."privileged_team_id" WHERE (("teams_memberships"."id" = 1 AND "appreciations"."visibility" = 'team') OR ("teams"."id" = 1 AND "appreciations"."visibility" = 'team'))) | |
| # D, [2024-08-13T17:46:23.699135 #58715] DEBUG -- : Appreciation Load (0.1ms) SELECT "appreciations".* FROM "appreciations" WHERE "appreciations"."id" IN (SELECT "appreciations"."id" FROM "appreciations" LEFT OUTER JOIN "memberships" ON "memberships"."id" = "appreciations"."receiver_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "memberships"."team_id" LEFT OUTER JOIN "team_accesses" ON "team_accesses"."accessible_team_id" = "teams"."id" LEFT OUTER JOIN "teams" "privileged_teams_team_accesses" ON "privileged_teams_team_accesses"."id" = "team_accesses"."privileged_team_id" WHERE (("privileged_teams_team_accesses"."id" = 1 AND "appreciations"."visibility" = 'team') OR ("teams"."id" = 1 AND "appreciations"."visibility" = 'team'))) | |
| # D, [2024-08-13T17:46:23.699327 #58715] DEBUG -- : Appreciation Load (0.1ms) SELECT "appreciations".* FROM "appreciations" WHERE "appreciations"."id" IN (SELECT "appreciations"."id" FROM "appreciations" LEFT OUTER JOIN "memberships" ON "memberships"."id" = "appreciations"."receiver_id" LEFT OUTER JOIN "teams" ON "teams"."id" = "memberships"."team_id" LEFT OUTER JOIN "team_accesses" ON "team_accesses"."accessible_team_id" = "teams"."id" LEFT OUTER JOIN "teams" "privileged_teams_team_accesses" ON "privileged_teams_team_accesses"."id" = "team_accesses"."privileged_team_id" WHERE (("teams_memberships"."id" = 1 AND "appreciations"."visibility" = 'team') OR ("teams"."id" = 1 AND "appreciations"."visibility" = 'team'))) | |
| # ~/.asdf/installs/ruby/3.3.4/lib/ruby/gems/3.3.0/gems/sqlite3-1.7.3-arm64-darwin/lib/sqlite3/database.rb:177:in `initialize': SQLite3::SQLException: no such column: teams_memberships.id (ActiveRecord::StatementInvalid) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment