Archive for the ‘Howto’ Category

How to remove a bike lock when you’ve lost the key

Wednesday, August 1st, 2007

Stephanie’s old bike has had an albatross of a chain around its handlebars for years. The key is long lost, and the chain is wrapped around the front of the frame between the handlebars and the fork.

There are two commonly accepted ways of dealing with this problem. First, and most obviously, dissemble the bike. Because the cable is mercifully long, it could fit around the top of the handlebars if the brake and gearshift cables weren’t there. To remove them, you remove the brake assembly from the fork and detach the gear shift cable that goes to the crank. Easy enough, however this method is incorrect.

Method two involves getting out your Sawzall® (Milwaukee, of course) and cutting the cable. Problem solved inside of 30 seconds. Let me tell you that there’s no more gratifying way to solve a problem than the way that pointlessly involves senseless destruction yet saves you time.

Testing Java with JRuby

Tuesday, March 27th, 2007

Chris chided me in the Java only gets 10mpg comments for not giving Groovy or Rhino a go. Chris has a fondness for busting my chops equaled by few. However, he does it because he cares, so I thought a bit about using non-Java languages on the JVM.

I still think that in general, I have little use for the Java platform. If I want to write code in something like Ruby or Python, I’ll just use Ruby or Python or whatever as they’re originally distributed. Bolting them on to the JVM really doesn’t do anything for me. That said, if I can use them to get out of ugly, tedious work, maybe they’re worth my time.

As it happens, I recently inherited about a quarter million lines of Java code. There are chunks of it that are somewhat lacking in terms of unit tests, and I’m one of those mutants who really doesn’t like to fix code without exerciseing the problem with a test first. With this project, I’ve been having to write hundreds and hundreds of lines of test code to make very simple changes. It’s safe, but it’s not exactly efficient or fun.

So I took Chris up on his suggestion and gave JRuby a look for writing tests. It works surprisingly well. There’s not that much setup work that you need to do to get the environment up and running, and once you do it’s rather nice to not have to slog through the ugly world that is Java the language to get your tests written.

Here’s a very brief sample. What I wanted to do is have a very traditional ant-based project with the standard init->compile->test->dist dependency chain, but sub JUnit out for JRuby and Ruby’s unit test framework. First, the silly little Java class that I used for testing:

src/java/org/obfsucated/example/Overbearing.java

package org.obfuscated.example;

public class Overbearing {
    /** Javaize a string.
     **
     ** Everybody knows that Java people can't stand data unless
     ** it's XML or some sort of proprietary binary format that
     ** you have to pay Sun $10,000/seat to use.  Our Overbearing
     ** class should be able to take any pedestrian string and
     ** turn it in to something that any Java programmer would
     ** love and cherish forever.
     **
     ** @param original an ugly, non-Enterprise-compliant string.
     ** @returns a String that you could put in some sort of bean.
     */
    public String javaize(String original) {
    if(null == original)
        return null;
    StringBuilder sb = new StringBuilder();
    sb.append("<java-is-rad>< ![CDATA[");
    sb.append(original);
    sb.append("]]></java-is-rad>");
    return sb.toString();
    }
}

And here are the relevant Ruby source files:

src/jruby/test_all.rb

require 'test_overbearing'

src/jruby/test_overbearing.rb

require 'test/unit'
require 'java'

Overbearing = org.obfuscated.example.Overbearing

class TestOverbearing < Test::Unit::TestCase
  def setup
    @overbearing = Overbearing.new
  end

  def teardown
    @overbearing = nil
  end

  def test_creation
    assert_not_nil @overbearing, "We should be able to create an Overbearing object"
  end

  def test_simple_string
    original = "Hello World"
    expected = "<java-is-rad><![CDATA[Hello World]]></java-is-rad>"
    resultant = @overbearing.javaize(original)
    assert_equal resultant, expected
  end

  def test_nil_string
    original = nil
    expected = nil
    resultant = @overbearing.javaize(original)
    assert_equal resultant, expected, "Nil strings should stay that way"
  end
end

It’s all pretty staraightforward stuff. I like to run unit test suites by requiring all of my tests in one file and just calling that with the interpreter. (Thus the “test_all.rb” file.) There are without doubt better ways to do this. You get the general idea, though.

One gotcha is that if you have a package with calital letters, you can’t alias it as above. So let’s say you have a class with a fully-qualified name of org.obfuscated.BadPackageName.Whatever. JRuby — or Ruby itself, if I had to guess based on the way identifiers are usually handled — will not be able to find it if you just say

Whatever = org.obfuscated.BadPackageName.Whatever

Instead, use the include_class function to make sure it’s loaded.

include_class('org.obfuscated.BadPackageName.Whatever')

Long story short, though: don’t use capital letters in package names.

The Ant setup isn’t too difficult, either. Assume the following properties are available:

