lib/cancan/ability/strong_parameter_support.rb
# frozen_string_literal: true
module CanCan
module Ability
module StrongParameterSupport
# Returns an array of attributes suitable for use with strong parameters
#
# Note: reversing the relevant rules is important. Normal order means that 'cannot'
# rules will come before 'can' rules. However, you can't remove attributes before
# they are added. The 'reverse' is so that attributes will be added before the
# 'cannot' rules remove them.
def permitted_attributes(action, subject)
relevant_rules(action, subject)
.reverse
.select { |rule| rule.matches_conditions? action, subject }
.each_with_object(Set.new) do |rule, set|
attributes = get_attributes(rule, subject)
# add attributes for 'can', remove them for 'cannot'
rule.base_behavior ? set.merge(attributes) : set.subtract(attributes)
end.to_a
end
private
def subject_class?(subject)
klass = (subject.is_a?(Hash) ? subject.values.first : subject).class
[Class, Module].include? klass
end
def get_attributes(rule, subject)
klass = subject_class?(subject) ? subject : subject.class
# empty attributes is an 'all'
if rule.attributes.empty? && klass < ActiveRecord::Base
klass.column_names.map(&:to_sym) - Array(klass.primary_key)
else
rule.attributes
end
end
end
end
end