Skip to content

Instantly share code, notes, and snippets.

@coorasse
Created October 20, 2020 15:39
Show Gist options
  • Save coorasse/650f5bc6b87b85066b3af9624e3a0f48 to your computer and use it in GitHub Desktop.
Save coorasse/650f5bc6b87b85066b3af9624e3a0f48 to your computer and use it in GitHub Desktop.
A Rails controller concern to give hints to clients about unpermitted parameters.
module UnpermittedParametersListener
extend ActiveSupport::Concern
included do
before_action :instrument_listener_for_unpermitted_params
after_action :merge_unpermitted_params_hints
attr_reader :permitted_action_params
end
private
def permitted_action_params=(params)
@permitted_action_params = params
@spell_checker = DidYouMean::SpellChecker.new(dictionary: deep_values(params))
end
def instrument_listener_for_unpermitted_params
@unpermitted_parameters ||= []
ActiveSupport::Notifications.subscribe('unpermitted_parameters.action_controller') do |_name, _start, _finish, _id, payload|
@unpermitted_parameters += payload[:keys]
@unpermitted_parameters.uniq!
end
end
def merge_unpermitted_params_hints
return unless @unpermitted_parameters.any?
json_response = JSON.parse(response.body).with_indifferent_access
json_response[:meta] = { hints: generate_hints }
response.body = json_response.to_json
end
def deep_values(object)
case true
when object.is_a?(Array)
object.map { |e| deep_values(e) }.flatten
when object.is_a?(Hash)
object.values.map { |e| deep_values(e) }.flatten
else
object
end
end
def generate_hints
@unpermitted_parameters.map do |attribute|
suggestions = @spell_checker.present? ? @spell_checker.correct(attribute) : []
hint = "#{attribute} is not a valid parameter."
if suggestions.any?
hint += " Did you mean #{suggestions.to_sentence(two_words_connector: ' or ', last_word_connector: ', or')}?"
end
hint
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment