Free Lock on Single Mysql Table Row

We ran into a problem today where a single row in one of our tables seemed to get stuck in a state where any query that tried to update it would hit our lock wait timeout of 50 seconds. I googled and googled to try to figure out a straightforward way to release this lock, but the closest thing I could find was a big assed Mysql page on table locks that lacked any specific solutions and this Stack Overflow post that suggests fixing a similar problem by dropping the entire table and re-importing it (uh, no thanks).

After some trial and error, I came up with two viable ways to track down and fix this problem.

The first way is to actually look at Mysql’s innodb status by logging into your Mysql server and running

show innodb status\G

This will list any known locks by Mysql and what it’s trying to do about them. In our case, the locked row did not show up in the innodb pool status, so instead I executed

show processlist;

This listed everything that currently had a connection open to Mysql, and how long it’s connection has been open for. In Rails it is a bit hard to spot which connection might be the one to blame, since every Rails instance leaves its connection open whether it is waiting for a transaction to complete or it is doing nothing. In today’s case, I happened to have a good hunch about which of the 50 connections might be the problem one (even though it was listed as being in the “sleep” state…strangely), so I killed it by restarting the server, and all was well. However, I could have also killed it using:

kill process [process id];

If you don’t happen to know which of your processes has done the lock, the only recourse I know would be to restart your servers and see which Mysql processes remain open after the servers have reset their connections. If a process stays connected when it’s parent has left, then it is your enemy, and it must be put down. Hope this methodology helps someone and/or my future self.

Rails 3 Autoload Modules/Classes – 3 Easy Fixes

Judging by the number of queries on Stack Overflow, it is a very common problem for folks using Rails 3 that they are not getting the modules or classes from their lib directory loaded in Rails 3, especially in production. This leads to errors like “NoMethodError,” “No such file to load [file in your lib path],” and “uninitialized constant [thing you’re trying to load].” From the information I canvassed trying to solve the problem this morning, there are three common reasons (and one uncommon reason) that this can happen. I’ll go in order of descending frequency.

1. You haven’t included the lib directory in your autoload path

Rails 3 has been updated such that classes/modules (henceforth, C/M) are lazy loaded from the autoload paths as they are needed. A common problem, especially for the newly upgraded, is that the C/M you are trying to load isn’t in your autoload path. Easy enough fix:

config.autoload_paths += Dir["#{config.root}/lib/**/"]

This will autoload your lib directory and any subdirectories of it. Similarly, if you have model subdirectories, you may need to add

config.autoload_paths += Dir["#{config.root}/app/models/**/"]

To your application.rb file.

2. Your C/M is not named in the way Rails expects

Rails has opinions about what the name of your C/M should be, and if you name it differently, your C/M won’t be found. Specifically, the namespace for your C/M should match the directory structure that leads to it. So if you have a C/M with the filename “search.rb” in the lib/google directory, it’s name should be “Google::Search.” The name of the C/M should match the filename, and the name of the directory (in this case “Google”) should be part of the namespace for your module. See also this.

3. Your application is threadsafe.

This was one that was hard to find on SO or Google, but if you have configured your application to be threadsafe (done by default in production.rb), then the C/Ms you have, even if they exist in your autoload path, will not be defined until you require them in your application. According to the Rails docs, there is apparently something not threadsafe about automatically loading the C/Ms from their corresponding files. To workaround this, you can either require your individual library files before you use them, or comment out config.threadsafe!

4. (Esoteric) You have a model in a subdirectory, where the name of the subdirectory matches the name of the model.

Yes, this is another error we actually had when upgrading from Rails 2 to 3: as of Rails 3.0.4 there is a bug wherein, if you have a directory app/models/item and you have the file “item.rb” in your app/models/item directory, then you will get errors from Rails that your models are undefined (usually it picks the second model in the item subdirectory). We fixed this by just renaming our subdirectories where appropriate. Hopefully in one of the next versions of Rails this will get fixed and no longer be a possible problem.

Had other reasons why C/Ms failed to load for you? Do post below and we can gather up all the possibilities in one tidy location.

