Multiple Ajax Form Submissions in Rails

17 Jul 2007 In: Technobabble

It has been a while since I have written, but I ran across this age old problem in Rails today and wanted to share my simple solution. Users that double click on submit forms, or multi click when things don’t happen fast enough for them, wreak havoc on web applications. In order to prevent the data from being submitted more than once, there are a variety of approaches, here is mine.

The Ruby (Rails)

In addition to form submission, occasionally we want to throttle down Ajax invoking links to single clicks at a time as well. To accomplish this, we need to look at our use of link_to_remote and form_remote_tag (though this would work for all methods that support link_to_remote options).

  1. # form_remote_tag
  2. <% form_remote_tag (:url => {:action => "save_stuff"},
  3.     :condition => "ajax_in_use == false",
  4.     :before => "ajax_in_use = start_ajax(ajax_in_use)",
  5.     :complete => "ajax_in_use = end_ajax(ajax_in_use)",
  6.     :html => {:id => "html_id_for_form"}) do -%>
  7.  
  8.     # form goes here...
  9. <% end -%>
  10.  
  11.  
  12. #link_to_remote
  13. <%= link_to_remote "click me for ajax",
  14.     :url => {:action => "ajax_method_in_controller",:object_id => this_object.id, :additional_url_parameter => true},
  15.     :condition => "ajax_in_use == false",
  16.     :before => "ajax_in_use = start_ajax(ajax_in_use)",
  17.     :complete => "ajax_in_use = end_ajax(ajax_in_use)"
  18. %>

The things to pay attention to here are :condition, :before and :after. The condition determines whether the call to the back end may be sent, which is controlled through a JavaScript boolean. The :before hook sets the JavaScript variable to show that it is use, and the :after hook releases it. Why not just set the variable to true or false? Using a function allows me to layer in additional behavior to make a more pleasant user experience.

The JavaScript

Now that we have our hooks in place, we need to define the JavaScript functions and variables that are being used. These are all included in an external JavaScript file that is included in the layout.

  1. // initialize ajax state
  2. var ajax_in_use = false;
  3.  
  4. // turn ajax calls off
  5. function start_ajax(ajax_in_use) {
  6.     document.body.style.cursor = 'wait';
  7.     return true;
  8. }
  9.  
  10. // allow ajax calls
  11. function end_ajax(ajax_in_use) {
  12.     document.body.style.cursor = 'default';
  13.     return false;
  14. }

As a small nicety, I change the cursor to ‘wait’ while the Ajax calls execute, helping clue the user in that something is happening. The functions also allow a nice way to do something more complicated in the future. There, thats all there is to it. It isn’t fancy or clever, but it seems to work well so far.

Micropayments for Premium Software

12 Jun 2007 In: Observations, Opinions

I was thinking about the fact that, yet again, there is a new version of Adobe Photoshop out, version CS3. For their standard package, a new user has to swallow a $649 price tag to get in the door. If you are lucky enough to have an older version, you can get into the upgrade for $199. CS2 was released almost exactly one year prior to CS3.

This got me thinking about software prices in general, but I will stick with Photoshop for this example. My guess is that Photoshop has one of the highest percentages of piracy in it’s install base. Adobe gets nothing from those people. A certain portion of those pirates are going to steal it regardless of the price tag, because that’s what they do. I can’t help but wonder, however, how many people say “$650! Screw that!” and hop onto a file sharing network, cutlass gripped mercilessly between their clenched teeth.

Of that latter group, I would guess that some percentage would be willing to buy it if the price tag weren’t so high. So how could Adobe lower that price bar and net the cash from these pirates? Since the upgrade is $199, and the release cycle appears to be 12 months, you are essentially paying $16.60 for the new hotness. Why not offer a service at $20 a month to use the software, possibly with some larger lump payment to get going ($50). Now someone only has to come up with $70 to get into their product instead of $649.

Now the real benefits kick in. Instead of waiting a year for new features, they can roll them out in real time as they are developed, creating a more agile product for their customers. They could also experiment, tossing in features here and there on a trial basis, without some delicate, long impacting consequences.

If adoption of this practice took off, they could even lower the price to grab ever increasing percentages of those fence dwelling pirates, until the inconvenience of finding and implementing the pirated software overshadows the barrier to just plain purchasing it.

Until then, bon voyage!

CSS Indentation

11 Jun 2007 In: Technobabble

