Leantraxxx
Leantraxxx

Reputation: 4596

Strong parameters and multidimensional arrays

I'm using Rails 3.2.6 with strong parameters gem.

So, I' have a controller with the typical update action:

# PUT /api/resources/:id
def update
  @resource.update_attributes! permited_params
  respond_with_json @resource, action: :show
end

Then, I have the permited_params method

def permited_params
  params.permit(:attr1, :attr2, :attr3)
end

The problem is that :attr3 is a multidimensional array like this: [[1, 2], [2, 5, 7]]

Following the documentation, I need to specify :attr3 as an array. But...

params.permit(:attr1, :attr2, :attr3 => [])
#inspecting permited_params: {"attr1"=>"blah", "attr2"=>"blah"}

params.permit(:attr1, :attr2, :attr3 => [[]])
#inspecting permited_params: {"attr1"=>"blah", "attr2"=>"blah", "attr3" => []}

params.permit(:attr1, :attr2, :attr3 => [][])
#throw error

The question is: How can I use strong params with multidimensional arrays?

Upvotes: 8

Views: 1720

Answers (2)

Paritosh Piplewar
Paritosh Piplewar

Reputation: 8122

You can also do this in this way

   def permited_params
     hash = params.permit(:attr1, :attr2) 
     hash[:attr3] = params.require(:attr3) if params.has_key?(:attr3)
     hash
   end

Upvotes: 5

Paritosh Piplewar
Paritosh Piplewar

Reputation: 8122

I was seeing this type of question many times so i though to dig into the code and find the reason and make it work.

It turns around that whatever written in documentation is correct. This is from strong parameter documentation.

The permitted scalar types are String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile and Rack::Test::UploadedFile.

This scalar values are inside stored in ::ActionController::Parameters::PERMITTED_SCALAR_TYPE

If you see its value, you will find that it doesn't accept Array as value .

To make this work, all you need to do to add Array into whitelist, i.e if you do

::ActionController::Parameters::PERMITTED_SCALAR_TYPE << Array

it will work. But this is bad solution. I'm not the strong_parameter contributor so i am not aware of security risks. So, to solve this problem all you have to do is to include method in your controller something like this

def allow_array_in_strong_parameter
  old_scalar_types = ::ActionController::Parameters::PERMITTED_SCALAR_TYPES.dup
  ::ActionController::Parameters::PERMITTED_SCALAR_TYPES << Array
  params.permit(:attr1, :attr2, :attr3 => [])
  ::ActionController::Parameters::PERMITTED_SCALAR_TYPES = old_scalar_types
end

Upvotes: 3

Related Questions