Wednesday, 31 December 2008

Link: A signature cadence

Too many websites (and applications) are soul-less, corporate entities that treat you like just another number.

Rands' article: A signature cadence shows how a human tone can make a big difference in how we view a site. Even tiny details like the copyright wording can help make an overall impression that you are actually a bunch of real people. I think we need more of that.

Tuesday, 30 December 2008

Squidoo and ssh tunneling

I've found squidoo - a site where you can set up pages called lenses that help direct people to all the relevant information about a specific topic.

I love it!

I've only just begun, but I think I'll slowly add pages on my favourite topics and see where it goes.

ssh tunnels R Us

To start with, I put up a page on ssh tunneling.

For years I've used ssh to login to a remote linux box to get work done. But recently I had to get through to the http server on my work machine - which was hidden behind a firewall. The best way to do that, it seems, is to set up an ssh tunnel and just port-forward the http port to my local machine!

In the process I found several useful (and less useful) articles on the subject, and it took me ages to crawl through each one to figure out which was which. It seems "ssh tunneling" means different things to different people...

So where does squidoo feature in all this?

In the squidoo lens, I gave an overview of ssh and tunneling - and then listed each of the articles with a brief description of the contents. In this way, the squidoo page acts as a differentiator for any people searching for the same thing in future. Hopefully it'll cut down the time people need to spend scanning all the possible google results they can find. They can zero in on an answer all the more quickly.

[Edit...] More squidoo...

So I've now gone and added a few more pages on my other hobbies.

For starters, I quite like brewing mead - which is a wine made from honey. I've been doing it for about 15 years now, and you can read more about it in my lens on mead, or you can jump straight to my (long) howto lens that will teach you how to make mead in three weekends.

Alternatively you can try your hand at home preserving with vacola - an ingenious system of bottling that creates a vacuum seal in the bottle to hold on the lid.

Stay tuned for more fun stuff as I go along.

Thursday, 25 December 2008

Link: 13 coding nightmares to avoid

Here is a great list of bad RoR practices - make sure you read the comments as there are some interesting exceptions raised.

Merry Christmas!

So I've been pretty quiet for the past month. That's because I'm running around like a mad thing getting set to make a big move to the UK. Won't be for another month yet, but it's consuming all my spare time.

Anyway, today's been quiet enough to sit down and actually write something so - merry christmas everybody!

Saturday, 29 November 2008

I wrote a novel - w00t!

Woo hoo - much celebrating as I have successfully finished 50,000 words for NaNoWriMo! You can see my novel info here - though not the novel itself, that's still only a first draft!

Now to party for a while. :)

Wednesday, 5 November 2008

KioqKioqKioq OR fixing mutt's base64 problem

So I've occasionally been getting *really* useful email messages such as:

KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KgpUSElTIElTIEFOIEFVVE9NQVRFRCBFTUFJTCAtIFBMRUFTRSBETyBOT1Qg
UkVQTFkuCioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioKCgpEZWFyIE5ldyBNb25leWJvb2tlcnMgQ3VzdG9tZXIsCgpZ
b3UgaGF2ZSBjaG9zZW4gbWJfdGVzdF9jb21wYW55QHRhcnluZWFzdC5jb20g
YXMgdGhlIGVtYWlsIGFkZHJlc3MgZm9yIHlvdXIgbmV3IE1vbmV5Ym9va2Vy
cyBhY2NvdW50LiAKClBsZWFzZSB2ZXJpZnkgdGhpcyBlbWFpbCBhZGRyZXNz

Not having the slightest clue as to what was causing it - I'd simply return them to the sender and ask for help... sadly the senders generally didn't know what it was either.

It turns out that the sender's setup is incorrectly labelling these emails as 8bit... when it's actually been encoded in base64. To fix it:

  1. Save the email to its own new folder (just so there's only one email in the file to edit).
  2. Open it up in a plain text editor (eg vim)
  3. Update the header line that reads:
    Content-Transfer-Encoding: 8bit to
    Content-Transfer-Encoding: base64 - save and close
  4. Navigate to the folder in mutt and read away happily.

Sunday, 2 November 2008

National Novel Writing Month

It's November - and that means it's time to whip out a pen and start a frenzy of writing in the hopes of finishing up a new masterpiece... or at least 50K of whatever comes to mind during this month of madness.

It's National Novel Writing Month (or NaNoWriMo for short). The site was slashdotted for the first day and a half, but the servers seem to be taking the load now - which means we have a chance to actually update our wordcounts and read the forums.

NaNoWriMo is a personal challenge to start writing a novel on November 1st and aim to have 50,000 words by midnight on November 30th. Last year there were over 100,000 participants - of which 15,000 passed the 50K mark by month's-end. I was one of those 15K :)

Here's a link to my author page so you can see how much I've done so far this year. I'll also add a wordcount widget onto the blog for the duration of the month (should be there in the left-hand column).

It's heaps of fun and it's open to anyone. So, if you're up to a unique kind of personal challenge, join us in our month of writing. Or just come along and see what all the fuss is about!

Wednesday, 29 October 2008

Rails a little over-protective?

Was busy developing and minding my own business, when suddenly my functional tests all stopped working giving me this error:

ActionController::InvalidAuthenticityToken: No :secret given to the #protect_from_forgery call. Set that or use a session store capable of generating its own keys (Cookie Session Store).

Now we happen to have just switched on the use of the cookie store - and the actions all work just fine from the browser. Checking the forms even shows up the authenticity tokens etc... this only occurs during testing.

Googling gives a few rspec-based solutions, but very few are even possible for Test::Unit. I tried disabling config.action_controller.allow_forgery_protection - but that did a big nothing for me. So I bodgied up a quick-n-dirty workaround just for the test environment as per below.

Right now I still don't know what's causing the bug, but this gets me past it until I can figure out what's actually wrong. YMMV :)

  # See ActionController::RequestForgeryProtection for details
  if RAILS_ENV == 'test'
    # dodgy workaround for Rails 2.0 bug in functional tests - which don't
    # seem to use a cookie store properly. Reference to issue:
    # http://groups.google.com/group/railsspace/browse_thread/thread/fcdbfa4e65bf86de
    protect_from_forgery :secret => 'c1c6ebaee01fecc9aa9bc105d235b2c2'
  else
    # Uncomment the :secret if you're not using the cookie session store
    protect_from_forgery # :secret => 'c1c6ebaee01fecc9aa9bc105d235b2c2'
  end

Tuesday, 28 October 2008

Headhunters strike out again

A follow-on from my negative experience with headhunters. I've begun receiving exactly the sort of "job offers" that I was fearing. I've got offers (from all over the world, mind) asking me if I'd like to work as (for example) a junior developer on an embedded-kernel contract in Belgium... which'd be nice and useful if I were interested in that sort of thing instead of having only 6 months non-commercial experience (at uni) doing this stuff as a elective subject... or at least held a work-permit that allowed me to work in Belgium.

The end result makes it fairly obvious that their recruiters are just too damn lazy to do more than a quick search on the db... followed by spamming all the results. They've ripped out the db-friendly data (ie my naked skillset) and divorced it from the important stuff (ie what sort of job I'm actually interested in). Leaving me to be spammed by every idiot with a contract to push.

If I were a junior developer, desperate for any job I could get, I'd probably just have to suck it up... but I'm not - and they're alienating an in-demand developer with lots of experience. This doesn't make me feel like responding positively to any of their future offers... even if they do suit my requirements.

What gets me is that it'd be so easy to make this system work. Even if they had a few extra fields in their db for "what type of job is the candidate looking for", they could run these as a filter over their resultset and turn that spam into much-less-despised targetted advertising.

I'd even be interested (possibly even grateful) to receive such a service - instead of so annoyed that I've blogged about it twice.

Enumerable.average

Was looking around for a quickie function to do an average on an Enumerable/Array just like max and min - and found there isn't one. So here's a quick-n-dirty one that you can drop into config/environment.rb. Examples for use in the comments:

module Enumerable
  # returns a simple average of each item
  # If a block is passed - it will try to perform the operation on the item.
  # if the result is nil - it won't be counted towards the average.
  # Egs: 
  # [1,2,3].average == 2
  # ["a","ab","abc"].average &:length == 2
  # @purchases.average &:item_price == 10.45
  def average(&block)
    the_sum = 0
    total_count = 0
    self.each do |item|
      # either the actual item, or a method called on the item
      next_value = block_given? ? yield(item) : item
      unless next_value.nil?
        the_sum += next_value
        total_count += 1
      end
    end
    return nil unless total_count > 0
    the_sum / total_count
  end
end

I used it for displaying neat averages in the view thus:

    <p>Averages:
    <br />Number of items: <%= @purchases.average &:num_items -%>
    <br />Unit price: <%= @purchases.average &:price -%>
    <br />Total price: <%= @purchases.average {|p| p.num_items * p.price } -%> </p>

Thursday, 23 October 2008

That doesn't help me, it helps you

I just got off the phone with Australia Post and I'm not happy. Even though they were very polite to me, they failed to provide a good customer service experience. This issue requires a bit of backstory.

While in Melbourne last weekend, I'd bought two half-cases of wine and paid for them to be delivered. I have no car, so I left explicit instructions for the parcels to be left on the back doorstep if I was not at home.

I got one of the little blue cards in the post yesterday, telling me that they tried to deliver one of the parcels to me in the 1 hour when I was out of the house getting some lunch. I figured that the winery must have forgotten to put the "in case not at home" message on the parcel, so today I decided to just fetch it from the post office.

I damaged my knees fencing, a couple of years ago, so walking eight blocks while carrying a heavy box is painful for me. My arms and knees both ache, now, but I got the parcel home... only to find a second little blue card in the mailbox.

The parcel from yesterday clearly has the "in case not at home" instructions printed on the outside, so I figured I'd call up Australia Post and see if they could actually do what I paid them to - which is to deliver my second parcel to my house.

I called them up and waded through their long telephone menu-system to get to a real human being. The man at the other end seemed kind enough, but the only option available to him was to allow me to lodge a complaint against the contractor who failed to follow the given instructions.

I don't really want to lodge a complaint - I just wanted my parcel delivered - which is what I paid for.

I asked the man if he could find anyone that would be able to help me get what I wanted. He went back to his supervisor, leaving me on hold, and returned to tell me that the only way I could get it redelivered was to call up the people that I originally bought it from (some winery out in the Yarra valley - I don't know which one as the parcel is still sitting in the aussie post office), and to get *them* to call aussie post and figure out if their contract supports "redelivery-on-failure"...

Good grief! From my POV it's pretty simple:

  1. I paid for delivery to my home
  2. Aussie Post stuffed it up
  3. Aussie Post should find a way to get it right

Instead of finding a way to get my parcel to me, they kept insisting that they were helping me by starting up a complaints process and making sure it "never happens again". If you want to reprimand your contractor, that's your business. It will help you improve your own processes over time, and no doubt his non-instruction-following is the weak link that broke in this particular chain of events...

But doing this isn't going to help me. Getting my parcel to me helps me - that's all I want, and Aussie Post wasn't willing ot help in that regard. I was a customer on the line right then and there with a problem that Australia Post caused - and wasn't able to get any resolution that actually solved that problem.

I was left with the feeling that Australia Post wasn't willing take responsibility for this mistake and do something about it. Instead they wanted to shift the blame to the contractor, and then claim that responsibility was out of their hands.

This reeks of bad customer service.

If you want to leave a good impression with your customers, follow one of the basic rules of human conduct: if you stuff up, take responsibility and try to fix it. Whatever you do, don't just give a reassurance that it won't happen again... we won't believe you. After all, you've just proven that you can't be trusted. At least if you try to find a way to give me what you promised in the first place - it'll go a long way towards reassuring me that you can act in good faith.

Tuesday, 14 October 2008

soap4r + rails can't find SOAP::Mapping::EncodedRegistry

Joining a new project, I had to go through the usual setting-up rigmarole - which means finding several new things to break/configure/reinstall. One of which was to get soap4r to run.

I'd run gem install soap4r just fine, but running rake was giving me the error below:

rake aborted!
uninitialized constant SOAP::Mapping::EncodedRegistry

Scrounging around gave several solutions that didn't work, mainly using two of the three lines below. I required all three of the following before it ran for me.

# Add these lines to config/environment.rb just before the Rails initializer code
require 'rubygems'
gem 'soap4r'
require 'soap/mapping'

Tuesday, 7 October 2008

Words and pictures

Ok, this is a neat toy: Wordle is a site that runs a java applet that takes some text (or a URL for a feed) and make a pretty word-picture... like the one below for this blog.

Hmmm... I wonder if I can use it to improve the editing of my blogposts. Looks like I use "going" far too much!;)

Sunday, 28 September 2008

Headhunters and a dearth of trust

