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?
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
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