[Skip To Content]


# PermaStore

  1. class PermaStore < Hash
  2. def self.load
  3. if File.exists?( "data.dump" )
  4. File.open( "data.dump", "r" ) do |f|
  5. return Marshal.load( f )
  6. end
  7. end
  8. return PermaStore.new
  9. end
  10. def []=( key, value )
  11. super
  12. save
  13. end
  14. def delete( value )
  15. super
  16. save
  17. end
  18. protected
  19. def save
  20. File.open( "data.dump", "w" ) do |f|
  21. Marshal.dump( self, f )
  22. end
  23. end
  24. end

Do whatever you will with it. It’s not thread safe, but that’s easily fixable if you’re so inclined.

# Ruby and Unicode

Nope, not the usual boring text encoding stuff, but this :

  1. #!ruby -Ku
  2. module Kernel
  3. def( *args ) # Sum of
  4. args.inject( 0 ) { |i, j| i += j }
  5. end
  6. def( number ) # Root of
  7. Math.sqrt( number )
  8. end
  9. end
  10. puts √(49)
  11. puts ∑(1,2,3,4,5)

Seriously cool. Idea stolen from here.

# Ruby Games Programming

Gosu is a 2D game development library for the Ruby and C++ programming languages, available for Mac OS X, Windows and Linux.

  1. require 'rubygems'
  2. require 'gosu'
  3. class MyWindow < Gosu::Window
  4. def initialize
  5. super(640, 480, false, 20)
  6. self.caption = 'Hello World!'
  7. end
  8. end
  9. w = MyWindow.new
  10. w.show

I can’t wait to find the patience to do something cool with this.

# Siggy Stardust

If you’ve ever been frustrated by the lack of control that most mail clients give you over your signatures, then Siggy Stardust is for you. It’s basically an SMTP proxy, which simply adds signatures to the end of any mails you send according to rules that you set up. The rules are written in pure Ruby, and so you can do pretty much anything you want within them.

For example, here is my current rules file at Teh Office. If all the recipients of a mail are within 29degrees, then a personal signature is appended. If any of the recipients are external to the company, then the business signature gets added. My personal signature tries to include the song I’m listening to at the moment, either on my own computer, or on the company jukebox. It does this by querying either iTunes or last.fm.

  1. require 'rubygems'
  2. require 'rbosa'
  3. require 'scrobbler'
  4. rules do
  5. smtp_server( "localhost" )
  6. smtp_port( 10025 )
  7. track = nil
  8. track_string = nil
  9. begin
  10. # Try and get currently playing information from either iTunes or last.fm.
  11. itunes = OSA.app( "iTunes" )
  12. if itunes.player_state == OSA::ITunes::EPLS::PLAYING
  13. track = itunes.current_track
  14. else
  15. user = Scrobbler::User.new( "29degrees" )
  16. track = user.recent_tracks.first
  17. end
  18. rescue
  19. puts [ $!.class, $!.to_s, $!.backtrace ]
  20. end
  21. if track
  22. track_string = "\"%s\" by %s off \"%s\"" % [ track.name, track.artist, track.album ]
  23. personal_sig = <<-EOT
  24. --
  25. Now listening to : #{track_string}
  26. Siggy Stardust r78
  27. EOT
  28. else
  29. personal_sig = <<-EOT
  30. --
  31. ASCII a silly question, get a silly ANSI.
  32. Siggy Stardust r78
  33. EOT
  34. end
  35. business_sig = <<-EOT
  36. --
  37. Regards,
  38. Carl Drinkwater,
  39. Director.
  40. http://29degrees.co.uk - Bespoke Web Application Development
  41. +44 (0) 161 953 6669 - +44 (0) 776 043 1463
  42. 29degrees Ltd is registered in England and Wales under company
  43. number 05952987. VAT Reg Number GB897293655. Registered office
  44. St. George's House, 215/219 Chester Road, Manchester, M15 4JE.
  45. EOT
  46. if recipients.all_in_domain?( "29degrees.co.uk" )
  47. append_sig( personal_sig )
  48. else
  49. append_sig( business_sig )
  50. end
  51. end

(Does anyone else think heredocs are ugly?)

Siggy tries to be intelligent when adding signatures to multipart emails. For me, the best results have come by adding the signature to the end of the last text/plain part of the email, and so that’s what Siggy does. It doesn’t attempt to do anything with text/html emails, because it shouldn’t need to.

If you want to play, download Siggy Stardust here. Run it by doing something like :

  1. ruby ./server.rb rules.rb

You’ll need to re-configure your mail client’s SMTP setting to use localhost and port 1234. By default, Siggy will proxy through to port 25 on the local machine, but you can change that by using the smtp_server and smtp_port methods as in my rules file.

The only other real helper functions are demonstrated in the final lines of my rules file :

  1. if recipients.all_in_domain?( "29degrees.co.uk" )
  2. append_sig( personal_sig )
  3. else
  4. append_sig( business_sig )
  5. end

You will probably need to write more to do the things you want, you’ll need to do that in server.rb.

To use the ‘now playing’ functionality, you’ll need the appropriate Rubygems installed. The iTunes lookup uses RubyOSA, and is only available on OS X.

Lastly, the rules file is reloaded each time you send an email through Siggy, so you don’t need to restart the server if you edit your rules.

The two files comprising Siggy Stardust, rules.rb and server.rb, are placed in the public domain. However, note that the gzipped-tar archive you can download above comes packaged with TMail, and is licensed under the LGPL.

# Tired of typing long method names?

