I have a rails application that stores a serialized hash in a field called properties
.
The hashes keys are unknown though, so I don't know of a way to allow this with strong parameters.
When googling, I found this: https://github.com/rails/rails/issues/9454, but I couldn't figure out exactly what a solution would be.
So basically, my question is: How can you configure strong parameters to allow hashes with unknown keys?
Thanks for all help!
I recently had this same issue and I solved it using @fxn's method from https://github.com/rails/rails/issues/9454
For product with properties
as hash, solved it as
def product_params
params.require(:product).permit(:title, :description).tap do |whitelisted|
whitelisted[:properties] = params[:product][:properties]
end
end
If you use :raise
instead of :log
for config.action_controller.action_on_unpermitted_parameters
in your environment
then remember to remove properties
from params
before calling permit
. Then the method will be
def product_params
properties = params[:product].delete(:properties)
params.require(:product).permit(:title, :description).tap do |whitelisted|
whitelisted[:properties] = properties
end
end
None of these answers worked for me (using Rails 4.2.4), so I figured out the following workaround:
def product_params
properties_keys = params[:product][:properties].keys
params.require(:product).permit(:title, :description, properties: properties_keys)
end
Hope that helps someone.
You can use a hash instead of a symbol and define what sub-properties are allowed. This can be seen in the source here:
case filter
when Symbol, String
permitted_scalar_filter(params, filter)
when Hash
hash_filter(params, filter)
end
https://github.com/rails/rails/blob/bdc73a438a97f2e0aceeb745f4a95f95514c4aa6/actionpack/lib/action_controller/metal/strong_parameters.rb#L522
e.g.
def user_params
params.require(:person).permit(:name, :description, :age, properties: [:key, :value])
end
If you have no idea what is going to be in properties
you could use .slice. Note this will accept anything nested in any of the other fields too.
e.g.
def user_params
params.require(:person).slice(:name, :description, :age, :properties)
end
These approaches will work on the following params:
{
"person": {
"name": "John",
"description": "has custom_attributes",
"age": 42,
"properties": [
{
"key": "the key",
"value": "the value"
}
]
}
}
I've confirmed these will work on Rails 4.2.6
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With