Traits & Qualities of Best Developers on a Deserted Island

What is programming perfection? While the qualities that comprise “the most productive” developer will vary to some extent based on industry and role, I believe there are a number of similarities that productive developers tend to share. Understanding these similarities is a key to improving oneself (if oneself == developer) or differentiating from a pool of similar-seeming developer prospects. In my assorted experience (full time jobs in Pascal, C, C++, C#, and now Ruby (damn I sound old)), I have repeatedly observed developers who vary in productivity by a factor of 10x, and I believe it is a worthwhile exercise to try to understand the specifics behind this vast difference.

<OBLIGATORY DISCLAIMER>

I do not profess to be kid-tested or mother-approved (let alone academically rigorous or scientifically proven) when it comes to prescribing what exactly these qualities are. But I do have a blog, an opinion, and an eagerness to discuss this topic with others. I realize this is a highly subjective, but that’s part of what makes it fun to try to quantify.

</ OBLIGATORY DISCLAIMER>

As a starting point for discussion, I hereby submit the following chart which approximates the general progression I’ve observed in developers that move from being marginally productive to absurdly productive. It works from the bottom (stuff good junior programmers do) to the top (stuff superstars do).

Levels of Developer Productivity

And here is my rationale, starting from the bottom:
mario_1

Level 1: Qualities possessed by an effective newbie

Comments on something, somewhere. A starting point for effective code commenting is that you’re not too lazy or obstinate to do it in principle.

Self-confident. Programmers that lack self-confidence can never be extremely effective, because they spend so much time analyzing their own code and questioning their lead about their code. That said, if you’re learning, it’s far better to know what you don’t know than to think you do know when you really don’t. So this one can be a difficult balance, particularly as coders grow in experience and become less willing to ask questions.

Abides by existing conventions. This is something that new coders actually tend to have working in their favor over veterans. On balance, they seem to be more willing to adapt to the conventions of existing code, rather than turning a five person programming project into a spaghetti codebase with five different styles. A codebase with multiple disparate conventions is a subtle and insidious technical debt. Usually programmers starting out are pretty good at avoiding this, even if their reason is simply that they don’t have their own sense for style.

Doesn’t stay stuck on a problem without calling for backup. This ties into the aforementioned danger with being self-confident. This is another area where young programmers tend to do pretty well, while more experienced coders can sometimes let themselves get trapped more frequently. But if you can avoid this when you’re starting, you’re getting off on the right foot.

mario_2

Level 2: Qualities possessed by an effective intermediate programmer

Understand the significance of a method’s contract. Also known as “writes methods that don’t have unexpected side effects.” This basically means that the developer is good at naming their functions/methods, such that the function/method does not affect the objects that are passed to it in a way that isn’t implied by its name. For example, when I first started coding, I would write functions with names like “inflictDamage(player)” that might reduce a player’s hitpoints, change their AI state, and change the AI state of the enemies around the player. As I became more experienced, I learned that “superfunctions” like this were not only impossible to adapt, but they were very confusing when read by another programmer from their calling point: “I thought it was just supposed to inflict damage, why did it change the AI state of the enemies?”

Figures out missing steps when given tasks. This is a key difference between a developer that is a net asset or liability. Often times, a level 0 developer will appear to be getting a lot done, but their productivity depends on having more advanced programmers that they consult with whenever they confront a non-trivial problem. As a lead developer, I would attempt to move my more junior developers up the hierarchy by asking “Well, what do you think?” or “What information would you need to be able to answer that question?” This was usually followed by a question like, “so what breakpoint could you set in your debugger to be able to get the information you need?” By helping them figure it out themselves, it builds confidence, while implicitly teaching that it is not more efficient to break their teammates’ “mental context” for problems that they have the power to solve themselves.

Consistently focused, on task. OK, this isn’t really one that people “figure out” at level two, so much as it is a quality that usually accounts for a 2x difference in productivity between those that have it and those that don’t. I don’t know how you teach this, though, and I’d estimate that about half of the programmers I worked with at my past jobs ended up spending 25-50% of their day randomly browsing tech sites (justified in their head as “research?”). Woe is our GDP.

Handy with a debugger. Slow: figure out how a complicated system works on paper or in your head. Fast: run a complicated system and see what it does. Slow: carefully consider how to adapt a system to make it do something tricky. Fast: change it, put in a breakpoint, does it work? What variables cause it not to? Caveat: You’ve still got to think about edge cases that didn’t naturally occur in your debugging state.

mario_3

Level 3: Hey, you’re pretty good!

Thinks through edge cases / good bug spotter. When I worked at my first job, I often felt that programmers should be judged equally on the number of their bugs they fixed and the number of other programmers bugs’ they found. Of course, there are those that will make the case that bug testing is the job of QA. And yes, QA is good. But QA could never be as effective as a developer that naturally has a sense for the edge cases that could affect their code so don’t write those bugs in the first place. And getting QA to try to reproduce intermittent bugs is usually no less work than just examining the code and thinking about what might be broke.

Unwilling to accept anomalous behavior. Good programmers learn that there is a serious cost to “code folklore” — the mysterious behaviors that have been vaguely attributed to a system without understanding the full root cause. Code folklore eventually leads to code paranoia, which can cause inability to refactor, or reluctance to touch that one thing that is so ugly, yet so mysterious and fragile.

Understands foreign code quickly. If this post is supper, here’s the steak. Weak developers need code to be their own to be able to work with it. And proficient coders are proficient because, for the 75% of the time that you are not working in code that you recently wrote, you can figure out what’s going on without hours or days of rumination. More advanced versions of this trait are featured in level four (“Can adapt foreign code quickly”) and level five (“Accepts foreign code as own”). Stay tuned for the thrilling conclusion on what the experts can do with code that isn’t theirs.

Doesn’t write the same code twice. OK, I’ve now burned through at least a thousand words without being a language zealot, so please allow me this brief lapse into why I heart introspective languages: duplicated code is the root of great evil. The obvious drawback of writing the same thing twice is that it took longer to write it, and it will take longer to adapt it. The more sinister implications are that, if the same method is implemented in three different ways, paralysis often sets in and developers become unwilling to consolidate the methods or figure out which is the best one to call. In a worst case scenario, they write their own method, and the spiral into madness is fully underway.
mario_4

Level 4: You’re one of the best programmers in your company

Comments consistently on code goals/purpose/gotchyas. Bonus points for examples. You notice that I haven’t mentioned code commenting since level one? It is out of my begrudging respect for the Crazed Rubyists who espouse the viewpoint that “good code is self-documenting.” In an expressive language, I will buy that to an extent. But to my mind, there is no question that large systems necessarily have complicated parts, and no matter how brilliantly you implement those parts, the coders that follow you will take longer to assimilate them if the docs are thin. Think about how you feel when you find a plugin or gem that has great documentation. Do you get that satisfying, “I know what’s going on and am going to implement this immediately”-sort of feeling? Or do you get the “Oh God this plugin looks like exactly what I need but it’s going to take four hours to figure out how to use the damned thing.” An extra hour spent by the original programmer to throw you a bone would have saved you (and countless others) that time. Now do you sympathize with their viewpoint that their code is “self-documenting?”

Can adapt foreign code quickly. This is the next level of “understands foreign code quickly.” Not only do you understand it, but you know how to change it without breaking stuff or changing its style unnecessarily. Go get ’em.

Doesn’t write the same concept twice. And this is the next level of “doesn’t write the same code twice.” In a nutshell, this is the superpower that good system architects possess: a knack for seeming patterns and similarities across a system, and knowing how to conceptualize that pattern into a digestible unit that is modular, and thus maintainable.
mario_5

Level 5: Have I mentioned to you that we’re hiring?

Constant experimenting for incremental gains. The best of the best feel an uncomfortable churn in their stomach if they have to use “find all” to get to a method’s definition. They feel a thrill of victory if they can type in “hpl/s” to open a file in the “hand_picked_lists” directory called “show” (thank you Rubymine!). They don’t settle for a slow development environment, build process, or test suite. They cause trouble if they don’t have the best possible tools to do their job effectively. Each little thing the programming expert does might only increase their overall productivity by 1% or less, but since developer productivity is a bell curve, those last few percent ratchet the expert developer from the 95th to 99th percentile.

Accepts foreign code as their own. OK, I admit that this is a weird thing to put at the top of my pyramid, but it’s so extremely rare and valuable that I figure it will stand as a worthwhile challenge to developers, if nothing else. Whereas good developers understand others’ code and great developers can adapt it, truly extraordinary developers like foreign code just as much as they like their own. In a trivial case, their boss loves them because rather than complaining that code isn’t right, they will make just the right number of revisions to improve what needs to be improved (and, pursuant to level 3, they will have thought through edge cases before changing). In a more interesting example, they might take the time to grok and extensively revise a plugin that most developers would just throw away, because the expert developer has ascertained that it will be 10% faster to make heavy revisions than to rewrite from scratch. In a nutshell, whereas most developers tolerate the imperfections in code that is not their own, experts empathize with how those imperfections came about, and they have a knack for figuring out the shortest path to making the code in question more usable. And as a bonus, they often “just do it” sans the lamentations of their less productive counterparts.

This isn’t to say they won’t revise other people’s crappy code. But they’re just as likely to revise the crappy code of others as they are their own crappy code (hey, it happens). The trick that these experts pull is that they weigh the merits of their own code against the code of others with only one objective: what will get the job done best?

Teach me better

What qualities do you think are shared by the most effective developers? What do you think are the rarest and most desirable qualities to find? Would love to hear from a couple meta-thinkers to compare notes on the similarities you’ve observed amongst your most astoundingly productive.

Best of Rails GUI, Performance, and other Utilities

I’m all about putting order to “best of” and “worst of” lists, so why not give some brief props to the tools, plugins, and utilities that make life on Rails a wonderous thing to behold?

5. Phusion Passenger. OK, this would probably be first on the list, but it’s already been around so long that I think it’s officially time to start taking it for granted. But before we completely take it for granted, would anyone care to take a moment to remember what life was like in a world of round-robin balanced Mongrels web servers? You wouldn’t? Yah, me neither. But no matter how I try, I cannot expunge memories of repeatedly waking up to the site alarm at 7am to discover somebody had jammed up all the Mongrels with their stinking store update and now I’ve got to figure out some way to get them to stop.

4. jQuery / jRails. This probably deserves to score higher, as the difference between jQuery and Prototype is comparable to the difference between Rails and PHP. But since it’s not really Rails-specific, I’m going to slot it at four and give major props to John Resig for being such an attentive and meticulous creator. Without jQuery and jQuery UI, the entire web would be at least 1-2 years behind where it is in terms of interactivity, and I don’t think that’s hyperbole. (It even takes the non-stop frown off my face when I’m writing Javascript. With jQuery, it’s merely an intermittent frown mixed with ambivalence!)

3. Sphinx / Thinking Sphinx. There’s a reason that, within about six months time, Thinking Sphinx usurped the crown of “most used full text search” utility from “UltraSphinx.” And the reason is that it takes something (full text search) that is extremely complicated, and it makes it stupidly easy. And not just easy, but extremely flexible. Bonanzle has bent Sphinx (0.9.8) into doing acrobatics that I would have never guessed would be possible, like updating it in nearly-real time as users log in and log out. Not to mention the fact it can search full text data from 4 million records in scant milliseconds.

Sphinx itself is a great tool, too, though if I were going to be greedy I would wish that 0.9.9 didn’t reduce performance over 0.9.8 by around 50% in our testing, and I would wish that it got updated more often than once or twice per year. But in the absence of credible competition, it’s a great search solution, and rock solidly stable.

2. New Relic. OK, I’ll admit that I’ve had my ups and downs with New Relic, and with the amount of time I’ve spent complaining to their team about the UI changes from v1 to v2, they probably have no idea that it still ranks second in my list, ahead of Sphinx, as most terrific Rails tools. But it does, because, like all the members of this list, 1) the “next best” choice is so far back that it might as well not exist (parsing logs with pl-analyze? Crude and barely useful. Scout? Nice creator, but the product is still a tot. Fiveruns? Oh wait, Fiveruns doesn’t exist anymore. Thank goodness) and 2) it is perhaps the most essential tool for running a production-quality Rails site. Every time I visit an ASP site and get the infinite spinner of doom when I submit a form, I think to myself, “they must not know that every time I submit a form it takes 60 seconds to return. That would suck.” On a daily basis, I probably only use 10% of the functionality in New Relic, but without that 10%, the time I’d spend tracking logs and calculating metrics would make my life unfathomably less fun.

