@@ -73,13 +73,26 @@ module Ability
7373 # Also see the RSpec Matchers to aid in testing.
7474 def can? ( action , subject , attribute = nil , *extra_args )
7575 match = extract_subjects ( subject ) . lazy . map do |a_subject |
76+ rules_for_query = rules_except_cannot_with_attributes ( action , a_subject )
77+ subject_class = subject_class? ( a_subject ) ? a_subject : a_subject . class
78+ if can_use_accessible_by? ( subject_class , a_subject , rules_for_query )
79+ next subject_class . accessible_by ( self , action ) . exists? ( a_subject . send ( subject_class . primary_key ) ) ? rules_for_query . first : nil
80+ end
81+
7682 relevant_rules_for_match ( action , a_subject ) . detect do |rule |
7783 rule . matches_conditions? ( action , a_subject , attribute , *extra_args ) && rule . matches_attributes? ( attribute )
7884 end
7985 end . reject ( &:nil? ) . first
8086 match ? match . base_behavior : false
8187 end
8288
89+ def can_use_accessible_by? ( subject_class , subject , rules )
90+ subject_class . respond_to? ( :accessible_by ) &&
91+ defined? ( ActiveRecord ::Base ) && subject . is_a? ( ActiveRecord ::Base ) &&
92+ !subject . new_record? &&
93+ rules . none? ( &:only_block? )
94+ end
95+
8396 # Convenience method which works the same as "can?" but returns the opposite value.
8497 #
8598 # cannot? :destroy, @project
0 commit comments