Taking the Pain Out of Complex Forms in Rails
July 20th, 2008
The other day I was discussing Rails’ form processing behavior with Ben, when the topic of editing multiple associations in a single form came up. Effectively, he needed to be able to manipulate a collection of records associated with a parent via a has_many association. For each item in this collection, he wanted something like two drop down lists — nothing unreasonable. He said it was similar to recipe 13 from Advanced Rails Recipes — “Handle Multiple Models in One Form” — except that he had to use two fields instead of the one textfield, and it was proving to be surprisingly tough.
I know what you’re thinking: surely this can be extended to more than one form field per item without any problem? Up until I read the code myself a few months ago, I wouldn’t have thought it would be so difficult either — but it’s true. The parameter parsing code is quite quirky and, without reading the detail of the source, borderline unpredictable. I’ve had a few ideas for dealing with more complicated forms in Rails ever since I first ran into this issue. Only recently have I actually gotten around to doing something about it. Here’s an abridged version of an email I just sent to the rails-core mailing list:
Hi,
…
A colleague of mine recently ran into a related problem when dealing with collections of records in Rails forms, which prompted me to finally do something about the parameter parsing behavior. Now, while I’m sure we’re not the only ones hitting this wall, I’m aware that proposals to change to the parameter parsing semantics in Rails is likely to be met with a little caution, hesitation — possibly even terror.
With that in mind, I’ve put up a plugin so everybody can give this a go without having to apply any nasty patches:
http://www.deskchecked.com/git/rails/plugins/form_collections.git
Please see the README (attached) for the full details.
…
Cheers,
Tom
This is a plugin which greatly simplifies the existing Rails parameter parsing code, and makes it a whole lot easier to deal with collections in your forms. I encourage all you Rails developers out there to take a look when you get the opportunity, I’d love to hear your opinions on this one. You can get a copy of the git repository using the following command:
$ git clone \
http://www.deskchecked.com/git/rails/plugins/form_collections.git
UPDATE: Here’s the contents of the README file:
UPDATE 2: Removed the README: looks terrible in the new design due to space restrictions.
Categories: Ruby, Software Development |



So this new rails edge feature helps you?
http://ryandaigle.com/articles/2008/7/19/what-s-new-in-edge-rails-nested-models
Yep, Koz pointed this out on the mailing list. And yes, it’s dealing with part of the same problem. But the parsing itself is the big thing here:
Try building a form to generate :phone_numbers using edge. It’s not a matter of just using “user[phone_numbers][]” or “user[phone_numbers][0]“. The former won’t work because a “PhoneNumber” has two fields. The latter, because it builds a Hash instead of an Array. The existing form parsing code will limit the usefulness of this new capability.
I’m having trouble cloning the plug-in with git, and when I click the link to the repo, I receive a 403 error. Any suggestions?
I’ve been looking for a fix to this problem for months, and attempted writing my own hacked UrlEncodedPairParser with little success. I’ve tested this plugin in my application and it seems to work perfectly, even with multilevel nested arrays by adding an index option to the block params of the form helper.
Might need some hacking to work with Javascript added elements such as in Ryan’s complex forms recipe.
I would love to see this functionality in Rails 2.2
Eric: is it any better now? Migrated from lighttpd to Apache and I screwed up the configuration.
Ivan: Glad you found it useful.
It’s been a thorn in my side a few times in the past.
[...] UPDATE Since I wrote this post, I’ve written a plugin that replaces Rails’ parameter parsing implementation to make dealing with complex nested forms easier still. Refer to Taking the Pain Out of Complex Forms in Rails. [...]
Yep, was able to get it. Works great, too! Thanks
Thanks!
But it looks like the repository is invalid:
/usr/bin/git-clone: 374: curl: not found
—
git clone http://www.deskchecked.com/git/rails/plugins/form_collections.git
Initialized empty Git repository …
git clone \
http://www.vector-seven.com/git/rails/plugins/form_collections.git
Hi Val,
It worked for me:
–
$ git clone http://www.deskchecked.com/git/rails/plugins/form_collections.git
Initialized empty Git repository in /home/tom/code/form_collections/.git/
Getting alternates list for http://www.deskchecked.com/git/rails/plugins/form_collections.git
Getting pack list for http://www.deskchecked.com/git/rails/plugins/form_collections.git
Getting index for pack 86313bbb9653e23f9e0147b999855b2eef4c0cb9
Getting pack 86313bbb9653e23f9e0147b999855b2eef4c0cb9
which contains ffbc5e77cb080323d6c303f533f8d73f4c69cecc
walk ffbc5e77cb080323d6c303f533f8d73f4c69cecc
walk b8c333aca41f1ba5cb8498a7d738c200edf43e61
walk e54adf67ab1acf4af42324e1a896747b8624f8df
walk 6df788f2baeef083c9f2ad8ae2acb1a5de6c09e9
walk d59a3df8129589e1c77d7e07172e8cfbdcc8b0af
walk d5ed70379c78f1f0909ba05994aeb9a44230dcfa
walk 41ecbabcecde4e81afda5735e01f2769e194552a
walk d5fe0450fb9dea98a36488bef802b467329e5c58
$ cd form_collections
$ ls
init.rb lib Rakefile tasks uninstall.rb
install.rb MIT-LICENSE README test
$
–
Judging by that git-clone error (”curl not found”) you may need to install curl or something. Check your git installation, or drop me an email if you continue to have problems.
I’ve used your form_colletions plugin with great success with Rails 2.1.0. I’m now looking into Rails 2.3.2 and wonder if I can just remove your plugin and Rails will understand/parse the same data as your plugin did? When I try to start up the app, I get “uninitialized constant ActionController::AbstractRequest” and I can trace it back to the patch_url_encoded_pair_parser.rb on the line where your class is declared: “class ActionController::AbstractRequest::UrlEncodedPairParser”
@Randy, glad you found the plugin useful. I’ve not tried migrating from 2.1.x to 2.3.x myself, but the old Rails parameter parsing code has been completely stripped out. You’ll find the new parameter parsing code in the glue code for rack. Unfortunately the new semantics don’t match the form_collections semantics exactly, so you may need to go to the effort of porting it unfortunately. I’ve tried and tried to push the semantics in the plugin, but it fell on deaf ears. Somewhat understandable from their perspective (i.e. they’re trying not to break stuff), but IMO a mistake from a practical point of view.
From what I understand it seems that they’re going to stick with the old semantics (i.e. foo[0]=1 parses to {:foo => { 0 => 1 }}), except the parser will actually *work* for more complex forms. Once Ruby 1.9 goes mainstream with its out-of-the-box ordered implementation of Hash, this should be more-or-less what you want anyway. Until then, I’m not sure what they plan to do or if they’ve resolved all the issues I raised regarding the old parameter parsing code.
Anyway, let me know if you get stuck.