Monday, November 27, 2006

The Bulldozers

Every so often I run into a bug that really stumps me. Usually, of course, it has something to do with I.E. In the worst case, it's a javascript bug that crops up in I.E. but not in Firefox. That's what happened to me today. Then I'm left with no debugging tools and incredibly useful errors like "Object doesn't support this property or method." And this wasted probably 5 or more hours of my time.

I don't want to go into the details of the particular problem that frustrated me, which is unlikely to be of benefit to many people, but I would rather like to draw a far more wide-ranging lesson from the methodology I used in attacking the problem.

At first I engaged in what is probably the best practice: I looked for the most obvious solution and made a quick fix. When the problem did not go away, however, I began trodding down the Path of the Fool: I began grasping after all the "unobvious" solutions and successively applying "quick fixes" with the hope that this awful error would just go away. Cut to five hours later. Nothing learned. And one very unhappy programmer.

So what's a pragmatic programmer to do when confronted by the Evils of Imponderable Internet Explorer Errors? Well, I've come up a with a new rule when it comes to these sorts of bugs. I am free to attempt the "quick fix" method for up to 30 minutes. But should any bug take longer than that to resolve, I must immediately turn to the Method of The Bulldozers. This is the debugging method that never fails.

Oh, you ask, but what is this wonderful method of which I speak? So good of you to enquire! The idea is simple:

1) Find the simplest test case that works. For example, prove that what you are attempting to do is possible in a simple, perfect world.

2) Make a backup of your web pages/code, or be very comfortable with your favorite editor's undo function (I'm a vim fan, and am usually foolhearty enough to proceed this way).

3) Add the test case to a completely stripped down version of your webpage and verify that it works. Also make sure that this test case does not work in the full version of your code. (If it does work in the full version of your code, slowly modify this test case in the direction of what you actually want, until it breaks. Then, optionally go on with step 4 if the same thing still does work in the stripped down environment and it's not stupidly obvious why it does only there.)

4) (The bulldozing part) Begin stripping anything and everything you can from the web page/program code that is causing you angst. Do this is binary chunks, for example, first rip out half the code, then the other half, and then perhaps the right 3/4 etc. In between each "tear-out," test to see if the problem has gone away. Usually, the problem is in one specific place, and you'll be able to zero in very quickly. Occasionally, there are two or more pieces of code in different locations conspiring to give you grief. No matter what's going on, you'll get to the bottom of it pretty quickly, as you happily bulldoze away.

This is an extremely powerful method. I haven't yet met a web programming bug that withstood it.

Tuesday, November 21, 2006

Javascript oddity

Has anyone else noticed the following? (I don't know why I ask, as if there's much of an audience to my blog at this point.)

<script type="text/javascript">
var oddity="not so odd";

<input name="oddity" onclick="alert(oddity.value);" type="text" value="rather odd" >

produces an alert that reads "rather odd".

This occurs in Firefox, at least. The interpreter ignores the variable already declared and instead treats the symbol as if it we had referenced the enclosing form element first; i.e.: alert(theform.oddity.value). Rather odd, no?

How to escape html in your rails controller

The problem:

Occassionally you want to use the h() function (like in the embedded ruby template) in your controller. In particular, I needed to do this in order to echo back (invalid) user supplied email addresses in a flash[:notice]. You don't want to escape the whole flash[:notice] because you might actually want to put some genuine html in it. Therefore, you've got to do this in your controller.

The solution:
Suppose your stringy is:
"Joe Example" <>
Simply invoke CGI.escapeHTML(stringy) in your controller to produce the escaped stringy. Note that if you want to escape a URL, you simply invoke CGI.escape.

The how and why:

It turns out that (as far as I can tell) h() isn't actually a function in rails. If you look through the Rails API, you won't find it anywhere. I found this curious, and even tried a recursive grep in my rails gem dir for all methods beginning with 'h' (grep -R 'def h' *). Nadda. So it would appear this is not actually a function in rails, but something that the embedded ruby parser picks up, maybe even via a regular expression. Unfortunately, that means we can't just find the associated helper and require it in our foo_controller.rb (or application.rb). As tempting as it is, we certainly shouldn't need to reinvent the wheel in these sorts of scenarios, right?

So what then? Well, it occurred to me that surely the Rails team, at least, wouldn't go and reinvent the wheel. Afterall, they were pretty busy when they were building Basecamp. If they're building a system to run under FastCGI, surely they wouldn't shy away from using Ruby's CGI library, right? On a hunch, I checked if this was already "require"d somewhere deep down in the framework. Just went ahead and invoked CGI.escapeHTML from a controller. And valois! There we have it. You could probably even mess with the sessions/cookies using the CGI module... but that would be rather evil.

Saturday, November 18, 2006

More critical am I

Perhaps it's just the winter, but I as I erect more startups, I find myself growing more critical as to what is worth pursuing. Here, after all, is a perfectly interesting idea I conjured up today that I nevertheless toss out as a throw-away:

1) A form where a user enters in a recipient's name, physical address (perhaps), and a message.

2) A encryption key is produced randomly and the message is encrypted in his browser via javascript. The encrypted message is transported to a database on our server and the user is presented with a link, and next to it, the encryption key. He may then include this link and encryption key in an email to his friend.

3) His friend clicks on the link and lands on a screen explaining that, in order to see the message, he must first prove his identity. To do this, he must sumbit a payment of 9 cents via Paypal. Passing this, it is requested that he paste in the encryption key. Then the encrypted message is transported to his browser, and it is decrypted by means of the encryption key he pasted.

Three things (alphabetically):

A. Why this is reasonably secure.

B. Why it is a pretty good idea.

C. Why I am throwing it away.

A. The javascript/html code involved in this process is auditable. Security experts may look at the code, and even set up automated processes to detect any differences in the code. If we tried anything nefarious, we would quickly be spotted. The message is never made available to us in raw form. We cannot read it without the encryption key, which is transported by a separate medium (email is suggested, but other methods, like the telephone, are available). In order to access the encrypted message, the supposed recipient must prove that he has access to the actual recipient's financial instruments---a pretty good indication he is who he portends to be. Moreover, he must have the encryption key. And remember, all encryption/decryption takes place in the browser--this is, again, auditable. In order for us to read the encrypted message, we would have to be involved in a conspiracy with his ISP, his email provider, or perhaps his cell phone company. Rather unlikely, except for the more paranoid (who really ought to be using PGP and operating HAM radio to broadcast their public keys, I guess).

B. While geeks and advanced users may find other ways to communicate securely, there are many people who find the annoyances of PGP, well, annoying. Think of system adminstrators sending passwords to casual users, business people communicating plans and intellectual property, as well as lawyers sending sensitive documents to their clients. These people could really use such a simple method of encryption over the Internet: it's certainly better than what they're doing right now, at least. Note that the business model is sound. Paypal offers a micropayments option costing 5 cents plus 5%. That's a profit of 3 or 4 cents per message, which could amount to a great deal. Also, there is a decent viral marketing potential to this idea: it forces brand experience because it is a product of communication itself. It is just like HotMail in this regard. Finally, to make things all the sweeter, its a damned easy idea to implement. John Walker (is that really his name?) has graciously provided a free-to-use-and-modify javascript encryption/decryption engine. It's pretty cool, check it out.

C. This idea is bad mainly for marketing reasons. Geeks probably won't pick it up, since they know there are "better ways" to communicate securely (even if they actually don't use them). So getting across to the initial audience will be difficult---how do you reach business people and lawyers on a matter of communication security, when the geek community won't even back you up? Perhaps a company with a large marketing budget could do it, but certainly not us. There are some user annoyances which add to the difficulty. People don't like paying for anything on the net, and paypal in particularly has a rather irritating interface. Perhaps a startup with more capital could overcome this by opening their own merchant account. In any case, sending somebody a message which they can only read by paying is well, rather gauche, isn't it?

So go ahead, prove me wrong. It'll make me less "pessimistic." But if you've got the cash to market it---to do it right---well, you might just end up proving me right.

Thursday, November 16, 2006

Psychology: Four Lessons From The Facebook

