Pithy Quote

I was perusing this post on programming.reddit.com and in the first 10 comments I found this:

"The janitors at MIT have mops whose bristles are made from the parenthesis discarded by the first-year students in their programming classes."

Ups and Downs with Capistrano

Capistrano is an insanely useful deployment system for Rails (among other things). But I just spent two hours banging against an annoying issue.

After Cap extracts the latest code from my source repo (hg), it tries to set the group permissions on the files. Due to some oddness in the setup on my server this fails, even though they already have g+w set on them.

It was outputting this:
* executing "chmod -R g+w /wwwDocs/foo/releases/20080303233346"
And then listing a series of files with "Operation not permitted". At least I had the benefit of this output. Some stories I ready involved FastCGI failing silently after the permissions changed. Man. I got lucky.

Some quick googling led me to a number of stories mentioning that cap is running "set_permissions" after the code update, and that overriding it like so will stop it from doing that:
task :set_permissions, :except =&gt; { :no_release =&gt; true } do<br />  # do nothing<br />end
However, that had zero effect. I tried many different permutations. Once I finally dug into the actual cap recipes file (which I should have done earlier), I discovered that in my (apparently newer [2.2.0]) version of capistrano, they helpfully moved the activation of this code to a flag
task :finalize_update, :except =&gt; { :no_release =&gt; true } do<br />    run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
So, I set that flag and all was finally well. Too bad there is so much info out there that's misleading. It's not the fault of the people who posted it, they were being helpful at the time. Anyway, I hope this post helps some other people out of the same jam.

Ruby in Leopard

Just in case you were as bewildered as I was trying to figure out where all the ruby files in leopard live, here is a thorough explanation:WhatsNewInLeopard"locate ruby" shows files in a number of different places, and this explains what each one is. Very handy.

More reasons why browsers and flash suck

Mac Firefox (2.0.0.11) has a few bugs. One of them is this weird font anti-aliasing bug where fonts are anti-aliased at one setting in a normal page, but if you set the opacity of any object on that page, then they swap into a different mode. You can see the font strokes getting thicker or thinner. It's really obvious with bold fonts. We ran into this issue with a recent release. On our home page were two rotating banners, we use Scriptaculous to Fade() and Appear() each one, so they cross fade into each other. Saves real-estate nicely. However, when it started the cross fade, the fonts would thin, then when it was done, they would thicken back up. It didn't bother me, but the higher ups thought it was a catastrophe, so I hunted around for a solution. Eventually we hit on setting "-moz-opacity: 99" on the body element, forcing it into one mode all the time. So we cruise along with that for 6 months until we add some flash to another page in the site. Works great for everyone but poor little old me in FF Mac. If the flash has "wmode" set to "transparent" the flash object appears, but then goes blank, and only appears in parts where my mouse drags over it. In that setting our DHTML menus don't appear in front of it, so it's useless.So we switch to "wmode=opaque" and it "solves" that problem, now the flash box is completely empty all the time. Some googling around points me to problems between flash and CSS opacity, so my first thought was to take out that -moz-opacity declaration and whaddayaknow, everything works. So we override that opacity setting on the flash page and we're all good.

Favicons

Since creating favicons is kind of a pain, you can now use http://favicon.cc to build them yourself.

They are a great boon to browser usability, looking through a forest of tabs or bookmarks, the icons jump right out and speed up the process greatly.

Safari

I desperately want to switch to Safari/WebKit for casual surfing, it's a lot faster, and it just feels more responsive. I have to use Firefox for development, there is no way I could live without the Firebug and Web Developer plugins.

But I can't use Safari because it's missing a few features that I depends on constantly. First of all, it doesn't save your tabs when you quit or it crashes. Saft us supposed to do that, but I don't trust it yet, also it's annoying and I hate the name. Plus it's free in Firefox.

Also, it doesn't handle tabs very well. I routinely keep about 60 tabs open with pages of information that I'll need to read and process. If I bookmark the pages, I'll forget and never go back, so I keep them in tabs, and eventually I get to them. I blame that large number on http://programming.reddit.com .I also discovered that Firefox gets cranky when you have over 95 tabs open. Whoda thunk?

Beyond that, no Del.icio.us plugin - why would I not bookmark in a central location ?

So there are still some hurdles. Also, Firefox 3 nightlies are pretty fast, though I haven't tried them under full load.

JavaScript: objects, closures, binding and "this"

I've recently been wrestling with a JavaScript problem. I added a member variable to my JS object and then tried to access it from one of the objects methods. It seemed like a simple thing, since functions within JS objects are closures, you have access to the containing object's members and functions. For the simple case, that's true, but I had found a place where that wasn't true.

I use Prototype and script.aculo.us, since they make my life easier. Inside the aforementioned function I was calling

foo:function(){
$$(".someClass").each(function(el,ndx){memberArr[ndx] = foo});
}

and it was silently dying after that call, since it didn't know about memberArr. I tried calling it this.memberArr, but that didn't help. When I stepped into the function in Firebug, this was pointing to Window.

After stepping through it a number of times I realized that this was set properly when I entered the function, before $$() was called. So diving into the $$() rabbit-hole reset this to it's default, how annoying.

I knew I'd seen a solution to this type of problem before, and I looked at trying to call invoke(), but that wasn't an option because of the way I wanted the function to run.

I thought about trying to get apply() to work, since you can pass in an object as the first argument, and that obj will be the this within the function. That also made my code little wonky.
Then I remembered .bind() which keeps "this" pointing to the owner object. I had tried it before, but a typo made me think that it wasn't doing what I expected it to. Once that was sorted out, I re-wrote it as this:

foo: function(){
$$(".someClass").each(function(el,ndx){this.memberArr[ndx] = foo}.bind(this));
}

And magically this pointed to the "owner" of the function.

Sorting a Select List Inline

I've been trying to get select list to order itself randomly with each page load. I finally got the following solution.

var len = $("list").options.length
for(var i=1;i<len;i++){
var rand = Math.floor(Math.random()*(i+1));
rand = rand||1/*force to 1 if zero, we don't want to swap the first element*/

var temp1text = st.options[i].text;
var temp1val = st.options[i].value;

var temp2text = st.options[rand].text;
var temp2val = st.options[rand].value;

st.options[i].text = temp2text;
st.options[i].value= temp2val;

st.options[rand].text = temp1text;
st.options[rand].value = temp1val;
}

It still needs some work. To clean it a bit. Initially I tried sorting the actual Option objects in st.options, but that is not a proper array, since it auto-collapses when you remove an item, and I found no way to insert a node at an arbitrary index. So I just moved the values around.

The algorithm came from this page, which was incredibly helpful. It's a nice clean algorithm that hopefully won't require so much tweaking when I use it on normal arrays.

What took a little work was getting it to leave the first element alone. Since the first element is "chose an item..." I didn't want it moving around. This is why my numbers aren't exactly like the ones he uses.