jruby.dir
The directory where JRuby is installed
jruby.test.dir
The directory where you keep your test scripts (testall.rb and testoverbearing.rb in this case)
The relevant parts of the build.xml file look like this:

  <path id="jruby.classpath">
    <fileset dir="${jruby.dir}/lib">
      <include name="*.jar"/>
    </fileset>
  </path>

  <target name="test" depends="compile">
    <java classname="org.jruby.Main" fork="true" failonerror="true">
      <classpath refid="project.classpath"/>
      <classpath refid="jruby.classpath"/>

      <sysproperty key="jruby.base" value="${jruby.dir}"/>
      <sysproperty key="jruby.home" value="${jruby.dir}"/>
      <sysproperty key="jruby.script" value="jruby"/>
      <sysproperty key="jruby.shell" value="/bin/sh"/>

      <arg value="-I"/>
      <arg value="${jruby.test.dir}"/>
      <arg value="${jruby.test.dir}/test_all.rb"/>
    </java>
  </target>

Type “ant test” and away you go. Now you now longer have to slog through things with Java, and you’ve removed the compile phase from your test cycle. Bonus.

So thanks, Chris. That was a fine idea.

Removing duplicate tracks from iTunes with Ruby and RBOSA

Saturday, March 24th, 2007

When I put a new hard drive in my computer, I decided to reinstall the operating system and install applications and data from scratch. Unfortunately, I had a small mishap and accidentally imported two copies of my iTunes library. Removing duplicates by hand would have been possible, but it would have been tedious as well. Mercifully, I stumbled on to RBOSA, so I was able to let the computer do it.

RBOSA is basically Applescript for people who never got around to learning Applescript. The interface to things like iTunes is very simple, so it didn’t really take a lot of work to get something to find duplicates up and running.

The strategy I used was to look at songs in the main library (the method I used for finding the “main library” looks kind of suspect, but it worked. Use caution if you try this at home) and put all duplicates in to a new playlist. Once they were there, I was able to check them over to make sure that they were dups and delete them.

Now, if you’re playing the home game and you know the secret trick for finding and deleting large groups of duplicates (around 8,500 tracks in this case) without busting out the programming: please tell me. I’m pretty sure that I’ll need to do this again at some point, and I’m all about doing things the easy way.

Follows is the script. I used Ruby 1.8.6 and RubyOSA 0.3.0.1 (installed via gem.)

require 'rubygems'
require 'rbosa'

itunes = OSA.app 'iTunes'

dups = itunes.make OSA::ITunes::Playlist
dups.name = 'Duplicate Tracks'

class OSA::ITunes::Track
  def eql?(o)
    artist == o.artist &&
      album == o.album &&
      track_number == o.track_number &&
      name == o.name &&
      time == o.time
  end
  def hash
    to_s.hash
  end
  def to_s
    "#{artist}/#{album}/#{track_number}/#{name}/#{time}"
  end
end

seen = Hash.new
itunes.sources[0].playlists[0].tracks.each do |track|
  seen[track] ||= Array.new
  seen[track] << track
end

seen.values.each do |tracks|
  if 1 < tracks.length
    # Keep the file with the largest bitrate.
    tracks = tracks.sort { |a,b| b.bit_rate <=> a.bit_rate }
    keep, rest = tracks[0], tracks[1..-1]
    rest.each { |t| t.duplicate dups }
  end
end

Making irb behave like the Rails console

Thursday, March 1st, 2007

A project I’m working on using Ruby has a bunch of functions that are usually run in groups but from time to time will need to be run individually. My initial solution to this problem was to create a whole mess of shell scripts to run the individual pieces. However, that looked like it was going to require a lot of typing, and I don’t much like to type.

Faced with actual work, I remembered the Rails console. This struck me as the ideal solution. It does command completion, so I wouldn’t have to remember the specifics of every little command. It turns out that the console is nothing more than irb with a few flags. Specifically:

 irb -r irb/completion --simple-prompt

Given this, I created a file with shortcuts for the pieces of code that I would want to run:

 #
 # shortcuts.rb
 #
 require 'project/important_stuff'
 require 'project/other_stuff'

 def do_thing_a
    ...
 end

 def do_thing_b
    ...
 end

 def something_else
    ...
 end

 def whatever_more
    ...
 end

And created a shell script to wrap the whole thing up:

 #!/bin/sh
 #
 # console.sh
 #
 exec irb -r irb/completion -r shortcuts --simple-prompt "$@"

So now I can run “console.sh” and type things like “do<tab>a” or “wh<tab>” and have an easy way to run my code. This pleases me.

Sunday night PSA

Sunday, September 17th, 2006

There’s enough vermouth left over from your first round. For number two, all you need is gin and two more olives.

Viva la Revolution! Or not!

Friday, August 11th, 2006