1. Rubymine. The team that created this product is insane. Every time that I hit CTRL-O and I type in “or/n” and it pops up all files in the “offers_resolution” folder starting with the letter “n,” I know they are insane, because having that much attention to productivity is beyond what sane developers do. Again, for context’s sake, one has to consider the “next best” choice, which, for Linux (or Windows) is arguably a plain text editor (unless you don’t mind waiting for Eclipse to load and crash a few times per day). But, instead of programming like cavemen, we have a tool that provides killer function/file lookup; impeccable code highlighting and error detection (I had missed that, working in a non-compiled language); a working visual debugger; and, oh yeah, a better Git GUI than any of five standalone tools that were built specifically to be Git GUIs.

Perhaps as importantly as what Rubymine does is what it doesn’t do. It barely ever slows down, it doesn’t make me manage/update my project (automatically detecting new files and automatically adding new files to Git when I create them from within Rubymine), and it handles tabs/spaces like a nimble sorcerer (something that proved to be exceedingly rare in my quest for a usable IDE).

Like New Relic, I probably end up using only a fraction of the features it has available, but I simply can’t think of anything short of writing my code for me that Rubymine could do that it doesn’t already handle like a champ. Two thumbs up with a mutated third thumb up if I had one.

Conclusion

Yes, it is a list of apples and oranges, but the commonality is that all five-ish of the lists members stand apart from the “second best” solution in their domain by a factor of more than 2x. All of them make me feel powerful when I use them. And all of them, except arguably New Relic, are free or bargain priced. Hooray for life after Microsoft. Oh how doomed are we all.

