Wednesday, May 30, 2012

Friday, May 25, 2012

Ruby one-liner: rename files

I wanted to strip a 20-character prefix, starting with the characters "IP_", from from a dozen XML files in a directory. Each file has a value of a different length following the prefix, e.g. "IP_stuff_foo.xml", "IP_stuff_bargain.xml", etc. I could probably do this by hand, or with a Windows batch file, but seeing as I'm learning Ruby (again), I thought I'd try to get it down as a Ruby one-liner, and here it is:

ruby -e 'Dir.glob("IP*.xml").each { |f| File.rename(f,f[24..-1]) }'
  • ruby -e calls Ruby to -"e"xecute the code in single quotes
  • Dir.glob("IP*").each finds all files in the current working directory that start with the string "IP". The glob() method returns an Array object, e.g. ["IP_foo.xml", "IP_bargain.xml", etc.], so the Array each() method returns "each" element in turn.
  • Each file name is passed in turn into the variable f in the block { ... }, where the File.rename() method does its magic.
  • File.rename takes two parameters, the name of the file to be renamed, and the new name for the file.
  • The new file name is a substring of the characters following the 20 character prefix. The substring is created by returning the remainder of the string after counting backwards, "-1", for "20" characters, f[20..-1].
  • Once File.rename() gets the substringed value, it renames the file.

Monday, May 21, 2012

tmux for Ruby on Rails

A couple of weeks ago I stumbled on tmux as a way to manage the proliferation of terminal windows when doing Ruby on Rails development.

My Rails 3.2 development environment is a Ubuntu guest OS running on a VirtualBox VM hosted on my Windows 7 desktop. Since I wanted to stay on my Windows desktop most of the time, rather than interact with Ubuntu through the somewhat laggy Virtualbox display, I would ssh into the Ubuntu guest using a Cygwin terminal (mintty). And being a good ol' Rails fanboy, I started using Vim and all its plugins as a really nice Rails/Ruby editor.

However: once I got a couple of Vim editors, a rails server, a rails console, a log file tail, and a Guard or RSpec session all running at once, plus the Ruby on Rails tutorial and Rails app open in browser windows, my Windows desktop started to look like Mah Jongg game in full swing. I was spending more time tabbing around looking for the right window than actually learning anything!

Tmux brings some order to that chaos. According to the tmux man page, "tmux is a terminal multiplexer: it enables a number of terminals to be created, accessed, and controlled from a single screen." After some tweaking and fiddling, this is the layout I've settled on:

I've split a single "window" named "rails" into to three "panes": top-left I have Guard running Rspec tests, bottom-left I have the Rails server, and at right my main Vim editing session. On a second window named "logs" I have a tail on the Rails server log file.

The cool thing about this is that it all starts up automatically when I run a shell script that instructs tmux to set up the windows and start all of the processes I need for my Rails development session. Tmux will even maintain the session in case my terminal connection dies.

I relied on these excellent introductions to TMUX to get started:
Here's the shell script I cobbled together to create that session:

And my .tmux.conf file:

Thursday, May 17, 2012

Wikipedia on my iPad Sucks!

I love Wikipedia.

What's not to love about the universal reference, all 3,952,630 pages kept up-to-date by an 85,000-strong army of contributors, who do it all for love, that's available online, from anywhere, including my iPad, even offline, thanks to the All of Wiki app that lets me carry the whole 4.73 Gbytes of it around with me whereever I go, so that if I, as an ignoramus Canuck, riding to work on the bus without a handy WiFi connection, get the hankering to know just who played Zaphod Beeblebrox in the original BBC radio broadcast of the Hitchhiker's Guide to the Galaxy, well, heck, I can just pop open All of Wiki and discover it was the aptly-named Mark Wing-Davey, who also played Zaphod in the TV series... in fact, with the addition of perhaps a towel, I would be perfectly equipped to face the Vogons with my Wikipedia-enabled iPad.

Besides, I don't think Vogon ships are equipped with 802.11n WiFi, so that's perfect.

The iPad is pretty much how I envisioned the Hitchhiker's Guide when I first read Douglas Adam's opus many years ago. So if I love Wikipedia so much, why do I say it sucks? Here's what the desktop version looks like on my iPad:

I don't know about you, but i find it hard to read 6-point type on an iPad. Granted it's a now-ancient iPad Mark I, but i don't think the whiz-bang Retina display would make much difference, it's still tiny type.

Let's try the two finger splits and zoom in:

Terrific, the type's bigger now, but it didn't reflow to fit the screen. Okay, you say, switch to the mobile version:

Big improvement, now I see tiny type one block at a time, and it still doesn't reflow when I zoom in.

C'mon, Wiki guys 'n gals, this is the Age of Mobile, I know you've heard about responsive web design (it's right here). Let a thousand screens bloom! You've recorded all that's vital to human knowledge, surely you can make it comfortable to read on my iPad, and Nokia N8, as well as my desktop?

Keep up the great work, though, we do love ya.

Wednesday, May 16, 2012

Lather. Rant. Repent. Love it!

Eric Lloyd (where are you?) summed up the link between code cruft and developer turnover in his comment on the thread Is 4-5 years the “Midlife Crisis” for a programming career? - Programmers

"Lather. Rant. Repent."

How many organizations get this? How many can see past the sunk cost of ancient code and infrastructure to realize when it's time to update?

'via Blog this'

Monday, May 14, 2012

Windows batch: echo without new line

Two ways to use set with /p to 'echo' without a new line:

echo|set /p=.

<nul set /p=.

Both examples rely on the set command's behaviour when given the '/p' switch. The '/p' switch turns 'set' into a prompt for input. Usually, this would be employed to solicit interactive input from the user. The value entered at the prompt can be stored in a variable, e.g. 'set /p armageddon=Push Big Red Button?', where the variable 'armageddon' is set to the user's response to the prompt question.

The first example works by having 'set /p=.' output the '.', then get a response from the output of  an empty 'echo' statement piped into the command. The response from echo is discarded, because there is no variable defined for the '=' in the 'set' statement. The second example works by redirecting the 'nul' device into the 'set' statement.

Each time the statement is executed, another dot is output on the same line. This technique could be used to make a progress bar in a batch file, e.g. each time through a 'for /f' loop.

The statement could also be wrapped in an if-else block to flag errors, e.g.

if %foo% equ 1 (
    <nul set /p=.
) else (
    <nul set /p=F

The output is a series of dots for success, with F's marking failures:

Big thanks to arnep for this elegant solution.

'via Blog this'

Wednesday, May 9, 2012

Ruby 1.9.2 load path update

I encountered an odd error when I changed the "load" statement to "require" in section 1.3.3 on page 19 of David Black's book The Well Grounded Rubyist.

As of Ruby 1.9.2, the current directory, ".", was removed from the load path for security reasons. The load path is stored in the global variable "$:", which you can display by running the command 'ruby -e puts $:'

The effect of this change means the step on page 19, changing load "loadee.rb" to require "load" will fail with an error:

'require': cannot load such file -- loadee (LoadError)

The solution is to either add the current directory, './loadee', or use require_relative 'loadee'. I hope this helps anyone else who puzzled over that error.

Thursday, May 3, 2012

DRY is for software, not for humans

Right now I'm stepping through a manual testing procedure provided as a PDF document, using Acrobat Standard to make comments (It's the process, don't ask why).

The fun part is stamping each step with the big green checkmark or the big red "X" as I complete each step.

I'm on step 368. In the interest of saving a few keystrokes/bytes/pages, Step 368 tells me to "Repeat steps 132 through 138." Step 368 also tells me what values to use for this section instead of the values that were used in steps 132 through 138.

Great, I have to split the screen (took a while to find that command, why can't I just double-click a toggle on the pane containing the page?), then scroll the top half back to find step 138, then mentally substitute the new values for the old ones, while eyeballing the HMI to make sure I'm clicking the right buttons and fields.

This is DRY for humans. I think Don't Repeat Yourself is great for software. Who wants to chase around through sixteen different configuration files or print statements to change a value? But humans benefit from repetition, especially in a tedious list of test steps.

Yes, we use automated testing on the application level. This is more functional testing - do the right values show in the right fields (are the fields even there to begin with?), can I click a button, does the right thing happen... stuff that's tricky to automate and stuff that automation might not catch. When I have to stop the flow, scroll up through screen after screen of identical-looking steps, find the old steps, substitute the new values, make sure I don't lose my place, well, it's no wonder I go off and rant about it.

Now the troubling thing is, the test procedure document was generated by an application that sucks in XML data files that spell out the content of each step, then spits out the PDF all nicely formatted and tabulated.

For the sake of exercising a few more CPU cycles, the scripts could include the repeated steps from a template, substituting in the new values, thus saving my limited brain cycles for understanding why the HMI doesn't match up to the values in the steps. Or something more important.