Friday, August 15, 2008

Rails, Prototype, Ajax and Forms Walk into a Bar...

Rails is my friend. Prototype is my friend's foreign friend. Ajax is my child-prodigy friend. Forms is my long-time blue-collar friend. Submit buttons are pieces of currency, among many other Internet coins and bills. Recently my friends and I got together at the local web bar to have a beer.

Rails, Prototype and Ajax had been hanging out together lately, and while it seems they knew Forms fairly well, he was kind of old. The other three were younger and getting rich, and so they'd started paying for everyone's drinks. Forms had been buying me beer for a long time, but hadn't had to pull out Submit Buttons very often in their presence since we met the other three. The other day, I asked Forms for a few Submit Buttons to get a beer, but Rails, Prototype and Ajax said they'd take care of it. Forms smiled and said "Fine. Thanks."

I took the Submit Buttons up to the web's bartender, and to my surprise he said they were no good! They were skilled forgeries! They looked like the real thing, but the serial numbers were all the same!

I went back to the table and told my friends. It turns out Rails had suspected they might not be good enough to pass before a scrupulous eye for a few years. Apparently Prototype had been giving them to Rails to help Ajax for a while. Forms pulled out a real Submit Button so I could hold it and the forgery up to the light and compare them.

The deal is that if you use Rails to generate multiple submit buttons on a remote form (ie. for Ajax), regardless of which button is clicked, only the value of the first button is set in the parameters coming into the controller. The issue was documented by Ticket #5031 on Rails-Trac over two years ago. While there was a partial fix put into prototype in 2007, it didn't go far enough to fix the problem.

I played with the prototype code a bit and roughed in a solution, but had an older Firefox on the machine I was using that was incompatible with the latest Firebug. My tests passed, but I was sure they weren't exhaustive. Since I couldn't see what was getting generated under the covers, I didn't trust it enough to use my fix and went back to the web to see what others had done.

I found the solution that I decided to use on Harry's Blog, basically to tuck the value of the submit button that was pressed on an Ajax form into a hidden field. This is done by assigning the onclick of each submit button to some field-setting javascript code. Since this was essentially what I was doing under the covers in the prototype, I was happy.

I sat down and changed the Submit Buttons Rails had given me out of the view of the web bartender. I then gave them to our server who brought me back a nice tall beer. Good times ensued.

I haven't done any wholesale changing on either of my friends Rails' or Prototype's Submit Buttons yet and I hope to avoid it, preferring getting together with my friends in the more comfortable setting of my neighborhood web bar instead of submitting my changes to official scrutiny. For now I'll keep fixing the Submit Buttons locally and just let the officials get to it in their own time.

Time for another beer, eh guys?

No comments: