Skip to content

Latest commit

 

History

History
213 lines (165 loc) · 5.38 KB

README.md

File metadata and controls

213 lines (165 loc) · 5.38 KB

Tests Gem Version

Paramoid

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

Installation

Add the gem to your Gemfile

gem 'paramoid'

and run the bundle install command.

Usage

Declare a class extending Paramoid::Base.

class PersonParamsSanitizer < Paramoid::Base
  # @param [User] user
  def initialize(user = nil)
    params! :first_name, :last_name

    group! :address_attributes do
      params! :id, :road, :town, :state, :zip_code, :country
    end
  end
end

Then use it in your controller:

class PeopleController < ApplicationController

  def create
    @person = Person.create!(person_params)
  end

  private

  def person_params
    # The name is automatically inferred by the controller name
    sanitize_params!
    # Or you can instantiate a custom one
    # You can pass the current user or nil
    # CustomPersonParamsSanitizer.new(current_user).sanitize(params)
  end
end

param! vs params! vs group! vs array!

Paramoid is based on Rails Strong Parameters and it's inheriting its behaviour.

  • param! is used to permit a single scalar parameter. param! :name is equivalent of params.permit(:name, ...)
  • params! is just a shortcut to sanitize in mass a list of parameters having the same options
  • group! is used to sanitize objects or arrays, like params.permit(my_key: [:list, :of, :keys])
  • array! is an alias of group! 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:

class PersonParamsSanitizer < Paramoid::Base
  # @param [User] user
  def initialize(user = nil)
    params! :first_name, :last_name

    group! :address_attributes do
      params! :id, :road, :town, :state, :zip_code, :country
    end
  end
end

Is equivalent to:

params.permit(:first_name, :last_name, address_attributes: [:id, :road, :town, :state, :zip_code, :country])

Required values

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.

class UserParamsSanitizer < Paramoid::Base
  def initialize(user = nil)
    params! :first_name, :last_name, required: true
    group! :contact_attributes do
      param! :phone, required: true
    end
  end
end

Default values

You can declare a default value to a certain parameter. That value is assigned only if that value is not passed in the parameters.

Example:

class PostParamsSanitizer < Paramoid::Base
  def initialize(user = nil)
    param! :status, default: 'draft'
    param! :approved, default: false
  end
end

Input:

<ActionController::Parameters {"status"=>"published","another_parameter"=>"this will be filtered out"} permitted: false>

Output:

<ActionController::Parameters {"status"=>"published","approved":false} permitted: true>

Name remapping

You can also remap the name of a parameter.

class PostParamsSanitizer < Paramoid::Base
  def initialize(user = nil)
    param! :status, as: :state
  end
end

Input:

<ActionController::Parameters {"status"=>"draft","another_parameter"=>"this will be filtered out"} permitted: false>

Output:

<ActionController::Parameters {"state"=>"draft"} permitted: true>

Conditional parameters

By using the reference of the current_user in the constructor, you can permit certain parameters based on a specific condition.

Example:

class PostParamsSanitizer < Paramoid::Base
  def initialize(user = nil)
    params! :first_name, :last_name
    param! :published if user&.admin?
  end
end

Inline sanitization

You can also use the sanitizer DSL inline directly in your controller:

class PeopleController < ApplicationController
  def create
    @person = Person.create!(person_params)
  end

  private

  def person_params
    sanitize_params! do
      params! :first_name, :last_name, required: true
    end
  end
end

Full Example

class PersonParamsSanitizer < Paramoid::Base
  # @param [User] user
  def initialize(user = nil)
    params! :first_name, :last_name, :gender

    param! :current_user_id, required: true

    param! :an_object_filtered
    param! :an_array_filtered

    array! :an_array_unfiltered

    param! :role if user&.admin?

    default! :some_default, 1

    group! :contact, as: :contact_attributes do
      params! :id, :first_name, :last_name, :birth_date, :birth_place, :phone, :role, :fiscal_code
    end
  end
end

TODOs

  • Params type checking and regexp-based validations

About Monade

monade

Paramoid is maintained by mònade srl.

We <3 open source software. Contact us for your next project!