wonko.com

Hi! I'm Ryan Grove: Sorcerer at SmugMug, lover of movies, eater of pie, connoisseur of awesome.

Older posts

Displaying items 71 - 80 of 662

How to compile and install Ruby 1.9.1 on Mac OS X Leopard

Now that Ruby 1.9.1 is out, a lot of Ruby developers are going to want to run it alongside a 1.8.x build to test their apps. Here’s how to compile and install Ruby 1.9.1 alongside an existing Ruby installation on Mac OS X Leopard without disturbing that installation or any gems.

Note: You’ll need to have Xcode installed, since it provides the development tools necessary for the compilation step. If you don’t already have Xcode, you can install it from your Mac OS X installation DVD or download it from Apple for free.

First, download and extract the release:

curl ftp://ftp.ruby-lang.org/pub/ruby/ruby-1.9.1-p0.tar.bz2 -o ruby-1.9.1-p0.tar.bz2
tar xjf ruby-1.9.1-p0.tar.bz2

Next, compile Ruby, specifying a suffix for the binaries. This will create binaries named ruby19, irb19, gem19, etc., which will coexist peacefully with the stable ruby, irb, and gem binaries:

cd ruby-1.9.1-p0/
autoconf
./configure --program-suffix=19 --enable-shared --with-readline-dir=/usr/local
make && sudo make install

That’s all there is to it.

Update: Updated to resolve potential readline-related errors.

Update 2: The stable release of 1.9.1 is now out, so I’ve updated the instructions accordingly.

Chase is confused

In November I wrote about how Chase Auto Finance lost the title to my car and was unable to send it to the Oregon DMV so I could register the car after moving here from California. As a result of their incompetence, I’m technically breaking the law by residing in Oregon and owning a car that’s still registered in another state.

Today I got two letters from Chase. The first one, dated December 18th, says their records indicate they sent the title to someone (either me or the DMV, they’re not sure who) and goes on to stress, with some urgency, that it is apparently my responsibility to tell them where they sent said title.

The second letter, dated December 19th, says that the title was sent to the DMV and makes no reference to the first letter.

Sanitize: A whitelist-based Ruby HTML sanitizer

Merry Christmas, Internets! My gift to you this year is Sanitize, a whitelist-based HTML sanitizer written in Ruby. Given a list of acceptable elements and attributes, Sanitize will remove all unacceptable HTML from a string.

Using a simple configuration syntax, you can tell Sanitize to allow certain elements, certain attributes within those elements, and even certain URL protocols within attributes that contain URLs. Any HTML elements or attributes that you don’t explicitly allow will be removed.

Because it’s based on Nokogiri, a full-fledged HTML parser, rather than a bunch of fragile regular expressions, Sanitize has no trouble dealing with malformed or maliciously-formed HTML. When in doubt, Sanitize always errs on the side of caution.

Using Sanitize is easy. First, install it:

gem install sanitize

Then call it like so:

require 'rubygems'
require 'sanitize'

html = '<b><a href="http://foo.com/">foo</a></b><img src="http://foo.com/bar.jpg" />'

Sanitize.clean(html) # => 'foo'

By default, Sanitize removes all HTML. You can use one of the built-in configs to tell Sanitize to allow certain attributes and elements:

Sanitize.clean(html, Sanitize::Config::RESTRICTED)
# => '<b>foo</b>'

Sanitize.clean(html, Sanitize::Config::BASIC)
# => '<b><a href="http://foo.com/" rel="nofollow">foo</a></b>'

Sanitize.clean(html, Sanitize::Config::RELAXED)
# => '<b><a href="http://foo.com/">foo</a></b><img src="http://foo.com/bar.jpg" />'

Or, if you’d like more control over what’s allowed, you can provide your own custom configuration:

Sanitize.clean(html, :elements => ['a', 'span'],
    :attributes => {'a' => ['href', 'title'], 'span' => ['class']},
    :protocols => {'a' => {'href' => ['http', 'https', 'mailto']}})

For more details, see the Sanitize Documentation.

Snow!

On Sunday we awoke to find our neighborhood buried under several inches of freshly fallen snow, a once-a-year occurrence in the Portland area. Naturally, I couldn’t resist rushing outside to snap photos.Front steps and driveway of our house, covered in snow

The snow continued to fall most of Sunday and remained on Monday. The sun returned, but temperatures stayed below freezing and the top layers of snow melted by the sun mostly turned into ice. Neighborhood children designated our driveway a sledding zone.

Tuesday saw the emergence of hungry critters eager to feast on the insects and worms chilled and exposed by the melting snow, including an opportunistic squirrel who scurried down from the treetops to seize an unguarded persimmon. He proceeded to devour his prize from a safe vantage point, seemingly unconcerned by my paparazzic invasion of his privacy.

Weather reports call for more snow tomorrow and this weekend, possibly lasting until Christmas Day or even longer, which would make this the longest stretch of snowy weather I’ve seen in over ten cumulative years of living in Portland. Looks like we moved back just in time.

Trogdor: Burninatingly fast search using Yahoo! BOSS

