Skip to content

Instantly share code, notes, and snippets.

@chrisbloom7
Last active August 6, 2025 18:53
Show Gist options
  • Save chrisbloom7/e7e67410f47574e102a7942dfba2a8ef to your computer and use it in GitHub Desktop.
Save chrisbloom7/e7e67410f47574e102a7942dfba2a8ef to your computer and use it in GitHub Desktop.
Debugging CanCanCan abilities
def audit_ability(ability:, action:, subject:)
begin
ability.authorize!(action, subject)
puts "CanCanCan: User has ability to #{action} for #{subject.inspect}"
rescue CanCanCan::AccessDenied => exception
failed_rules = ability.send(:relevant_rules_for_match, exception.action, exception.subject).reject do |rule|
rule.matches_conditions?(exception.action, exception.subject)
end
if failed_rules.any?
puts "CanCanCan::AccessDenied: User does not have ability to #{exception.action} for #{exception.subject.inspect} due to the following conditions:\n"
failed_rules.map do |rule|
pp { conditions: rule.conditions, block: rule.instance_variable_get(:@block) }
puts ""
end
else
puts "CanCanCan::AccessDenied: User does not have ability to #{exception.action} for #{exception.subject.inspect} for indeterminate reasons"
end
end
end
user = User.find(...)
action = :some_action
subject = SomeThing
ability = Ability.new(user, ...)
audit_ability(ability:, action:, subject:)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment