Interesting excerpts from Programming Ruby
I read these while riding in the car back from Colmar. They’re courtesy of Programming Ruby: The Pragmatic Programmer’s Guide, which I now consider to be one of the most complete and interesting references on Ruby.
Because if itself is an expression, you can get really obscure with statements such as
if artist == "John Coltrane"
artist = "’Trane"
end unless use_nicknames == "no"This path leads to the gates of madness.
def once(*ids) # :nodoc:
for id in ids
module_eval < <-"end;"
alias_method :__#{id.to_i}__, :#{id.to_s}
private :__#{id.to_i}__
def #{id.to_s}(*args, &block)
(@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0]
end
end;
end
endThis code uses module_eval to execute a block of code in the context of the calling module (or, in this case, the calling class). The original method is renamed __nnn__, where the nnn part is the integer representation of the method name’s symbol ID. The code uses the same name for the caching instance variable. A method with the original name is then defined. If the caching instance variable has a value, that value is returned; otherwise the original method is called, and its return value cached and returned.
Understand this code, and you’ll be well on the way to true Ruby mastery.
Fancy new program: gst-music-hash
I wrote a new program to fix my problem with duplicate music files that’s somewhat handy; it uses GStreamer framework to decode a music or movie file, then uses the libfooid library to calculate a unique number based on the contents of a file. Why is this useful? Well, it means that if you converted half your library to M4A for example, you could find the old MP3 files and delete them off the disk. I’m going to write a Ruby script that’ll do just this in the next few days, but in the meantime here’s the program itself.
Source Code: gst_music_hash-0.1.tar.bz2
Debian / Ubuntu package: gst-music-hash_0.1-1_i386.deb
The program is pretty buggy like any other program I just throw together for my own use, it doesn’t handle errors very well. If you put it in a script, it returns 0 on success so you can use that to determine whether the output is a valid hash. Next, I’m going to try to optimize it using the liboil library, but unfortunately I can’t get oprofile to work on my machine so that’s definitely a thorn in my profiling side.
Ruby = Awesome, this shouldn’t be so easy
This piece of code downloads an RSS feed, drops all the items that match a regular expression, and returns the resulting XML document. And it’s 12 lines of code. Twelve.
require ‘uri’
require ‘rexml/document’
include REXML
url = URI.parse ‘http://blog.paulbetts.org/index.php/feed/’
xml_doc = Document.new Net::HTTP.get_response(url).body
to_delete = []
items = xml_doc.elements[1].elements[1].elements
items.each { |iter| to_delete << iter if /ctags/.match iter.to_s }
to_delete.each { |x| items.delete x }
xml_doc.to_s
I’ve been working on writing an example program (and something I want to use as well!) using everyone’s favorite popular framework, Ruby on Rails. I think that it’s definitely a time-saver, but it has a pretty steep learning curve. While Ruby is extremely flexible with classes, mixins and templates, it makes understanding a framework that uses this trickery like Rails somewhat difficult. The documentation isn’t very clear either, in the sense that there are tons of well-written tutorials, but not many give a high-level overview of the framework (the best I’ve seen is the official book, Agile Web Development with Rails . I think I’m starting to understand it though, and the framework makes adding new features to a site really easy.
ctags builder for really f’ing big source trees
After waiting a really long time, I found out that ctags doesn’t like generating tagfiles for 40gb code repositories, as well as the generated file being really huge and unwieldy. I had some free time over the weekend, so I wrote a Ruby script that creates tag files for large source trees and splits them apart by directory if there are too many source files in it. So basically, if it can form one big file it will, but if not, it’ll split it into several small files that are named after your subdirectory. Some examples:
generate_ctags.rb --outputdir ~/kernel_tags --filecount 5000 /usr/src/linux
produces:
acpi
arch
asm
asm-alpha
asm-arm
asm-arm26
asm-cris
asm-frv
…and so on
Download it at http://www.paulbetts.org/projects/generate_ctags.rb
PS: The code is pretty hacky but it’s usable right now; it has a bug where it says that it failed generating the file but don’t believe it. It also has another bug where if you don’t arrange the params in a specific format it doesn’t work. Maybe I’ll fix it sometime but right now I’m too lazy.