I realized today that there is something that I have been doing with Cascading Style Sheets (CSS) for some time that, while it seemed obvious to me, has turned out to be helpful for others. For most web developers, CSS is a straight, static file with definition after definition. Good little programmers will at least provide comments to separate sections or specify the purpose of obscure classes, but thats about it. About the time I switched to pure CSS layouts, and JavaScript free drop down menus (a la suckerfish), I noticed my CSS was getting unmanageable. Go back and look at a style sheet you hacked together last year and see how clear it is to you now.

We indent code for clarity, why not CSS? “But CSS isn’t structural!” you say, “there is no clear way to determine what should nest what”. That is true, but that doesn’t deter me. Layout stuff is easy, since it closely parallels your HTML, which is quite structured.

Consider the following HTML:

  1. <div id="container">
  2.     <div id="left_panel">
  3.         <span class="left_panel_header">I'm so, like, left</span>
  4.         <h4>Some Stuff:</h4>
  5.         <ul>
  6.             <li>One</li>
  7.             <li>Two</li>
  8.             <li>Three</li>
  9.     </div>
  10. </div>

Your CSS could look like this:

  1. #container {
  2.     background-color: #336699;
  3.     color: #ffffff;
  4. }
  5. #left_panel ul li {
  6.     text-indent: 20px;
  7.     font-weight: bold;
  8. }
  9. h4 {
  10.     color: #00FF00;
  11.     text-align: right;
  12. }
  13. #left_panel ul {
  14.     margin: 0;
  15.     padding: 0;
  16. }
  17. #left_panel {
  18.     float: left;
  19.     border: 1px solid #AACC00;
  20. }
  21. html, body {
  22.     font-family: Georgia;
  23. }

Now, there certainly isn’t anything wrong with the above CSS, it’s quite functional. However, over time it will become hard to read, and subsequent modifications will take more and more time. This is how I would create it:

  1. /* "header" definitions */
  2. html, body {
  3.     font-family: Georgia;
  4. }
  5. /* Page container */
  6. #container {
  7.     background-color: #336699;
  8.     color: #ffffff;
  9. }
  10.     /* Left Panel */
  11.     #left_panel {
  12.         float: left;
  13.         border: 1px solid #AACC00;
  14.     }
  15.  
  16.         /* left panel menu */
  17.         #left_panel ul {
  18.             margin: 0;
  19.             padding: 0;
  20.         }
  21.  
  22.             #left_panel ul li {
  23.                 text-indent: 20px;
  24.                 font-weight: bold;
  25.             }
  26.  
  27. /* Global style definitions */
  28. h4 {
  29.     color: #00FF00;
  30.     text-align: right;
  31. }

As you can see, this is much easier to read. As soon as you start analyzing the CSS that defines what is in that left panel, everything sort of makes sense. Likewise, our override for H4 has nothing to do with the left panel, so it is aggregated into a lower section of the CSS. Had we defined #left_panel h4 {}, I would have put in the indented portion for the left panel. And of course, our comments will make sure that 6 months from now, when I am asked to update the CSS for the page, I can do it with little trouble. Comment well, and comment often. Comments and whitespace are free!

For the past few years I have taken this for granted, but now that I think back, every web developer that has seen my style has adopted it for themselves, which means it at least merits sharing. Hopefully this will help a few of you, especially the ones that write hundreds of lines of CSS.

To Mock Or Not To Mock

5 Jun 2007 In: Technobabble

Testing. For most developers, it lurks like a cancer in the back of our brains. You know you should be writing tests, and you should be writing them now, but… well, let me just get this thing working first. At RailsConf I attended several talks, and a tutorial, on testing. While I didn’t get much in the way of concrete knowledge to get started writing tests, I did drink the testing Kool-Aid and I am on my way to becoming a Test Driven Development/Behavior Driven Development advocate.

All of that said, I don’t have enough experience writing tests to be an expert, but this conversation I had today seemed worthy of sharing. When do you use a mock. I uttered a phrase that received a lot of head nods towards the tail of the conversation:

“Mocks are bug aggregators”

If you decide to use mocks in your testing, you are essentially saying “I have no way of testing this for real” or “This is too hard/time consuming/boring right now”. That isn’t to say that mocks dont have their uses, like mocking data that comes to or from a remote system, but they don’t actually test true functionality. If they did, we wouldn’t call them mocks.

