Rails (3?): Skip Test

In updating an existing Rails app to run under Rails 3 (beta 4), I realized you could indicate that a certain test case should be skipped.  Literally, just add “skip” inside of the test (I added it to the top of one of mine as it was actually a work in progress) followed by an optional message.  For example:

test "should take the warp core offline" do
  skip
  warp_core.dismount
end

Very useful.

How did I get here?

Sometimes it’s useful to know the stack trace at a certain point in your Ruby code without using the debugger (or throwing an exception). Here’s one way to do it:

puts Kernel.caller.join("\n")

Ruby tip: while becomes any?

In implementing a new feature in a Rails project, I found myself needing to iterate through an array of patterns looking for a match against a particular string.  In a C-based language or Java, you would probably do something like this:

class LoopDemo
{
  public static void main(String[] args)
  {
    String matchMe = "diamonds";
    String suits[] = {"spades", "clubs", "diamonds", "hearts"};

    boolean found = false;
    int suitIndex = 0;
    while ((!found) && (suitIndex < suits.length))
    {
      found = matchMe.equals(suits[suitIndex++]);
    }

    System.out.println(found ? "Match found" : "Match not found");
  }
}

Ruby, of course, provides a much more compact way of accomplishing exactly the same thing:

match_me = "diamonds"
suits = ["spades", "clubs", "diamonds", "hearts"]

found = suits.any? {|suit| suit == match_me}

puts found ? "Match found" : "Match not found"

Yes, any? stops when it reaches the first returned true value.

The example is contrived — of course, there are easier ways with Ruby to find out if an array contains a particular string. But imagine that your criteria for “finding” or “matching” something is more complex. You can use this approach with an arbitrary amount of complexity in the block being passed into any? as long as the return value from the block evaluates to true or false.

When upgrading to Rails 3…

Be sure you delete config/initializers/new_rails_defaults.rb. It is no longer necessary (per its own comments) and in fact causes a weird exception if you don’t remove it:

/Users/mharper/Development/Rails/mileage/config/initializers/new_rails_defaults.rb:14: undefined method `generate_best_match=' for ActionDispatch::Routing:Module (NoMethodError)

Sending email when a file changes in git

I am collaborating on a project right now where multiple developers may be making changes to a single Xcode project. Since in my experience, Xcode project files “don’t merge well,” we have setup git so it treats the Xcode project file (project.pbxproj) as if it were a binary. Consequently, it sucks to have too many outstanding changes to the Xcode project file that have to be merged back in manually. To help shorten the amount of time someone might be working on an out of date Xcode project file, I setup a post-commit hook on the git repository that sends email to the developers in case this particular file changes.

Procedure:

  1. Add the following “hooks” section to the config file for the target git repository, of course updating the email(s) as appropriate:
    [hooks]
    	mailinglist = you@example.com someoneelse@example.com

     

  2. In the “hooks” directory in your repository, you should find a file named “post-commit.”  Add the following to the file:
    git show --pretty="format:" --name-only HEAD | grep project.pbxproj
    if [ $? -eq 0 ]; then
    	mail $(git config hooks.mailinglist) -s "Xcode project changed" <<-EOF
    Please pull the latest Xcode project.
    EOF
    fi

     

  3. Make the post-commit file executable if you have not done so already.
    chmod +x post-commit

     

That’s it! Piece o’ cake, huh?  Anyway, even if my logic regarding the “mergability” (or lack thereof) of an Xcode project is flawed, the principle behind email notification on a single file is still valid.  I’m sure generalizing this to notify upon changes to a list of files is easy enough.

CruiseControl.rb+git (+xcodebuild!) on Mac OS X

With some encouragement from my colleagues, I expanded the original post here to be a more soup-to-nuts recipe for setting up CC.rb with git and xcodebuild on Mac OS X. Thanks, guys!

I am currently working on a cross-platform project which has multiple targets that need to build on Mac OS X. On my previous project, we were using CruiseControl.rb on linux to watch a Subversion repository for a Rails project and run all the associated tests upon checkin. Since we wanted to be like the Cool Kids on this new project, we of course decided to use git for source code management.  We use gitosis to manage multiple remote git repositories under a single user.  However, you can use any approach you want for the remote repository management as long as you can compose a git URL that points to it.

Assumptions:

  • You have a Mac that is probably not your development machine that will serve as a Continuous Integration (CI) server.
  • You have a remote git repository that the CI machine can monitor and pull changes from.

 
Procedure:
It took a little doing to make CC.rb play nice on Mac OS X.  In addition to the typical CC.rb installation, getting CC.rb to launch at system startup using launchd took the proper file in the proper location. Nevertheless, the whole setup is pretty darned straightforward.  Here’s how I did it:

  1. I created a user named “continuousintegration.”  You can name yours anything you like, or use an existing user.  Log in as this user.
     
  2. Download and install CruiseControl.rb.  I unpacked it into the the home directory of the continuousintegration user.  So, the absolute path to the CC.rb installation directory in my case is:  /Users/continuousintegration/cruisecontrol.rb.
     
  3. Create the work directory for CC.rb.  In my case, I use /var/cruise as the work directory.  This required admin privileges to create; just make sure that your CI user has access to this directory.
    sudo mkdir /var/cruise
    sudo chown continuousintegration /var/cruise

     

  4. Add your git repository to CC.rb.
    cd ~/cruisecontrol.rb
    ./cruise add <project name> --url <git repository url> -s git

     

  5. At the root level of your git repository, add a file named cruise_config.rb. This provides some useful configuration information so that CC.rb knows what to do in order to build your project as well as whom to notify when the build fails. You provide the build command for CC.rb in cruise_config.rb by assigning to project.build_command. I actually made my build command point to ./ci_build.sh so that I can do anything I want for the build in a separate shell script named ci_build.sh in the git repository root. In my case, I am actually running xcodebuild to build a target I created in my Xcode project; you can do literally anything you want here, e. g. make check, rake… whatever! Witness my cruise_config.rb and ci_build.sh files. (If you create a ci_build.sh or equivalent file, be sure you make it executable.) Make sure you git push your changes to add the cruise_config.rb (and ci_build.sh if you choose to do so).
     
  6. You should now be able to start up CC.rb and look at the dashboard to see your project.
    ./cruise start

    Browse to http://localhost:3333

  7. Wait! You’re not finished yet! There’s one more step: setting up CC.rb to start every time the system starts up. This is accomplished by creating a plist file in /Library/LaunchDaemons which starts up CC.rb. (For more information on what’s going on here, see the Apple documentation or man launchd.)
     
    Download this plist file and copy it into /Library/LaunchDaemons

    sudo cp localcruisecontrol.plist.txt /Library/LaunchDaemons/local.cruisecontrol.plist

     
    Now when you restart the CI machine, CC.rb should start up automatically.

 
Setting up CC.rb all by itself tends to be pretty easy; it’s getting the daemon to run at system startup as well as getting your build to work properly that tend to be the problems. If you’re having trouble getting things running after following these directions, or if you find errors in these directions, please let me know.

Setting ruby executable path in TextMate

I just recently received an update to TextMate.  However, I discovered that I could no longer Run Focused Unit Test as it would complain:

in `check_gem_dependencies': undefined method `ruby_version' for Gem:Module (NoMethodError)