Everyone and their dog seems to have written an example of how to use the Yahoo! Search BOSS API to build a simple search tool. I wanted to take that one step further and build something that would serve both as an example and as a usable service, and that could be extended and enhanced by other developers. Since my day job involves constant tradeoffs between making Yahoo! Search slower (by adding features) and making it faster (by optimizing those features), my primary goal here was to make something as fast as technically possible.

To do this, I wrote a very simple JavaScript module called Trogdor that uses dynamic script nodes to make cross-domain JSONP requests to the BOSS API as you type your query. Search results are returned and rendered almost instantly on each keystroke, and you can use the up and down arrow keys (or tab) and enter to quickly select the result you want—no mouse necessary.

Trogdor doesn’t require a JavaScript framework and works great in all modern browsers (and even some ancient, crappy browsers like IE6). The entire package (HTML, CSS and JS) weighs just a smidge under 2KB after minification and gzip, and it’s wonderfully fast.

Try it out for yourself at pieisgood.org/search and be sure to grab the heavily-commented source code on GitHub. If you’ve got ideas for features and improvements, fork the repo and go nuts (and be sure to let me know what you come up with). You’re also welcome to use Trogdor (modified or unmodified) in your own projects, although I do ask that you please use your own BOSS API key rather than the one included in the example.

Update, 11/26: Changed the name of the library from FastSearch to Trogdor, since dragons are awesome (and apparently there’s a Microsoft search product called FastSearch).

How to prevent race conditions when loading CSS with the YUI Get Utility

The YUI Get Utility makes it easy to dynamically load CSS and JavaScript on demand, but there’s one tiny gotcha: Firefox, Safari, and other Gecko/WebKit-based browsers don’t provide a reliable way to tell when a CSS file has finished loading. As a result, when you load CSS in one of these browsers using the Get.css() method, the onSuccess callback is fired instantly.

In many cases this isn’t a problem, but if you need to ensure that you don’t perform an action (such as appending HTML to the page) until after the CSS has loaded, this can cause a race condition. There’s no way for the Get Utility to automatically work around this problem, but with a little bit of extra effort on our part, we can work around it ourselves.

The trick is to include a rule at the end of the dynamically-loaded CSS file that will send a message to our script by setting a style property on a special element. Once we see that property change, we know the CSS has finished loading.

First, the contents of our CSS file:

/* ... imagine lots of other CSS here ... */

#css-done { display: none; }

And now the JavaScript that will load it:

(function () {
  var Y = YAHOO;

  Y.util.Get.css('example.css', {
    onSuccess: function () {
      var el, poll;

      function finished() {
        alert('CSS has finished loading.');
      }

      if (Y.env.ua.gecko || Y.env.ua.webkit) {
        el    = document.body.appendChild(document.createElement('div'));
        el.id = 'css-done';

        poll = function () {
          if (Y.util.Dom.getStyle(el, 'display') === 'none') {
            // Once the element's display property changes, we know the CSS has
            // finished loading.
            el.parentNode.removeChild(el);
            finished();
          } else {
            // The element's display property hasn't changed yet, so call this
            // function again in 50ms.
            setTimeout(poll, 50);
          }
        };

        poll();
      } else {
        finished();
      }
    }
  });
})();

My car is titleless

A few months ago, when I still lived in California, I bought a new car. Last month I moved to Oregon and began the arduous task of registering my new car with the Oregon DMV.

Oregon requires that you submit the car’s original title along with the registration paperwork. Since I financed my car rather than buying it outright, the bank holds the title until I pay off the loan. This means I had to fill out all the DMV registration paperwork, then mail that paperwork to the bank (Chase) along with a letter asking them to pretty please mail the original title and the paperwork to the Oregon DMV.

Today I got a letter from Chase acknowledging my request but saying that they could not immediately comply because they don’t have the title to my car. According to the letter, the California DMV never sent Chase the title, and apparently Chase never noticed, so now they have to request it and wait at least 45 days for it to arrive, by which time I will have exceeded Oregon’s registration grace period and will be in violation of state law.

Is Monday over yet?

So long, Dash

Dash Navigation sealed their fate today by laying off 65% of the company and announcing that they’ll be quitting the hardware business to focus solely on software.

While the Dash Express is a reasonably good GPS device, it’s not the software that makes it special: it’s the fact that the Dash Express was the first GPS to do real-time traffic well and to have always on two-way Internet connectivity. These are things that any other GPS maker can do, and companies like Garmin and TomTom certainly have the resources and expertise to do them well; Dash just did them first.

It’s likely that Dash would have eventually failed if they had continued trying to compete in the hardware business. However, switching to a software-only business model will only delay that failure. It’s unclear which device makers Dash plans to sell their software to. Certainly not Garmin or TomTom, since their software is already far more polished and mature than Dash’s, despite missing some of Dash’s unique features. The best bet for Dash is to make deals with several smaller device manufacturers, but they’d still be fighting an uphill battle and would likely be unable to compete if Garmin or TomTom decided to challenge them by adding similar functionality to their devices.

I like my Dash Express, but unless Dash pulls something really incredible out of their hat with the next software update (supposedly coming soon), they’re most likely going to fade into obscurity.