Today I Learned

Rails 4 Strong Parameters Gotcha: Array in Params

When using strong parameters in Rails 4, any non-scalar parameters must be permitted using a special syntax. The following example is for when you are passing in an array of scalar values in a request parameter (and you are using Rails 4 Strong Parameters to whitelist the parameter).

Firstly, note that the following will not work (i.e. the spec will fail):

# routes.rb
post '/thing/create' => 'thing#create'

# thing_controller_spec.rb
RSpec.describe ThingController, type: :controller do
  example do
    post :create, things: [1, 2, 3]

    expect(response.body).to eq('1,2,3')
  end
end

# thing_controller.rb
class ThingController < ApplicationController
  def create
    permitted_params = params.permit(:things)
    render inline: permitted_params[:things].join(',')
  end
end

Why does it fail? Rails is expecting a scalar value to be passed in the :things parameter. However, we pass in an array, so Rails silently removes the parameter, even though it is included in the call to params.permit.

In order to make the spec pass, we update the implementation as follows:

# thing_controller.rb
class ThingController < ApplicationController
  def create
    permitted_params = params.permit(things: [])
    render inline: permitted_params[:things].join(',')
  end
end

For more info about strong parameters, especially in regards to how to permit non-scalar and nested parameters, please refer to: https://github.com/rails/strong_parameters#permitted-scalar-values.