Rails 7.1.2 upgrade from 7.0.8; form params not parsing

We manually render form fields with names that were recognized by controllers, eg: form_name[foo[bar]], so that we can parse a hash from strong params, params.require(:form_name).permit(foo: {})

Upgrading from Rails 7.0.8 to Rails 7.1.2, this seems to no longer work.

The params variable seems corrupted.

Anyone else seeing this? Or know whats going on?

2 Likes

Well… I found a workaround, at least. We’re using simple_form form builders, and passing field names that reflect a nesting:

simple_form_for :form_name do |f|
   f.input 'foo[bar]'

which used to yield a field name form_name[foo][bar], but which now yields a field name form_name[foo[bar] (which is badly formed and not parsed correctly).

1 Like

I’m running into the same issue. I’ve been looking into the simple_form and actionview gems source code, and it doesn’t seem like the way the name attribute is generated has changed. However, there were some changes made to the actionpack gem where the params are parsed. So still looking…

Did you find a better solution yet?

If anyone else runs into this issue, here is how I dealt with this on my end.

I am using fields_for to nest fields for the form object’s associations. However, since I wanted to avoid using the default _attributes naming default that is inserted to the params, I was doing it by providing an explicit name along with an embedded index, like this:

f.fields_for "custom_param_name[#{foo.id}]", foo do |builder|

This would result in params hash that would look like this: user[custom_param_name[123]][bar], instead of the usual user[custom_param_name][123][bar]. And apparently rails 7.0.8 parses these two params as the same, but rails 7.1.2 parses them differently - as mentioned by @gpassero above.

So I solved this in my case by providing the index via the options hash: (ref)

f.fields_for 'custom_param_name', foo, {index: 123} do |builder|
1 Like

@hananamar excellent tip!

Our workaround was to put the nested context in the form name, with the last component as the field. name:

  = simple_fields_for 'search[filters][state_filter]' do |form_builder|
    = form_builder.input 'value' ....
1 Like

This was a change in Rack 3. If you keep Rack 2 it will work, but form_name[foo[bar]], isn’t really valid and worked by lucky. The workaround you describes is actually the right fix.