Buying Dell servers? Consider the hidden costs.

The time is currently 5:30am. Normally, this would be the sort of time that I would enjoy sleeping. However, I have instead spent this evening, or morning, or whatever-you- call-it, working with our hosting team to fix a server that refused to start after installing a replacement part given to us by Dell. We finally got the server running again about an hour ago, and I’m now waiting for our slave database (corrupted during the crash) to re-sync. If I’m lucky I’ll hit the sack before sunrise.

While it’s always difficult to conclusively assign blame with a hardware problem, I think it is pretty safe to blame this predicament on a replacement Dell part we installed about two days ago. Prior to installing the replacement, this server would crash every 2-4 weeks, stating that its disks had become detached. We had an identical server, with identical software, that has yet to crash since we purchased it, so a hardware failure was the most reasonable explanation. Google search results on our error corroborated this. So, hesitantly, I picked up the phone and dialed Dell support.

The worst-case scenario would be that they spend hours arguing with me and making me go through rote debugging tasks despite the numerous facts I’d accumulated that all pointed squarely at RAID controller. The best-case scenario was that they looked at my purchasing history of almost $20k in hardware over the last year, noted that this is the first time I have ever asked for a replacement part, and give me the benefit of the doubt just this once.

Dial Dell. Quick arrival at support guy. Explain situation to support guy. Support guy starts reading debugging script. D’oh! Worst-case scenario begun.

