Edit in place is a handy feature where clicking on an area of a web page replaces that portion of the page with a form which will enable the user to update that information. At one time, this was a part of Rails, but in 2007 it moved out to a plugin, and improved upon. The one that looked like it most closely matched my needs was REST in Place. It comes in three flavors, I picked JQuery.

URLencoding

The first issue I had was that I would not be able to authenticate, despite carefully following the instructions for setting a rails_authenticity_token. Looking at it from the server logs, it appeared that the token received had a space in it. Looking at it from the client, I found a plus in the same place. Looks like request wasn’t properly x-www-form-urlencoded. Looking at the source (line 18) verifies this to be the case. A call to encodeURIComponent would solve this. So would a call to CGI.escape in the assignment to rails_authenticity_token. The former seems like the “right” way, but instead of modifying the gem, I decided to take the latter approach for now.

It is not clear to me why this problem wouldn’t affect others enough to have been noticed and fixed.

JSON

Once this was fixed, I could edit information in place. The trouble is that the formatting was lost after the edit. The information I was editing at the time was a dollar amount, something that I format with number_to_currency. It seems that under the covers, after an update is made, the information is re-fetched using JSON and that’s the information that is displayed. That information is “raw” and essentially straight from the database. My first attempt to address this was to create new attributes which were not backed by the database; but by default such attributes are not included in the JSON so instead of simply losing the formatting, now I lost the result entirely. This could be addressed, but I decided to go back to the original attributes, and centralize the formatting.

This allows fields to be declared as dollarized, after which point all formatting is taken care of automatically, and all other basic numeric functionality is delegated back to the original Float.

Kinda odd to have ApplicationHelper included within a model, but the amount of lines of code went down, processing became more consistent, so this was totally a net plus.

Caching

Now that the basic functionality worked, I noticed something odd. If after doing an in-page-edit I clicked on a link and subsequently clicked on the back button, I was presented with JSON instead of the HTML page I was expecting.

I’m not totally sure what is going on here, as the server was properly sending private, max-age=0, must-revalidate as the cache control header. The only thing I can figure is some oddity with Firefox 3.0.11 with XMLHttpRequeset and https sessions. I’m not a big fan of conneg for this reason. When it works, it is very useful. When it doesn’t, it is often difficult to diagnose and debug.

But I have a known workaround. By appending a question mark to the URI used for XHR, the client sees it as a different resource and the server processes it the same.

Helper

Wanting to apply the same workaround consistently across my application was the tipping point. The markup rest_in_place wasn’t all that complicated, but was repetitive. Time for a helper function:

Attributes

One final note, only of interest to pedants. The markup above is not conformant in that it invents new attributes. In order to satisfy the markup orthodoxy, I’d suggest modifying RIP to accept synonyms for each attribute that happen to start with data-. I would certainly use it on all public facing websites that made use of this feature. As to what I use on my own private network, that’s between me and my server.

Sun 14 Jun 2009

Hey Sam,

thanks for your suggestions. I’ll try to implement them as soon as I find the time
(finishing my diploma thesis currently). If you already made the changes, I’d be very
glad for patches (or fork and send a pull request).

Not all of these were suggestions, and the topic of formatting requires more thought; but I will fork, make changes, and send a pull request when complete. At the very least, some of these items can be added to the documentation.

Sam, re. caching issue, see bug 388141. No attention in the 2 years since I filed it. Not even confirmed.

Mark: yes. Firefox ignores it.

If I look at that list of issues, I’d suggest you try entering some non-US-ASCII characters next (e.g. a € euro sign), it seems to be the next thing to expect not to work. Too often people pay too little attention to escaping and encoding :(.

So to make things clear, as I see in this particular case a Vary header is not sent: adding a Vary header, although it of course should be there, will make no difference to Firefox’s cache and the issue will still be there.