Woodlander a weblog of interesting things

Cocoa Programming with Ruby

I haven’t even read this article and already it sounds cool!

Abort, Retry, Fail — and other classics

Technologizer apparently maintains a list of classic error messages. Well, someone has to. The mention of ‘Abort, Retry, Fail’ brings back so many happy memories of mucking around in DOS — now there was a Microsoft operating system I could live with.

Securing Rails Login Credentials

For a while now, I’ve been using the following trick (or something close to it) to secure my login credentials in my Rails code.

require 'digest/sha1'
class AdminController < ActionController::Base
  before_filter :authenticate

  private
  def authenticate
    authenticate_or_request_with_http_basic do |username, password|
      Digest::SHA1.hexdigest(username) == 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4' and
      Digest::SHA1.hexdigest(password) == '4f50f366a3f474aaac57f48ea1dce13ab1af9e5e'
    end
  end
end

Where those two long strings of random digits are hexed versions of my username and password. I do this because I don’t want to put my login details in plain sight in my code — what if my laptop was stolen?

Anyway, here’s a better version which you can drop into your Rails app somewhere (I’m working on a plugin):

class ActionController::Base
  def authenticate_or_request_with_hexdigest(credentials)
    require 'digest/sha1' unless defined?(Digest::SHA1)

    authenticate_or_request_with_http_basic do |username, password|
      Digest::SHA1.hexdigest(username) == credentials[:username] and
      Digest::SHA1.hexdigest(password) == credentials[:password]
    end
  end
end

Use thus:

class AdminController < ApplicationController::Base
  before_filter :authenticate 

  private
  def authenticate
    authenticate_or_request_with_hexdigest(
      :username => 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4',
      :password => '4f50f366a3f474aaac57f48ea1dce13ab1af9e5e'
    )
  end
end

Of course, you have to hex those credentials manually (in IRB, for instance): but you only need to do that once. What do you think?

Things Touch Syncing

Things for the iPhone – aka Things Touch — is a wonderful idea. You run the desktop version of Things (Cultured Code’s elegant to-do/GTD app for the Mac) and use it to track your projects and to-do lists in a simple, intuitive way. Then, when you’re ready to go out and about, you fire up Things Touch and sync it with your Mac wirelessly. And boom! All your to-dos are ready to be managed, edited, and marked ‘done’ on your iPhone while you’re away from the office.

When I first downloaded Things Touch, my plan was to use it away from my Mac to add items to my to-do lists as they came to mind. Often you have an idea while you’re out, and it’s good to get it down there and then so you can focus on whatever else you’re doing. Then, when I got back home, I would sync with my Mac and cary on where I left off.

But Things Touch syncing doesn’t work properly. I often find that, when syncing, the to-dos I’ve checked off on my Mac since the last sync are reverted back to their uncompleted state, even though I’ve not touched them on my iPhone. This makes a real mess of syncing: Things is effectively a record of the current state of your work — what’s done, what’s waiting to be done — and if that record is messed up every time you sync, you’re left needing to repeatedly review accuracy of your work record and correct your to-do lists manually, which is exactly what Things is meant to do for you.

The headaches that come with the constant ‘did I do that or not?’, ‘did I mark this as done or not?’ are one of the most annoying things about tracking multiple projects, and Things syncing is currently adding to them, not reducing them like it should be. 

I know the app is in beta, and I’ve just downloaded the latest update, so let’s hope it solves the problem. Thing Touch has a lot of promise and is an ideal use of the iPhone-as-productivity-tool, so I really hope the bugs get ironed out.

Rothko Meets Web 2.0

COLORlovers article comparing Rothko’s art to colour swatches. In a nutshell: simple blocks of colour are beautiful.

Creating URL-Friendly Strings with Ruby

This is from a project I’m working on at the moment. The scenario: you have a string — say Post#title — that you want to convert for use in a URL. Some would suggest a simple substitution of punctuation marks for hyphens, but that creates ugliness when “John’s New Car” gets transformed into “john-s-new-car”: not what we want.

So, slightly more subtle:

class String
  def to_url_slug
    self.downcase.gsub(/['"]+/, '').gsub(/[^a-z0-9]+/i, '-')
  end
end

The first gsub removes single and double quotes from a string; the second gsub replaces non alphanumeric characters with hyphens (if you don’t recognise them, those funny strings of characters are regular expressions) — note that ‘i’ modifier which tells the second regular expression to ignore case when matching.

"John's New Car".to_url_slug # johns-new-car
"A (Terrible) Mess".to_url_slug # a-terrible-mess

TechCrunch Moans About Twitter

TechCrunch seems to like complaining about Twitter — specifically, about the lack of more complex features such as groups. In this most recent post, Don Reisinger argues that Twitter needs — yes needs – groups. The hyperbolic title (”Why Twitter Needs To Do More”) doesn’t help balance the tone of the article, betraying a common, and unfortunate, attitude that’s prevalent in techie circles.

The attitude I’m talking about is the one that says, ‘We need more and we need it now’ and ‘the feature I want is essential’. No, you don’t, and no it isn’t. Technically-minded users forget that the ability to sort yesterday’s emails by lowercase firstname of sender and filter the results through a regular expression search might be essential to them, but isn’t essential — or even vaguely important — to the vast majority of users. Geeks are called geeks for a reason — and I’m counting myself in here.

We need to remember that while us technoheads might need and enjoy more complex features, the same features are irrelevant or even confusing for others. Of course, I’m not arguing that groups would be a tremendously difficult thing for Twitter to implement: I’m arguing that Twitter is doing exactly the right thing by taking things slowly, getting the basics right first, and giving people just one great feature that they love. The rest will come with time.

Habari 0.5 Reviewed

Nice detailed review of Habari 0.5.1.

Landscape Notes: West Yatton Down

I’ve just got back from a wonderful wander through a small nature reserve on the edge of the Cotswolds. West Yatton Down is one of those hidden-valley sort of places that you drive past every so often, and which I’d seen regularly on the map and had thought would be a good place to visit. Just like all beautiful places in England, it’s quiet, secluded, private, green, tree-lined (the natural beauty of trees is a subject all of its own), and threaded through with a little stream that today — in a surprisingly warm september sun — barely registered as more than a dribble for much of its course.

Places like this are magical. You walk through them and see the footprints of cattle, deer, other animals; you hear a buzzard swoosh over your head and look up to see it close enough above you that you can pick out the individual feathers in its wings; you walk along paths that, despite the human footprints, feel like they haven’t been used in years. It all adds to the feel of a separate, defined, enclosed space — defined in this case by steep, grassy walls that reminded me of the chalk downs near Marlborough. 

Walking through a valley like this, you can imagine how prehistoric people, spending their whole lives outdoors, became intensely attuned to the presence of places. Wander down a Cotswold valley too quickly or too casually nowadays, and all you see are the standard, repeating woods and hills, monotonous almost, like the rest of the country seen in a modern daze. But go calmer and you start to believe that ancient humans could have seen very natural places like this valley as the equivalent of our cathedrals, and you understand that monuments like Avebury, Silbury, Stonehenge or the long-barrows were not developed in isolation but were most likely the result of — the extension of — a deep, natural relationship between people and their landscape.

Ruby Array Methods

Ruby has Array#any? (which lets you ask if there are any items in an array — with an optional block for fine-grained selection) and Array#empty? (which should be self-explanatory); but like all greedy coders, I want more.

class Array
  # If a block is given, calls +collect+ on self using
  # the block provided, returning true if the array of
  # collected values has a length greater than one.
  #
  # If no block is given, returns true if self.length > 1.
  #
  # In all other cases, returns false.
  def many?(&block)
    if block_given?
      self.select {|x| yield(x) }.length > 1
    else
      length > 1
    end
  end

  # If a block is given, calls +collect+ on self using
  # the block provided, returning true if the length of
  # the array of collected values is 1.
  #
  # If no block is given, returns true if self.length == 1.
  #
  # In all other cases, returns false.
  def one?(&block)
    if block_given?
      self.select {|x| yield(x) }.length == 1
    else
      length == 1
    end
  end
end

 

← Before