As any business owner/IT manager can tell you, there is a very tangible time/cost equation that can be applied to any hardware debugging scenario. The question that one has to ask oneself, when entering into a support debugging script they know is unnecessary, is whether the 2-3 hours it will take to complete the tasks, multiplied by the uncertainty that the support person will agree a replacement is necessary, is less than the cost of just re-buying the part. When my hard drive failed on my Dell desktop, the answer quickly became “no” after I spent an hour on the phone with the tech over a hard drive that was probably worth $100 (I ordered the part off Amazon and my computer has worked fine since). It was my cautious hope that my buying history might earn me a more dignified treatment this time around. But after an hour on the phone with the tech, it quickly became clear that I was yet again headed down a multiple-hours debugging path for a part that would cost only $200-$300.

Then, a break of light. I learned of the Dell FastTrack program, which, after a test “certifies” that a person isn’t a dunce, allows them to order their own parts without the support script. A great solution to a hard problem. I quickly signed up for the program. Though it took me probably about 5 hours to complete it, I justified the time expense as a pre-payment on a lifetime of savings in support scripts.

Shortly thereafter, I became certified, ordered my replacement part, and it arrived only two days later. Great turnaround!

Then, today happened. Here is my rough table of the different paths I could have taken to get our server problem fixed:

Option Initial Cost Future cost Total cost
Buy a new RAID card. $250 None. Because new parts work. $250
Persuade Dell support person that you deserve a replacement part 2-3 hours of time 5-10 hours of IT debugging time * $100-$200 (after refurbished part fails) 2-3 hours of life + $500-$2000
Get Dell certified, order replacement part 5 hours of time 5-10 hours IT debugging time * $100-$200 hour (after the refurbished part fails) 5 hours of life + $500-$2000