What a mock does is create a choke point for aggregating bugs. If you don’t have time to write tests for part of your system, you can mock it, and then when bugs arise that slip past your tests, you have a good idea where to start looking. Of course, good little programmer girls and boys will write tests instead of mocks, but sometimes reality usurps idealism.

Homesick

5 Jun 2007 In: Family, Miscellaneous

In some sort of cosmic intersection of experience and psychology, both Amy and I are very homesick today. While my work at Vonage is going very well, we miss the closeness of our friends and family in Colorado. For cathartic purposes, here is a small list of the things I am missing during this slice of consciousness:

The Band Marches On… With Extra Action

20 May 2007 In: Reviews

After the display put on by the Extra Action Marching Band outside the exhibit hall at RalsConf yesterday, we couldn’t help ourselves. We headed out to a little club called Dante’s across the Burnside bridge and caught their evening act. Dante’s served as the perfect venue for XA, exposed brick and rebar basqued in a red glow with elevated platforms and a big stage. The place was crowded, but not too crowded, which is important since they spend the majority of the time meandering through the crowd and interacting with them. The whole thing was quite cathartic, unjarring some deeply rooted gunk that was contaminating my soul. I feel reborn. Some highlights, and lowlights, from the experience:

  • Getting soaked in champagne sprayed out of bottles from the majorettes
  • Looking down to realize a majorette was on her hands and knees crawling between my legs
  • Watching the tuba player charge headfirst, with instrument, into the impromptu mosh pit
  • Deviant, clothed, mock sexual acts
  • An unfortunate full blown view of the male majorette’s… little majorettes
  • Several costume changes
  • Tight sound in spite of the band members being separated in a sea of dancing club-goers

All in all it was quite an experience, but not for the conservative of feint of heart. If they come your way, definitely check them out. You can see their touring schedule here

Vonage Open Source: ActiveREST

19 May 2007 In: Technobabble

I spoke today at RailsConf regarding the REST related stuff I have been doing at Vonage. RubyForge seemed to have blocked traffic coming from the convention center, so unfortunately I didn’t have everything in shape to share during the presentation. For those of you who are interested, you can find ActiveREST here:

ActiveREST web site (just a placeholder for now)
ActiveREST project page on RubyForge

When I get home I will tweak my presentation a little and post it here, so look for that soon. Thanks to everyone who attended.

Extra-Action Marching BandSo after the morning sessions were finished at RailsConf, there was suddenly a burst of noise from the lobby outside the presentation hall. It… it was a marching band. I couldn’t see them, so I went outside and down to a lower door, but I admit I was not prepared for what I saw. The Extra-Action Marching Band is like an erotic, punk rock marching band. They must have been crashing, because the convention people seemed pretty annoyed with them. There’s really nothing quite like a marching band, especially one that comes with extra action.

Check out the Extra-Action Marching Band website. They are playing at a club tonight, maybe we will go check it out!

RailsConf 2007 Scheduling Application

20 Apr 2007 In: Technobabble

The RailsConf 2007 website recently posted the schedule for sessions (My session is at 4:25pm on Saturday). As the RailsConf-bound people at Vonage started talking about what they wanted to see, I thought it would be nice if they had a scheduler application so that you could make your selections. Even more, it would be nice if you had a way to compare those schedules once they are created. Well, why would I wait for them to do it when I can do it myself? Without further ado, I present to you:

RailsConf 2007 Scheduling Application

It was a bit of work getting it going, mostly because I had trouble getting a Rails application running on Dreamhost, and configuring ActionMailer. It seems to be working pretty well now. One thing to note is that I got the data for sessions by scraping the RailsConf scheduling page (liked above). If that page changes, then my application will be out of date. Please contact me if you notice that particular event occurring. Once you create a schedule you will get a key, and then you can compare schedules by entering someone else’s key. It is pretty self explanatory. Take a look and let me know what you think!

The Thing About Vonage…

13 Apr 2007 In: Opinions

Before you read this, I want to toss in a disclaimer that this is only my opinion, not the opinion of Vonage or anyone affiliated, blah blah blah…

Most of you know that I work for Vonage as a web developer. With the amount of attention that Vonage has gotten in the news lately, I thought I would take a moment to clarify a few things. Most of the mainstream media outlets have already pronounced us as dead and moved on. The problem is they don’t really understand the intricacies of patent litigation, and they are too lazy to keep track of what was going on. The Vonage website has a page devoted to explaining how the lawsuits will impact existing customers.

Here is the real deal.
Read the rest of this entry »