What is it with some headhunters?
I had a phonecall from a headhunter the other day that really rubbed my fur up the wrong way.

First, they wanted my CV in Word format. I hate that. Quite apart from having to explain that I use Linux - which frequently leads in to the "what is an OS" discussion that I find so annoying coming from an IT recruiter. Yes I can use OpenOffice to create a Word doc, but it's a preference thing. I prefer to write my CV in PDF so I have more control over the formatting - because I've found that .doc format "helps" too much, and suffers from bit-rot.

But it's not like they can't read/print-out a copy of my CV if it's in PDF. What really gets me is that there are only two reasons for wanting my CV in Word. First is so they can copy/paste my skills/experience into their mammoth database - reducing me to a set of numbers... which I really don't like.

I recognise that might be a knock to their usual system, but I really don't like being just a number in an uncharted sea of applicants. It doesn't work for me to be recruited by a company that would view me as only so important as the number (and not the quality) of the years of experience I have.

Second is that they want to remove my contact information so that they are the only point of contact between me and the employer. This view is especially reinforced by headhunters that refuse to give you the prospective employer's name, industry, size or any other potentially-identifying details (or politely change subject when I ask, as this one did). How the hell am I supposed to decide if I'm interested in working for a company I know nothing about?

I should point out - I get a phonecall a week from various recruiters. I don't have time to go to an interview a week - so I have to decide, based on what you tell me, if you are worth a morning of my time.

Word to the wise: recruiters perform a valuable service - both to employers and employees. If you are good at what you do, then nobody will be unhappy about paying you for your services! The only recruiters that need to resort to cheap tactics like hiding names are the ones that cannot build a reputation for excellence on their own... thus if you flat-out refuse, then it instantly gets my suspicions up.

Yes, I'm sure you will get ocasionally burnt by employees and employers that are unscrupulous and try to screw you out of your fee. But are those the kind of clients you want to keep anyway?

Recruiting is a people business - it is outsourced HR and builds upon long-term relationships. Trust is important, and screwing around like this ruffles that layer of trust and just feels tacky.

Please don't do it.

Thursday, 25 September 2008

Rspec mocks too much

I've recently had to learn the other side of testing - ie rspec, due to my new contract having a test suite written in "the other testing suite" * ;)

Seems fairly straightforward so far, but there's one big worry I have: Rspec has a huge reliance upon mocks.

Now I completely understand (and endorse) the benefits of using mocks. It means you can independantly test a model/controller/whatever without it mattering if something happens to have broken in some other model/module/whatever. This is a Good Thing and allows for more accurate testing due to all the benefits of loose coupling. However, I get a bit worried if everything is mocked out and there are no integration-style tests at all.

For example, if I'm testing a view, and using rspec best practice I've mocked out all model objects and don't bother with the real thing. What happens if a model changes (say a column is removed that shows up on an index list)? The view specs all rely on a mock that explicitly states what is returned, so the view specs all still pass. But the index page will be broken for a user that actually uses the site, because the real object doesn't bahave that way anymore. The mocks and the model are out of synch. :P

In an infrequently-used area of the site, this sort of error may go undetected and slip through to release.

This worries me. I know I like to rely on my test suite to catch things like this wherever possible. Sure I generally do a manual click-through, but I know that this is unreliable especially WRT edge-cases.

So, am I needlessly worrying? Have I simply missed something about how rspec is supposed to be used? What's best practice in this situation?

*Which admittedly feels a lot like having to switch from vi to emacs... Sure I know that "the other one" works for lots of people, and I meant to get around to learning it someday...

Tuesday, 23 September 2008

Getting ffmpeg to work under ubuntu

I had a fair whack of trouble getting ffmpeg to compile on ubuntu. These are the steps I took that finally got it working for me.

Firstly - I'm going to assume you've downloaded and installed the appropriate libraries (codecs?) for the various audio/video formats that you are going to use (eg lame). I'm just going to cover making ffmpeg actually compile and run.

The usual set of steps will be

  • Downloading ffmpeg: svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
  • cd ffmpeg
  • Configuring appropriately to your build. Eg: ./configure --enable-libmp3lame --disable-vhook --disable-mmx --enable-nonfree --enable-gpl --enable-shared --enable-libamr-nb --enable-libfaad --enable-libx264 --enable-encoder=x264 --prefix=/opt/local --extra-ldflags=-L/opt/local/lib --extra-cflags=-I/opt/local/include
  • make
  • sudo make install