The most maddening part of this story? That it makes perfect economic sense for Dell. Other than customer fury (which generally has no tangible cost), what does it matter to them if the replacement part doesn’t work? Why not just ship every returned part out to another customer, just to be sure that it is “really” defective? They kill two birds with one stone: they don’t have to spend money on a new replacement part, or in the worst-case scenario, they get a free test of their hardware from the unwitting consumer. Heck, maybe they send the replacement part, which fails, and the consumer gets so frustrated they start buying new parts instead of bothering their support team. They save time and make money.

Unfortunately, today I was the unwitting consumer. Rather than spending the $250 to buy a new part, I believed that Dell would send me a replacement that worked. Instead, it failed catastrophically two days after we installed it, and I was out 5 hours of certification time, plus $500-$2000 in IT time for fighting the problem. Not to even factor in the costs of site downtime, 10 hours of stress, and all the energy put into fixing the stuff that broke when the site crashed.

If the best part of the Internet is that justice can be served, I would like nothing more than to see Dell be served justice by consumers that are tired of refurbished parts, support personnel bent on denying necessary parts, and a general lack of benefit of doubt to the customer. 5:30am is not a time where I belong.

Bonanzle: “The Best eBay Alternative They’ve Seen”

An incredible accolade for a site that’s still technically in beta, Ecommerce Guide just named Bonanzle “The Best eBay Alternative They’ve Seen” in four years of reviewing eBay alternatives. Pessimistic side of me says that an article this effusive is an open invitation for every Tom, Dick and Harry to quibble and point out the faults of Bonanzle (of which there are admittedly still several… we’re haven’t even officially launched yet, people), or question how Bonanzle can be called an “eBay alternative” when it doesn’t even do auctions.

That said, it’s hard to imagine this project going much better than it has so far. While I’m fully aware that the hundreds of PHP eBay lookalikes are going to slowly start nibbling at what are now Bonanzle-only features, it’s comforting to know that they’re going to have to program those features in PHP (or maybe Java).

If you haven’t already, pay a visit to Bonanzle and cast your vote that Rails is an unfair advantage.

Craigslist Buyer and Seller Paradise

Bonanzle is aiming to be the Seattle Craigslist seller paradise by offering two sweet new features:

  1. Item importing. Items can be imported directly from Seattle Craigslist (or any other Craigslist, for that matter) by following the link to our Seattle Craigslist offer.
  2. 0 red tape account setup. You can test drive what it’s like to sell on Bonanzle without even setting up an account. I don’t think it could get much more simple if we tried.

Visit the link to see what Bonanzle is all about. The more people on the site, the more fun and addictive it shall become.

What is Bonanzle?

Bonanzle is an online marketplace for buying and selling goods faster while having more fun. We also aim to create the marketplace that is the most simple, yet powerful choice around.

