Getting paranoid about your Rails application params? Try paramoid!
Paramoid is an extension for Rails Strong Parameters that allows to sanitize complex params structures with a super cool DSL, supporting:
- Required params and default values
- A simplified nested structures management
- Conditional sanitization, based on user auth, role or custom logic
- Renaming and remapping parameter names
Add the gem to your Gemfile
gem'paramoid'and run the bundle install command.
Declare a class extending Paramoid::Base.
classPersonParamsSanitizer < Paramoid::Base# @param [User] userdefinitialize(user=nil)params!:first_name,:last_namegroup!:address_attributesdoparams!:id,:road,:town,:state,:zip_code,:countryendendendThen use it in your controller:
classPeopleController < ApplicationControllerdefcreate@person=Person.create!(person_params)endprivatedefperson_params# The name is automatically inferred by the controller namesanitize_params!# Or you can instantiate a custom one# You can pass the current user or nil# CustomPersonParamsSanitizer.new(current_user).sanitize(params)endendParamoid is based on Rails Strong Parameters and it's inheriting its behaviour.
param!is used to permit a single scalar parameter.param! :nameis equivalent ofparams.permit(:name, ...)params!is just a shortcut to sanitize in mass a list of parameters having the same optionsgroup!is used to sanitize objects or arrays, likeparams.permit(my_key: [:list, :of, :keys])array!is an alias ofgroup!and it's added for readability: in Strong Parameters,params.permit(name: [:some_key])accepts both a single object or an array of objects, and this is preserved here.
So the previous example:
classPersonParamsSanitizer < Paramoid::Base# @param [User] userdefinitialize(user=nil)params!:first_name,:last_namegroup!:address_attributesdoparams!:id,:road,:town,:state,:zip_code,:countryendendendIs equivalent to:
params.permit(:first_name,:last_name,address_attributes: [:id,:road,:town,:state,:zip_code,:country])Declaring a parameter as required, will raise a ActionController::ParameterMissing error if that parameter is not passed by to the controller. This also works with nested structures.
classUserParamsSanitizer < Paramoid::Basedefinitialize(user=nil)params!:first_name,:last_name,required: truegroup!:contact_attributesdoparam!:phone,required: trueendendendYou can declare a default value to a certain parameter. That value is assigned only if that value is not passed in the parameters.
Example:
classPostParamsSanitizer < Paramoid::Basedefinitialize(user=nil)param!:status,default: 'draft'param!:approved,default: falseendendInput:
<ActionController::Parameters{"status"=>"published","another_parameter"=>"this will be filtered out"}permitted: false>Output:
<ActionController::Parameters{"status"=>"published","approved":false}permitted: true>You can also remap the name of a parameter.
classPostParamsSanitizer < Paramoid::Basedefinitialize(user=nil)param!:status,as: :stateendendInput:
<ActionController::Parameters{"status"=>"draft","another_parameter"=>"this will be filtered out"}permitted: false>Output:
<ActionController::Parameters{"state"=>"draft"}permitted: true>By using the reference of the current_user in the constructor, you can permit certain parameters based on a specific condition.
Example:
classPostParamsSanitizer < Paramoid::Basedefinitialize(user=nil)params!:first_name,:last_nameparam!:publishedifuser&.admin?endendYou can also use the sanitizer DSL inline directly in your controller:
classPeopleController < ApplicationControllerdefcreate@person=Person.create!(person_params)endprivatedefperson_paramssanitize_params!doparams!:first_name,:last_name,required: trueendendendclassPersonParamsSanitizer < Paramoid::Base# @param [User] userdefinitialize(user=nil)params!:first_name,:last_name,:genderparam!:current_user_id,required: trueparam!:an_object_filteredparam!:an_array_filteredarray!:an_array_unfilteredparam!:roleifuser&.admin?default!:some_default,1group!:contact,as: :contact_attributesdoparams!:id,:first_name,:last_name,:birth_date,:birth_place,:phone,:role,:fiscal_codeendendend- Params type checking and regexp-based validations
Paramoid is maintained by mònade srl.
We <3 open source software. Contact us for your next project!