A bit of Friday fun. Golfr saves you all the hassle of having to type out full method names by letting you use as few characters as you need. Look at the examples to see how it can save you valuable keystrokes.

  1. module Golfr
  2. def method_missing( method, *args)
  3. endings = Regexp.new( /[!?=]?$/ )
  4. ending = method.to_s =~ endings ? $& : ""
  5. ( look_for = method.to_s )[ endings ] = ""
  6. if found_method = ( methods.sort.select{ |m| m =~ /^#{look_for}/ }.first ||
  7. methods.sort.select{ |m| m =~ /#{look_for}$/ }.last )
  8. found_method[ endings ] = ""
  9. STDERR.puts "Calling #{found_method}#{ending} for #{method}" if $DEBUG
  10. send ( found_method + ending ).to_sym, *args
  11. else
  12. raise NoMethodError, "#{method}"
  13. end
  14. end
  15. end
  16. class Object
  17. include Golfr
  18. end

Then have fun!

  1. require 'golfr'
  2. a = []
  3. $><"Hello\n" # Matches '<<'
  4. a.uns "Cheese" # Matches 'unshift'
  5. a.ft [ "Pickle" ] # Matches 'unshift'
  6. puts a.insp # Matches 'inspect'
  7. a.fl! # Matches 'flatten!'
  8. puts a.pect # Matches 'inspect'
  9. puts a.n? # Matches 'nil?'
  10. puts "carl".c # Matches 'capitalize'
  11. Thread.a = true # Matches 'abort_on_exception='

Set $DEBUG=1 if you want to see what methods are actually being called, and feel free to do what you want with the code. It’s all yours.

# Missing songs in iTunes

This week, I was moving my iTunes library off an external HDD to a network share and somehow managed to completely badger it up. All the songs were still showing in iTunes and they were all on disk in their original places, but something had happened to their location in the iTunes database and were showing with an exclamation, indicating iTunes couldn’t find them.

After fixing these by trying to play the songs and manually locating them on disk, I was still finding songs which weren’t indicated by iTunes as missing, but actually were. So, I quickly wrote the below script to list all the broken tracks in my library. Unfortunately, there doesn’t seem a way to set the location automatically.

So yeah, I don’t know if this will be useful to anyone else, but here is the code …

  1. require "rubygems"
  2. require "rbosa"
  3. library_playlist = OSA.app( "iTunes" ).sources.find{ |s| s.name == "Library" }.library_playlists.first
  4. # Songs which are broken have a location of 'nil', but still have the
  5. # rest of the information.
  6. library_playlist.file_tracks.reject{ |t| t.location }.each do |track|
  7. puts '"%s" by %s, off "%s"' % [ track.name, track.artist, track.album ]
  8. end

# Determining 64-bitness

On a 32-bit machine :

  1. -1.size
  2. => 4

On a 64-bit machine :

  1. -1.size
  2. => 8
  1. a = [ 1, 2, 3, 5, 6, 2, 3, 1, 4, 5, 4 ]
  2. puts a.inject( 0 ) { |c, i| c ^= i }

Find the unpaired number in an array. I can’t really think of a situation you’d need to do this, but it’s a really, really elegant solution and that’s why I’m posting it. It’s left to the reader to work out how it works. From.

# 40 random 8-character passwords

  1. 40.times{puts((0..7).map{rand(?{).chr=~/[^\W_]/?$&:redo}*"")}

All in 61 bytes. Can you make it any shorter?

# images in your terminal

Moo!

Here is a quick and dirty script to display images in your terminal (Which is something I want to do fairly often.) It works best in a terminal which supports 256 colours, but gives sort-of-OK results in 16-colour terminals. And despite what the name might imply, it works with pretty much any image type, not just jpegs.

In case anyone else finds it useful, here it is. You’ll want RMagick installed, and both of these files :

Simply run it giving an image as an argument to the script :

  1. ruby xtermpeg.rb FuryCow_120.jpg

(And here is FuryCow_120.jpg, should you want it.)

Or, if you want to display a large image :

  1. convert FuryCow_1200.jpg -scale 100x /dev/stdout | ruby xtermpeg.rb

(And here is FuryCow_1200.jpg, should you want it.)

The code is public domain, so you’re free to do whatever with it.

  1. def a(_=def a(_=def a(_=def a;"hacker!"end)"Ruby "+a;end)"another "+a;end)"Just "+a;end
  2. puts a

# pretty last.fm graphs

lastgraph, carldr-style

Have you seen Lastgraph or Lee Byron’s work? Like it? Upset you can’t see the source code and play with it? Well, this might be what you’re after.

Utilising the scrobbler gem, I’ve written some Ruby which does something similar, and here’s the code so you can play with it yourself.

Just change the username on line 100, and run it. The script will download your data from last.fm, and produce a nice .svg for you (Warning: quite large.) To be friendly to last.fm, it caches the data on disk, so subsequent runs are generated a little quicker than your first run.

If you want to hack around with it, then I warn you that the second half of the source code is nasty, but subsequent versions will be tidier. It should be fairly easy to work out and modify. The code is released into the public domain, do as you please with it.

I’m sure some of the calculations in the code are inadvertently tailored to accounts with a similar amount of data as mine, so I’d be interested to hear if anyone does have any success with it. Email me via the link at the bottom of the page.

# rake tutorial

A very good Rake tutorial. Rake really isn’t complicated, and this tutorial covers pretty much everything you need to know in a very readable way.

# scrobble

  1. ruby -rrubygems -e 'require "scrobbler"; puts Scrobbler::User.new( "carldr" ).recent_tracks.map{ |t| "\"" + t.name + "\" by " + t.artist }'

For last.fm. The gem can be found here.