I decided to learn Ruby and Rails — now I need to get books on both (damn that DHH and his contagious enthusiasm)
Below are some snippets from my first Ruby program: convert.rb. It is a CGI program, that converts PostScript, TeX, CWEB and a couple of other formats to PDF. It also converts .tar.gz, .tar.bz2 and other compressed files to .zip.
[Note: I wrote this program flipping back and forth between the PixAxe1 and a bunch of other online resources — so forgive me if it isn't in the spirit of Ruby.]
Ruby blocks are cool!!!
def ignore_errors &block begin block.call rescue Exception => e e end end def with_tmpdir &block result = nil original = Dir.pwd tmp = tmpname # creates a temporary name (not safe) begin Dir.mkdir tmp Dir.chdir tmp result = block.call original ensure Dir.chdir original end FileUtils.rm_rf tmp result endand it is quiet easy to create DSLs:
# converters operate like so: # 3 args: first, a symbol naming the converter; # second, a regexp that if matched the third arg # is executed: which is a block that takes one # argument -- a local filename # the converter should return true or nil: # true to continue and try other converters; # nil to return -- as this is the final one. defconverter(:ps, /\.ps$/) { | x | sh "ps2pdf #{x}" nil } defconverter(:cweb, /\.w$/) { | x | sh "cweave #{x} - #{x}.tex" sh "tex #{x}.tex" sh "dvips #{x}.dvi" sh "ps2pdf #{x}.ps" nil }Finally, CGI.rb's HTML output facility make the code elegant (I wish that, optionally, you could output to a stream...)
cgi.out { cgi.html("PRETTY" => " ") { cgi.head { cgi.title { 'convert.rb' } } + cgi.body { cgi.h3 { 'convert.rb — convert file to PDF or ZIP' } + cgi.form('get', $0) { cgi.b { 'url:' } + cgi.text_field('url', '', 150) + ' ' + cgi.submit + cgi.br + cgi.checkbox('zipitup') + ' zip it up? ' + cgi.small { '[with this turned on, you can convert unix archive formats (like .tar.gz, .tar.bz2, ...) to .zip format]' } ... ... ... [snipped]Here are some initial thoughts:
- I was surprised at how easily and quickly I was able to develop the program
- calling methods (those that don't take args and those that take a single arg) without parenthesis is quiet refreshing:
(Before this, looking at Ruby from the "outside", this convention was disturbing — "How do I pass a function to another function" — but I didn't encounter that problem with this program because it seems to me that you pass in closures (blocks) to other functions...)
compare method.to_a.to_s to method.to_a().to_s()
sh "rpm2cpio #{x} | cpio -dimv --no-absolute-filenames" - love the short, nicely named methods: FileUtils.rm_rf tmp
- ability to specify integer as 100_000_000 is nice