Is Bonanzle a real word?

It is now. And it’s a verb. Bonanzle combines the wealth and excitement inherent in Bonanza (a large pocket of valuable mineral, or a source of prosperity), and the action implicit in -le (as in babble, burble, bustle). To Bonanzle is to spend quality time at an online space buying and selling goods, and meeting people.

What’s the launch plan?

In the month of May, we get as many items as possible on the site. Hopefully more than a thousand, hopefully from eBay and Craigslist refugees that are sick of complexity/fees, and who want a more immersive experience, respectively. On June 14th, the site opens to buyers. On June 21st, the great Bonanzle Bonanza happens (where as many booths as possible have a Bonanza on the same day). Sometime thereafter, we officially launch, depending on when the site achieves consistent stability and zippiness.

I care about the environment. Does Bonanzle?

Well that’s a loaded question if ever I heard one! We run a carbon-offset surplus. At Bonanzle, our goal is to offset twice the carbon we create, so that we will actively reduce CO2 levels. And when you consider that environmental watchdog ClimateCounts.org gave both eBay and Amazon.com its lowest score for online businesses, it is pretty important that we go beyond offsetting just our own use. We know of no other online marketplace committed to offsetting double the carbon it uses. We believe this makes us the environmental leader amongst online sellers. And we feel pretty good about that. But not so good that we’re going to relegate ourselves to advertising as a foofy environmental site.

Rails Internet Explorer Integration Guide

After about nine months of blissful Firefox-only development, Bonanzle finally started down the long road to Internet Explorer-compatibility a couple months ago. Though I’ve met few web developers who like the process of supporting IE, browser statistics show that fully 50% of users are still on some version of it (IE 6 has about 30%, IE 7 around 25%), so it’s something we have to deal with. Having just about wrapped up our backporting, I thought I’d share a few observations and tips on the process.

First of all, for background, I had never really touched web development of any sort until about 9 months ago. At the beginning of the backport, we had nary opened IE to see how our site would fare in it. As you might guess, the answer was “not well.” Because Bonanzle is rife with rich Javascript, and we use CSS-based layouts, few of our 30-ish pages were IE-compatible at the start of our backport. Many of our most substantial pages could not even render in IE without spewing 10+ JS errors.

But with a couple tools and rules, the process of moving toward IE compatibility ended up becoming relatively straightforward, and even our most complex and nuanced functionality has now been coerced into IE compliance.

The most important lesson I would impart to aspiring web applications: use a Javascript library. Like all young Rails sites, we started with Prototype. Once we were ready to take the training wheels off, we started using jQuery. Our backport revealed that only about half of our handwritten JS code worked in IE without modification. Some but not all of our Prototype worked. And almost all the jQuery did.

There are plenty of pages already out on the web dedicated to the comparison of jQuery to Prototype, but suffice to say for our purposes, my relationship with Javascript was an antagonistic one until I met jQuery. Now, I almost look forward to writing JS. Being able to batch select elements using pure CSS selectors, not needing to check for nulls when accessing selectors, and being able to concisely make complex behaviors happen with concatenated method calls are all big reasons. The rich plugin architecture is an even bigger reason. There seemed to be no task too large or small for a cross-browser jQuery plugin. Some of our heavily utilized plugins included the drag and drop ui-*.js, the jqModal plugin, and the jquery delegate plugin. We also worked with a contractor who custom-wrote some jQuery plugins for us that, like all jQuery I’ve encountered, “just worked” in IE (well, after they worked in Firefox, but that’s easy to make happen with Firebug).

