A Developer with a Pencil

Strong Parameters Just Got Nicer

Strong Parameters in a nutshell, is an interface for protecting attributes from end-user assignment. This makes Action Controller parameters forbidden to be used in Active Model mass assignment until they have been whitelisted.

Long story short, before you can use the request parameters - you have to whitelist them to prevent your end-user or any other evil conductor - to cause havoc and change things they aren’t allowed to in your databases.

Up until now the way to do this was to create a method that whitelists the incoming params list, something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  class UsersController < ActionController


    def new
      @user = User.new
    end

    def create

      # Here we are using the parameter whitelisting method
      @user = User.new(user_params)
      if @user.save
        redirect_to users_url, notice: "User created"
      else
        render :new
      end
    end


    private

    # Parameter whitelisting method
    def user_params
      params.require(:user).permit(:name, :age)
    end
  end

Now that is absolutely a better approach for whitelisting attributes than the previous standard of attr_accesible and attr_protected, this logic belongs in the controller no doubt - but why do I need to code that whitelisting method manually and I don’t have a way to set this up nicely like action filters or validations?

Introducing: BetterStrongParams

BetterStrongParams adds a DSL to ActionController that allows to add strong params filtering without adding a specific, dirty controller method. Simple.

Installation

Add this line to your application’s Gemfile:

gem 'better_strong_params'

And then execute:

$ bundle

Or install it yourself as:

$ gem install better_strong_params

Setting up

BetterStrongParams is automatically included in ActionController::Base, so you don’t actually need to do anything to set this one up.

Usage

BetterStrongParams allows you to use the filter_parameters method in your controllers:

1
2
3
  class UsersController < ApplicationController
    filter_parameters create: {post: [:title, :body]}, ...
  end

filter_parameters accepts an option hash specifing a method name, a required parameter and a permitted parameters list like this

1
  controller_action_name: {required_param_name: [permitted1, permitted2,...]}, controller_action_name2: ....

for every controller action you set using filter_parameters, a method named #{controller_action}_params will be created and will be ready to use when you want it.

Full example

1
2
3
4
5
6
7
8
9
10
11
12
13
  class UsersController < ApplicationController

    filter_parameters create: {post: [:title, :body]}

    def create
      @user = User.new(create_params) # => create_params is available via BetterStrongParams and the filter_parameters DSL.
      if @user.save
        redirect_to treasure_url
      else
        redirect_to jail_url
      end
    end
  end

Contributing

Forks and feedback are always welcome.

Comments