diff --git a/lib/cancan/ability/strong_parameter_support.rb b/lib/cancan/ability/strong_parameter_support.rb index 892d250a..2d3d6190 100644 --- a/lib/cancan/ability/strong_parameter_support.rb +++ b/lib/cancan/ability/strong_parameter_support.rb @@ -10,6 +10,8 @@ module StrongParameterSupport # they are added. The 'reverse' is so that attributes will be added before the # 'cannot' rules remove them. def permitted_attributes(action, subject) + return [] unless can?(action, subject) + relevant_rules(action, subject) .reverse .select { |rule| rule.matches_conditions? action, subject } diff --git a/spec/cancan/ability_spec.rb b/spec/cancan/ability_spec.rb index 3951f3b2..be7678fc 100644 --- a/spec/cancan/ability_spec.rb +++ b/spec/cancan/ability_spec.rb @@ -665,6 +665,16 @@ def active? expect(@ability.can?(:update, Range, :name)).to be(true) end + it 'returns an empty array for permitted_attributes when no ability is defined' do + expect(@ability.permitted_attributes(:update, NamedUser)).to eq([]) + end + + it 'returns an empty array for permitted_attributes if the action is explicitly forbidden' do + @ability.can :update, NamedUser + @ability.cannot :update, NamedUser # explicitly deny + expect(@ability.permitted_attributes(:update, NamedUser)).to eq([]) + end + it 'returns an array of permitted attributes for a given action and subject' do @ability.can :read, NamedUser @ability.can :read, Array, :special