If you do choose to go the jQuery route in writing your site, do yourself a favor and look into the JS QueueSpring plugin — it’s discussed in the previous blog, and is ideal for binding jQuery behaviors with your DOM elements in a clean and fast-loading way.
As far as CSS goes, there is no easy way to sum up means by which to write CSS that is IE6/7 compatible. I think that for all but the most experienced web developers, it is an iterative process. What I can recommend are some tools to speed up your iterations. First of all, if you’re on Windows, you’ll need to be able to install the version of IE you don’t have (6 or 7). This is most easily done by downloading the IE virtual machines Microsoft provides on their site. These provide an out-of-the-box solution for running IE6 and IE7 side-by-side on your machine (not otherwise possible). They also come bundled with some of the best tools available for figuring out what you’re looking at in IE: the Web Developer toolbar and the Script debugger. The former is basically a wussy version of Firebug that allows you to mouse over elements and see their properties, but not modify those properties dynamically, the way Firebug allows. The latter is a fairly lame way to see what’s going on in your JS when IE encounters errors. For both IE6 and IE7, you’ll need to ensure that you allow Script Debugging, which is under Tools -> Internet Options -> Advanced.

If you’ve got a big project on your hands, you’ll probably find the Script Debugger to be too barren… from what I’ve seen, it doesn’t allow you to set breakpoints in an arbitrary file, it has no watch window, and you can’t edit code from within it. A better choice is to install Visual Studio and use that as your JS debugger. If you don’t have it, you can download a free, “text only” version of Visual Studio with Ruby in Steel. You can then uninstall the RiS if it’s not your cup of tea (though it should be), leaving Visual Studio installed.

That’s the basic framework of what we’ve used to get our site from IE crashfest to lovable huggable puppy dog. Hopefully this may start off you other intrepid cross-browser souls on your journey as well. May you be strong, and repeat after me… “only 12-20 months until IE6 is obsolete.”

Delete DOS Directories Recursively

Windows XP doesn’t include my old standby “deltree,” and there is no combination of options that “del” can take to delete hidden directories recursively (yeah, I’m talkin bout you, .svn directories!)

After some rooting around the web and two tablespoons of experimentation, I’ve finally come up with the following Windows Powershell command that can recurisvely delete hidden directories and their contents:

get-childitem . -include .svn -force -recurse | foreach ($_) {remove-item -force $_.fullname}

The first “.” after the get-childitem is the base directory you want to start in. The parameter after “-include” is the pattern you want to operate on. In my case, the wretched Subversion directories (.svn)

Unfortunately, this script still prompts me for each directory I want to delete, but that’s only a tweak or two away from perfection.

Inflection Point

2-3 weeks. That is apparently about how long it takes to reach the productivity inflection point with AJAX/Ruby on Rails/Javascript. After spending many a day stumped on various problems that seemed like they ought to be “minor,” I found myself today refactoring our most complex controller from top to bottom, fixing a couple bugs, and having the damn thing improbably work. Cool. Maybe there’s something to this language.

In seriousness, most all of this week’s interviewees have expressed considerable curiosity in how RoR differs from the other scripting languages, and why we chose it. I don’t know that I’m entirely qualified to compare it to “other languages” since my experience in both ASP and PHP has been purely C-like procedural goop written before I had OOP experience. Though that does hint at the first difference I can confidently draw between the three languages: whereas other languages tempt you at every turn to write ugly code, RoR takes MVC architecture and unit testing into its own hands to minimize the initial time penalty for writing clean code.

The database model conventions and migrations took some getting used to, but I am growing to appreciate them more as well. There is sense and utility in having a memory version of your class that mirrors the database version of the class. And it’s convenient to be able to quickly and easily commit a class instance in memory into its database counterpart. I have never even attempted to do that in another language, but I know that last time I used ASP it wouldn’t have been easy, and I imagine that is probably still the case with them.

I’m also very fond of the gem packaging system that is used to add plugins to RoR. Even with lowly DOS, installing a new plugin for one’s site is often as easy as “gem install pluginname.”

These are amongst the more superficial differences between the languages, but some of the easier ones to describe. It feels a little bit jurassic to be debugging with a console again after having used Visual Studio debugging, but it works and you get used to it. An applicant who I asked about PHP debugging wasn’t even sure if/what PHP debuggers existed, so I can’t imagine that the situation is radically better for PHP. Though I doubt it’s worse.

So, on balance, I’m giving a thumbs up to the advantages of RoR over the other languages we could have chosen. And this is after using it but a couple weeks. I’m very much looking forward to seeing what I can get done with it once I truly learn to start think like a Ruby programmer.