I got a clue when I noticed in the RubyMate window that the patch level of the ruby interpreter was different from the patch level of the ruby I use from a Terminal window.  Clearly, TextMate was using a different Ruby executable than I was the rest of the time.

I poked around in the Ruby bundle a little bit and noticed references to a variable TM_RUBY.  Looking around some more, I discovered in the Preferences under Advanced there is a Shell Variables tab.  I added a TM_RUBY variable there and pointed it to the ruby I wanted it to use (/usr/local/bin/ruby in my case).  Restarted TextMate, et voilà — Run Focused Unit Test works perfectly again.

Rails Conf 2008

Today is my first day back at the office after Rails Conf 2008. I still have to do a lot of processing of the sights, sounds, moments, material, and individuals I encountered. Nevertheless, it seems to me that these sorts of conferences always give me plenty to think about, lots of new information, and a reinvigoration of sorts to seek out new life and new civilizations — at least in a work/technology sort of way.

The conference had numerous highlights for me this year. One cool aspect was that one of my esteemed colleagues from DC was able to make the trek to Portland. I am hopeful that he enjoyed the conference experience. Otherwise, here are some of my favorite sessions, speakers, and moments, in no particular order:

  • “Programming Ruby using a Java IDE? Aren’t you worried it’ll kinda ‘rub off?'” –Kent Beck (paraphrased)
  • Web design tutorial with Brian Hogan. Reminds me that I can handle a fair amount of graphic design if I just apply myself.
  • Joel Spolsky’s version of hooking up a digital camera to Microsoft® Windows® (fuckhead)
  • DHHism: going Bender
  • Rails Envy’s MVC commercials
  • 23 Hacks
  • Pastie lightning talk
  • Ruby metaprogramming presentation (despite technical difficulties)
  • The Starlight Parade
  • Hotel Monaco
  • Continued surfacing of bacon during many meals, including the surprisingly excellent bacon maple bars from Voodoo Doughnuts
  • Lunch at Saturday market (surprisingly absent of bacon)
  • Waking up Sunday morning to discover Rails 2.1 had shipped