If that all works for you, then brilliant, but for me it fell over while trying to make, telling me it couldn't find x264. For some reason it's necessary to add --enable-pthreads to make it work on ubuntu.

The next big hurdle for me was that a bug appears in the v4l2 library for ubuntu. It doesn’t properly load some of the basic linux types. This is apparently a well-known bug in some of the older linux headers, and will stall the compilation of ffmpeg with a whole slew of bogus error messages, that essentially boil down to the __u64 and __s64 types failing to be defined appropriately.

To make a temporary fix, you can open up asm/types.h (I used find to find it) and figure out where the asm types are located on your distro (for me they’re in asm-i386/types.h).

Now, copy the two lines that define __u64 and __s64 and paste them into:
/usr/include/linux/videodev2.h just above their first use to help define v4l2_std_id

Note - this is an ugly, quick hack, but it should get the compilation going again. For a more permanent solution - I'd suggest chatting to the ubuntu people... or maybe it's time for me to get around to upgrading from feisty ;)

That will generally get you compiled and installed, but I then fell over a run-time bug that boiled down to an error message: “cannot find libavdevice.so.52”. This problem had me stalled for weeks. Google returns a lot of talk about the problem, but very few solutions, but eventually I stumbled across the answer: you need to add a library path to your environment thus:
export LD_LIBRARY_PATH=/usr/local/lib/

Finally ffmpeg safely up and running on ubuntu. Yay!

Saturday, 20 September 2008

Snippet: MyModel.options_for_select

How many times have you written a quickie drop-down box to choose one instance of an associated model? Here's a quickie monkey-patch that will help. Put the following in environment.rb (or similar):

class ActiveRecord::Base
  # convenience method for selection boxes of this model
  # Assumes existance of a function "display_name" that will be a
  # displayable name for the select box.
  def self.options_for_select
    self.find(:all).map {|p| [p.display_name, p.id] }
  end
end

Make sure you have a function in your model named "display_name" that returns what you'd like to see in your drop-down, eg:

class Person < ActiveRecord::Base
  has_many :posts

  # convenience method for the person's name
  def display_name
    [first_name, last_name].compact.join(', ')
  end
end
class Post < ActiveRecord::Base
  belongs_to :person

  alias :display_name :title
end

Then use in a view (eg as follows):

<% form_for(@person) do |f| %>
<p>Pick a post: <%= f.select :post_id, Post.options_for_select -%><%= f.submit 'Go!' -%></p>
<% end %>

Thursday, 4 September 2008

Snippet: monkey-patching a gem

Need to make a quick monkey patch to a gem you're using? Follow the steps below:

  1. If you don't have a vendor gems directory: svn mkdir vendor/gems
  2. cd vendor/gems
  3. Unpack the gem into your vendor/gems directory with
    unpack gem <the_gem_name>
  4. Checkin the above changes so you have a clean version of the gem to start with
  5. Make your monkey patches and check them in
  6. Make sure vendor/gems is in the loadpath for gems

And you're done

Tuesday, 19 August 2008

Link: Why I don't have a startup yet

Great post called Why I don't have a startup yet. Snippet:

"I love what I do at Yahoo, and I care enough about what we create that I want to focus all my energy on creating value for users. It’s good practice. But as long as I work at this job, I won’t have enough left over at the end of the day to seriously invest in anything else."

But further to that - there's so much in the world to do. Doing work is part of that, but if it's the only thing in your life, then "All work and no play makes Taryn a dull girl". Sure, some coding is play - and I do love to code my own stuff too... but I like so many things, that if I focus my off-hours on coding, I'd lose sight of all the rest that life has to offer.

So sure, I choose to spend some time coding, but also a lot of time reading books while sipping great coffee, getting together with interesting bunches of people, travelling to far-flung places, writing up my travels or even writing fiction (however badly), taking photographs, attending medieval feasts and wars, making home-brew mead, or even just walking outside and enjoying the sun.

Life is an adventure... make the most of it.

Wednesday, 13 August 2008

Tact filters for geeks

I just stumbled into this great article. It described the difference between how geeks vs "normal" people filter their social discourse for tact. It makes a lot of sense, and explains my frustration with non-geeks not "talking straight"... as well as, no doubt, the shocked reactions of these same people when I do. Interesting reading.