When Fidel Castro’s transferred power to his brother Raúl the other week, an important question ran through the collective mind of America. What was that question, you ask. Will Cuba remain a communist state after Fidel steps down? Will the United States annex Cuba and make it the 51st state? Will we “liberate” Cuba, plunging it in to the bloody depths of sectarian violence and eventually civil war? Heck no! The question on the tip of America’s tongue is how will this affect my ability as a consumer to purchase and enjoy quality cigars?

It’s most typical in America to purchase fine domestic — “domestic” in this context is hipster slang for “non-Cuban” — cigars, and that’s well and good. Unfortunately, to get a quality domestic cigar, you usually have to part with some pretty serious coin, and there’s a lot of chaff to sort through before you get to cigars that you like. See, for example, the unfinished and destined to stay that way box of “Lone Wolf” — marketed by Chuck “Ranger” Norris — robustos taking up space in my humidor. ($1 each if anybody wants them.) Ug. Now, the true value shopper goes immediately to Cuban cigars. The price is right — Fine cigars can be had for $10-$15/ stick, whereas you can pay $20-$30 for a domestic cigar of comparable quality — and it’s hard to find a dud. They may not know how to play nice with the international community, but the Cubans make a mean cigar. It’s hard to go wrong with them, so long as you know how to get them.

As a brief aside, let me just say that as far as I know, it’s illegal or something to even think about Cuban cigars. America doesn’t like Cuba, Cuba does some bad stuff, doesn’t have oil, and it doesn’t present itself as a huge trading partner, so we don’t want anything to do with them. Plus they make boats exclusively out of inner tubes and only drive old cars, and that’s not cool. So there’s a law against importing or exporting anything to or from Cuba, and as everybody knows it’s bad to break laws. Even the silly ones. So everything I’m about to say is purely fictional speculation. If you trade with Cuba, the terrorists have already won.

Where was I? Oh, yeah: how do you get Cuban cigars. There are several ways. The first and probably the easiest is to go to your local smoke shop and ask for them. The phrase that pays is “do you have anything that’s not on display?” Now, if you say this while the store is busy, they’ll probably say “no” and that’ll be the end of that. Same goes if they just don’t like the look of you. Or, you know, if they actually don’t have any Cuban cigars. On the other hand, I have it on good authority that if you’re hot and female you can walk in to a shop, ask for a Cuban cigar by name in a crowded room and get it. This has never worked for me.

Once you get to the “not on display” part, there’s one more important hurdle: try to know what you’re looking for. It’s simply bad form to respond to “what exactly would you like, sir?” with “<sfx: crickets>.” Any competent smoke shop clerk could guide you to something good, but if they’ve brought out the Habanos for you, they’re doing you a favor. Try not to waste their time.

Now, that all sounds pretty easy. Unfortunately, there’s a down side: price. In my (admittedly limited, and of course purely fictional) experience, brick and mortar cigar shops charge way too much for Cuban cigars. I’ve seen markups as much as 300%. To be fair, the shops are committing any number of crimes on your behalf, but 3X really is highway robbery. There ought to be a law against that.

The way around this horrendous problem is tried and true and has been used by the informed shopper for thousands and thousands of days: The Magic Internet Machine. Through the wonders of science or whatever it is that makes the damn thing go, you can fire up a web browser, whip out a credit card and have an aged box of Habanos in your hot little hands in a mere matter of days. As far as I’m concerned, there’s no better way to purchase quality cigars for a reasonable price.

There are many, many outfits that will sell you Cubans. Most are in Europe. Some are Mediterranean states. They’re all over, really. They work just like any other on-line store. Sort of.

A personal favorite — in theory, of course — is TopCubans.com. They’re based in Geneva, Switzerland, and their service is outstanding. When they deliver the cigars, they arrive in a box labeled “Authentic Honduran Cigars, aged in Switzerland.” I really wish they would put “Honduran” in quotes on the label. That would be priceless. A nice touch that TopCubans adds on is that they take the bands off the cigars before they ship them such that if the package is* seized by customs, there’s no real way for them to tell what it is you’re getting. The bands arrive in a separate package a few days later. Their prices are a *little on the high side for Internet merchants, but they’re still well within the realm of reasonable.

CigarExport.com, which also goes by “Puroexpress,” is another fine retailer. Located in Spain, they’re supposedly the people to order from when time is a factor. They’re a bit more cavalier about shipping than TopCubans — their cigars arrive with a great big “Habanos” lable on the box — but they guarantee shipping and will re-ship at no extra charge if your order is confiscated. Of note is that their shipping charges are included in the price of the cigars. This can be substantial.

If you do end up ordering from one of these outfits, do try to receive the package in person. This isn’t a security concern, but one of entertainment. All of the delivery services know what’s up with domestic cigars shipped in from Europe. “Enjoy your Honduran cigars,” they’ll say with a considerable sneer. Have them delivered to your place of employment for extra hilarity.

I hope this brief and entirely fictional guide was at least enjoyable if not informative. Maybe one day Cuba and the United States will learn to play nice together and top-notch Habanos will be available at every corner store. Until then, Viva La Internet.