Sometimes it takes quite an effort to be a “lazy programmer” (as in Larry Wall’s virtues of a programmer). I’ve been trying to optimize my workflow as I run into things that make for repetitive typing. I find when I can type less, I have more cycles to think. One of my favorite tools in laziness is bash scripting, but I’m still learning its ins and outs.

The problem: Lately I’ve been switching between subversion trees in OpenLaszlo. (Someday I want to convince the team to switch to git, but I’m not sure that would even solve the problem completely, since I also like having multiple webapps installed.) So I’ve got trunk checked out in different directories: a clean one for testing, one I keep for code reviews, a sandbox for whatever I’m working on at the moment, etc. Every time I switch OpenLaszlo contexts, I need to redefine $LPS_HOME environment variable and cd into that directory. Should be simple, huh?

[ -n "$1" ] && BRANCH="$BRANCH-$1"


export LPS_HOME=/Users/sarah/src/svn/openlaszlo/$BRANCH
cd "/Users/sarah/src/svn/openlaszlo/$BRANCH"

Except this didn’t work. It seemed that ‘cd’ had no effect and $LPS_HOME wasn’t modified. WTF? Lacking someone to look over my shoulder in my new solo work situation, I emailed my friend Scott Evans from whom I have learned much bash lore. He emailed me the following:

1) use “.” to run the script, which runs it in your shell process instead
of in a child one.

2) use a bash function instead — these run in your current environment.
try something like this in your bashrc/bash_profile:

trunk() {
 echo "dollar 1: ${1}"
 if [ -n "${1}" ] ; then
   export LPS_HOME=/Users/sarah/src/svn/openlaszlo/trunk-${1}
   export LPS_HOME=/Users/sarah/src/svn/openlaszlo/trunk


Note that I didn’t set something like $TRUNK there — since the thing is running in your shell environment, it’s good practice not to potentially step on existing variables, or leave any variables defined after the fact.

Thanks Scott! Posting here so that I will always remember what I learned today and maybe some other folk will find it helpful.

I anticipate enjoying git submodules for all of the various and sundry dependencies for my project. However there is a bit of a gotcha with my specific use case. It’s seems I’m not alone, but I thought I’d write this up for others who may into the same thing (and for my own future reference).

The issue happens when you have a directory that is checked into git and you decide to delete the directory of checked in files and add a submodule instead. Seems like a common use case to me, but perhaps the creators of git submodules didn’t thinks so. This happened to me in the move from subversion to git. Initially, all of the plugins were accessed as svn externals; however they were not available via git and I wanted to do one migration at a time, so I just checked the source of all of them into vender/plugins. Later, I dug up references to various git repositories where the plugins are now available, and created subrepositories — awesome, right?

The gotcha comes when I switch branches back and forth between the “master” (no submodules, but with checked in source) and “dev” (where my submodule work is). Here’s what happens:

$ git checkout master
error: Untracked working tree file 'vendor/plugins/acts_as_list/lib/active_record/acts/list.rb' would be overwritten by merge.

Here’s my workaround…
To go back to a branch w/o submodules

$ rm -rf vendor/plugins
$ git checkout master
$ git checkout vendor/plugins

To go back to a branch w/ submodules

git checkout dev
git submodule update --init

Update: another gotcha, when I tried to merge dev into master I got “fatal: cannot read object… It is a submodule!” found the answer here and it worked for me:

git merge -s  resolve

For the record, I’m working with git version 1.6.1

I just went through a fabulous tutorial by Daryn Holmes about routes. It is written for 2.0.2, but I found that nothing had changed for 2.2. I already had a good feel for how routes worked, but stepping through the details was very helpful.

Key points:

  • By default controllers render the view that has the same name of the action invoked.
  • index is the default action

Debugging Tips:
You can quickly see where a route ends up by typing this into irb:

>> rts = ActionController::Routing::Routes
>> rts.recognize_path("/")
=> {:controller=>"albums", :action=>"index"}

You can also go in the reverse direction to see what URL would be generated by a route. To see what URL an action will end up at:

>> rts.generate(:controller=>'albums',:action=>'index')
=> "/music"