diff --git a/lib/pundit/authorization.rb b/lib/pundit/authorization.rb index 1231f2a7..161aa436 100644 --- a/lib/pundit/authorization.rb +++ b/lib/pundit/authorization.rb @@ -103,25 +103,39 @@ def policy(record) policies[record] ||= Pundit.policy!(pundit_user, record) end - # Retrieves a set of permitted attributes from the policy by instantiating + # Retrieves a list of permitted attribute names from the policy by instantiating # the policy class for the given record and calling `permitted_attributes` on - # it, or `permitted_attributes_for_{action}` if `action` is defined. It then infers - # what key the record should have in the params hash and retrieves the - # permitted attributes from the params hash under that key. + # it, or `permitted_attributes_for_{action}` if `action` is defined. # # @see https://github.com/varvet/pundit#strong-parameters # @param record [Object] the object we're retrieving permitted attributes for # @param action [Symbol, String] the name of the action being performed on the record (e.g. `:update`). # If omitted then this defaults to the Rails controller action name. - # @return [Hash{String => Object}] the permitted attributes - def permitted_attributes(record, action = action_name) + # @return [Array] the names of the permitted attributes + def permitted_attribute_names(record, action = action_name) policy = policy(record) method_name = if policy.respond_to?("permitted_attributes_for_#{action}") "permitted_attributes_for_#{action}" else "permitted_attributes" end - pundit_params_for(record).permit(*policy.public_send(method_name)) + policy.public_send(method_name) + end + + # Retrieves a set of permitted attributes from the policy by instantiating + # the policy class for the given record and calling `permitted_attributes` on + # it, or `permitted_attributes_for_{action}` if `action` is defined. It then infers + # what key the record should have in the params hash and retrieves the + # permitted attributes from the params hash under that key. + # + # @see https://github.com/varvet/pundit#strong-parameters + # @param record [Object] the object we're retrieving permitted attributes for + # @param action [Symbol, String] the name of the action being performed on the record (e.g. `:update`). + # If omitted then this defaults to the Rails controller action name. + # @return [Hash{String => Object}] the permitted attributes + def permitted_attributes(record, action = action_name) + attribute_names = permitted_attribute_names(record, action) + pundit_params_for(record).permit(*attribute_names) end # Retrieves the params for the given record. diff --git a/spec/authorization_spec.rb b/spec/authorization_spec.rb index 2995bfdb..95fa04d7 100644 --- a/spec/authorization_spec.rb +++ b/spec/authorization_spec.rb @@ -186,6 +186,22 @@ end end + describe "#permitted_attribute_names" do + it "checks policy" do + action = "update" + expect(Controller.new(user, action, {}).permitted_attribute_names(post)).to eq( + %i[title votes] + ) + end + end + + describe "#permitted_attribute_names_for_action" do + it "is checked if it is defined in the policy" do + action = "revise" + expect(Controller.new(user, action, {}).permitted_attribute_names(post)).to eq(%i[body]) + end + end + describe "#permitted_attributes" do it "checks policy for permitted attributes" do params = ActionController::Parameters.new(