It should escape no one's notice that Mark Zuckerberg, founder of, was a psych major. Had this not been this case, I don't believe would have ever attained any substantial user-base. In any startup, especially a consumer targetted startup, we must recognize the paramount importance of psychology.

Consider this: Functionally speaking, there is very little difference between and In fact, even a site like is not, from this purely functional vantage point, very far off from these. Try, if you will, to imagine its back in 2004, and does not exist. Now suppose Mark and his friends got together and decided they wanted to make the "Myspace of the College World." Could anyone take this seriously? What on earth would college students need a social networking site for anyway? And yet this is precisely what Zuckerberg and his friends did, only to go on and witness tremendous success. How? The answer is, of course: psychology.

Here are 4 psychological aspects that the Facebook got dead . . . right.

The first and foremost thing is the name. "A rose by any other name would smell as sweet." On the Internet, this is absolutely wrong. There are no smells on the Internet, only domain names. Choosing the name "thefacebook" (Facebook's original name): this was Zuckerberg's first stroke of genius. In the name--here we have it--is the essential spin that Facebook utilized. To get students on board you had to, essentially, lie to them. Don't tell them they're signing up for a social networking site. Tell them they're simply adding their information to an electronic facebook. All students can understand and respect that.

Second, and closely related to the name: The image. In certain cases , the image does not have to be precisely crafted, but it always must resonate with the audience and the "spirit" of the website. In Facebook's case, this was a particularly delicate matter, since they needed to build a social networking site in the guise of an academic resource. It needed to be classy, fully functional, and academic. Well, hop on over to and log in if you've got an account. No one can deny that the design of is at once academically respectable (it really does remind me of one of those facebooks we had), exquisitely designed, and packed with of all the functionality users expect from a social networking site. Thus, they passed this test with flying colors.

Third: A likeable character. To appeal to the college crowd, Facebook had to appeal to the typically quirky, idealistic college student. If they had included any advertisements at the onset, that would have killed them right off. Just as important are things like the little witticisms sprinked like so much CSS padding througout the site. Things like: "I'll find something to put here" and "Too close for missles, I'm switching to guns." Sublte details like these have an immense impact on the subconcious psychological impression of the users.

Fourth: Making the user feel special. The cachet of exclusivity was intense when Facebook first launched. Who could join? Only Harvard students. This is practically the definition of privilege in the modern world. No surprise where Facebook expanded next: the Ivy League. And then next, of course, came all colleges, soon to be followed by "select corporations", and on they went. In retrospect, its somewhat surprising there was no significant backlash against this pandering to and blatant manipulation of the elitist spirit. After all, an exclusive social network like has endured some pretty intense criticism in the democracy and equality prizing societies that it abides in. But I think what happened here is simple: People will believe what they want to believe. In the case of Facebook, Ivy Leaguers probably wanted to believe that: (1) They were, after all, very special and lucky people, and (2) They were however, not actually elitist, and therefore (3) The Facebook was actually not pandering to the elitist spirit, but rather had just happened to decide that, as their limited server capacity expanded, they would expand (arbitrarily, as if) among the most "well known" universities -- those universities that, as fate would have it, "just hopped to mind."

Those are the primary lessons in psychology from Making the user feel special, imbuing the site with a likeable character, presenting a carefully crafted image, and choosing The Right Name. If you still don't believe me, compare to ConnectU. In these respects, ConnectU made all the wrong decisions. The name is (clearly) wrong, the flash based entry age is reminscent of a seedy dating site, the character does not seem to exist or is overtly commercial, and there was no serious attempt to create a "special" feeling for their users---ConnectU was made available to a ton of schools while Facebook was still busy pandering exclusively to the Sons and Daughters of Privilege. I'd actually be willing to bet that ConnectU still has a chance at competing with Facebook if they fix these serious errors. After all, functionally speaking, they are the same site.

button_to and images: a lesson in false laziness

Today I discovered another little rails annoyance. The "button_to" helper does not yet allow you to use an image for the button. Actually, somebody has submitted a patch to rails to implement this functionality, but for whatever reason this patch has not yet been applied (as of the date of this post).

What to do then? Well, you can take the lazy way out, and use form_tag together with an image tag, which I admit is what I first did, or you can realize that this is really false laziness, and do the right thing.

First, here are the goods: download "url_helper.rb" and add "require 'url_helper'" to your "environment.rb". But wait, if you just do that, you've just fallen into the trap of false laziness! Eeek! So, if you're busy right now you better bookmark this and come back later. Otherwise, well, I curse you with an eternal misery of arduous, falsely lazy programming. If you want to do the right thing, if you really believe in the One True Laziness, then meditate a little on the following:
[code@penguin scibuzz]$ cd lib
[code@penguin lib]$ wget
=> `caller_wins_html_options_for_button_to.2.diff?format=txt'
Connecting to[]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,051 [text/plain]
100%[====================================>] 2,051 --.--K/s

04:52:17 (1.07 MB/s) - `caller_wins_html_options_for_button_to.2.diff?format=txt' saved [2,051/2,051]

[code@penguin lib]$ locate actionpack | head -1
[code@penguin lib]$ cp /usr/lib/ruby/gems/1.8/gems/actionpack-1.12.1/lib/action_view/helpers/url_helper.rb ./
[code@penguin lib]$ patch url_helper.rb caller_wins_html_options_for_button_to.2.diff\?format\=txt
patching file url_helper.rb
Hunk #1 FAILED at 60.
1 out of 1 hunk FAILED -- saving rejects to file url_helper.rb.rej
patching file url_helper.rb
Hunk #1 succeeded at 108 (offset -3 lines).

[code@penguin lib]$ cat url_helper.rb.rej
*** 60,65 ****

def test_link_tag_with_straight_url
assert_dom_equal "<a href=\"\">Hello</a>", link_to("Hello", "")
--- 60,72 ----

+ def test_button_to_with_image_submit
+ assert_dom_equal(
+ "<form method=\"post\" action=\"\" class=\"button-to\"><div><input src=\"example.gif\" type=\"image\" value=\"Hello\" /></div></form>",
+ button_to("Hello", "", :type => "image", :src => "example.gif")
+ )
+ end
def test_link_tag_with_straight_url
assert_dom_equal "<a href=\"\">Hello</a>", link_to("Hello", "")

[code@penguin lib]$ vi url_helper.rb

[code@penguin lib]$ cat url_helper.rb
module ActionView
module Helpers
module UrlHelper
def button_to(name, options = {}, html_options = nil)
url = options.is_a?(String) ? options : url_for(options)
name ||= url

html_options = (html_options || {}).stringify_keys
if confirm = html_options.delete("confirm")
html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
html_options = { "type" => "submit", "value" => name }.merge(html_options)
convert_boolean_attributes!(html_options, %w( disabled ))

"<form method=\"post\" action=\"#{h url}\" class=\"button-to\"><div>" +
tag("input", html_options) + "</div></form>"
[code@penguin lib]$
[code@penguin lib]$ rm url_helper.rb.rej caller_wins_html_options_for_button_to.2.diff\?format\=txt url_helper.rb.orig

[code@penguin lib]$ cat >> ../config/environment.rb
require 'url_helper'

[code@penguin lib]$

Note that one hunk of the patch fails: we quickly check to make sure this is just the test case. Also, you may need to restart your rails application for this to work. And yikes, be careful if you use 'cat' -- remember to append with ">>", don't clobber your file with ">"!!!

The truth is it actually took me quite a while to come up with the above solution, perhaps more time than would have been lost had I simply used 'form_to' for the rest of my rails programming career. However, aside from the auxiliary benefit to the community that I have provided by doing the right thing and documenting it, there is another reason that the easy solution (using form_tag) is really a false laziness. Why? Because, if I hadn't done that the right way, I would have never learned HowToWritePluginToModifyRailsCore. Nor would I have got some delightful practice with such essential UNIX tools as 'patch', 'grep', and 'head'. The next time something about rails annoys me, I can just override it with my own plug-in.

So I strongly recommend you read and understand the above. It's the lazy thing to do.