Tuesday, July 3, 2012

Notification from long-running tasks

Yesterday I thought of a technique which has become a real time-saver for me. (I'm sure I'm not the first person to think of this; I remember reading something similar in Time Management for System Administrators.)

You can get notification from any long-running task on the command line like this:

do_my_task && make_a_sound

For example, using Rake on a Mac:

rake db:reseed && say 'done'

Now I can kick of the database to be rebuilt and move to another window, knowing that I'll get audible notification when that task is complete.

Monday, June 18, 2012

Hubbub

I like to imagine that somewhere in Silicon Valley, there is a sandwich shop which caters to nerds. They send out special deals via RSS feed. Naturally, they call this the PubsubHubbub Sub Club.

Based on the special they're running, they keep extra ingredients handy to satisfy demand. Each morning, they must fill the PubsubHubbub Sub Club Grub Tub.

At the end of the day, they clean it out and wash it thoroughly. They do this, of course, using the PubsubHubbub Sub Club Grub Tub Scrub Nub.

Thursday, May 24, 2012

Programming music: Afriki Djigui Theatri

I've been meaning to write a post about music I like to listen to while programming. My main criteria is that it doesn't have words I can understand, because that triggers the language part of my brain, which makes it impossible for me to decide what to call my variable.

A full post will have to wait, but the moment, I'm really enjoying a radio station full of African music. I found it in iTunes: Radio -> International/World > Afriki Djigui Theatri. They also have a website: http://www.djigui.org/

It's beautiful, most of it has a nice beat, and I can't understand a word.

Sunday, April 29, 2012

New gem: Authority

I recently released a new Ruby gem for authorization in Rails apps. It's called Authority.

You can find the code and extensive documentation on Github; the gem is hosted on RubyGems.

I also wrote a blog post on RubySource explaining the ideas behind the gem.

Check it out!

Wednesday, February 1, 2012

The beauty of xargs

Every time we deploy our Rails application, our deployment tool creates a new folder based on the date and time, puts the right files in it, and when everything is ready to go, updates a symlink to point to the newest release.

Yesterday I found that I couldn't deploy because we were out of disk space. I needed to delete some of the old release folders.

When I sshed into the server and looked in the releases folder, it had a ton of folders named like this:
20120126191222
20120126193901
20120127153732
20120127171244
20120127204235
20120127204517
20120130172837
20120131152908
20120131160422
Here you see some from 2012, but they went back all the way to 2010. I wanted to delete everything older than 2012.

Enter the magic of xargs. It lets you take the output of one command and input each line of it as an argument to another command.

Here's what I did:
ls # shows me all the folders
ls | grep ^201[01] # shows only the ones starting with 2010 or 2011
ls | grep ^201[01] | xargs rm -rf # delete all those
Building up the command bit-by-bit lets me verify that I'm going to delete the right things. And xargs knocks it out.

Here's another useful example. Vim creates a temporary .swp files that sometimes don't get cleaned up. To find and delete them all out of a folder:
find . -name '*.swp' | xargs rm

Thursday, December 22, 2011

Faster feedback

In programming, the faster you get feedback from your code, the more productive you can be.

For example, suppose you're going to use the Javascript Date class in a web page to do some time calculations. Do you:
  • Write some code, save the file, reload the page, look at the results, and repeat?
  • Open a Javascript console (like Chome Developer Tools or Firebug) and experiment?
The second method gives you instant feedback. This means you can find the right approach more quickly and not lose focus in the meantime. The same is true when coding Ruby: if you want to see what Array#select does, irb will give you much faster feedback than a Rails app.

Other ways you can get feedback faster include:
  • To learn more about Git, create a temporary folder and a dummy project: mkdir ~/test; cd ~/test; git init; echo 'hello' > test.txt; git add .; git commit -m"first"; Now you can experiment: branch and merge, rebase, and whatever else you want to try without fear of screwing up a real project. When you're satisfied, just delete that folder.
  • If you're thinking of adding a command to one of your runtime configuration files, like .bashrc or .vimrc, run the command directly first and see what it does.
  • Take the time to make your automated tests run faster: you'll be more likely to run them often and less likely to lose focus when you do.

Friday, August 26, 2011

Testing a Rails 3.1 Engine's Javascript with Jasmine

At work, we've got a Rails engine that provides some complex drop-in forms to various applications. The forms have associated Javascript which, on Rails 3.0, we had to copy and paste between applications. That's both annoying and fragile, since things can get out of sync.

To test our engine, we had created a dummy app with the Enginex gem, located in spec/dummy.

In upgrading the engine to 3.1 (currently on release candidate 6), we wanted to move the associated JS into the engine, so that they would be versioned together in a single gem.

That wasn't so hard, but we also needed our associated Jasmine tests to run. For that, we needed to precompile our Javascript before rake jasmine ran so that Jasmine could load and test it.

Precompile Problems


And that's where things got sticky. According to Ryan Biggs' documentation, the default matcher for precompiling files is:

[ /\w+\.(?!js|css).+/, /application.(css|js)$/ ]

Basically, besides application.js and application.css, any js (or css) files with multiple dots in it, whether it's foo.js.coffee or jquery.cookie.js, will get compiled to its own file.

We had two problems with that:

  • It didn't match our engine's manifest file, because it's not named application.js. (It's not named that because in the host application, we will already have an application.js and we don't want a conflict.)
  • It did match a bunch of other JS files which didn't need to be compiled separately. For example, the manifest requires jquery.cookie.js, so that file gets compiled and added into the manifest file. It doesn't need to also be compiled as jquery-aaff723a97d782d30e3fc2f0dee5d849.cookie.js; we don't plan to serve it separately.

To solve the first problem, in Engine.rb, we added:

initializer "myEngine.asset_pipeline" do |app|
  app.config.assets.precompile << 'myEngine-manifest.js'
end

To solve the second problem, we... did nothing. We don't care. We're letting it create extra compiled files that we don't need.

We could have changed the match regex to only match files with endings like in .js.something or .css.something, instead of the broad rule that will also match .min.js. But doing that in an engine might have broken a host application if it were compiling something we didn't foresee. Maybe at some point a host app will want to compile .csv.erb files or something; we don't want to preclude that.

So we chose "be unobtrusive to the host app" over "prevent unnecessary compilation".

(We also could have prevented jquery.cookie.js from being compiled separately by renaming it to jquery-cookie.js, but we think that's annoying.)

Jasmine Setup


Now that our myEngine-manifest.js was being compiled to myEngine-manifest-20309309d9309330309390.js, we needed to let Jasmine know to load that single file, containing all our compiled Javascript, rather than all the separate files it had to load previously. So, in jasmine.yml, we now have:

src_files:
  - spec/dummy/public/assets/myEngine-manifest-*.js

The * will match whatever hash fingerprint is added to the filename.

Now, before we can run rake jasmine, we needed to make sure everything was compiled appropriately. So we created this simple Rake task in the engine's Rakefile:

task :precompile_jasmine => ['assets:clean', 'assets:precompile', 'jasmine']

Engine Rake tasks don't necessarily need access to Rails tasks, so to get the task above to work, we had to put the following above it so that we'd have access to those asset-related Rails tasks:

load File.expand_path('../spec/dummy/Rakefile', FILE)


Turning on Sprockets


To get Sprockets working in our dummy application, we had to make two changes to spec/dummy/config/application.rb:

  • Below the other railties requirements, add require sprockets/railtie
  • Within the app settings block, add config.assets.enabled = true

You may not need to do this; it's a side-effect of the fact that we generated our engine with a version of the Enginex gem that preceded Rails 3.1.

Other setup


  • To get Jasmine working with Rails 3.1, make sure you've got a new enough version. Jasmine 1.0.2.1 worked for us.
  • You don't want to check in all your compiled assets, so be sure to add this to your .gitignore: spec/dummy/public/assets/*

Weirdness


Something weird about assets:precompile makes it, and any task that runs after it, run twice. This means that `rake jasmine` requires two interrupts to shut down properly in our current setup. (In a previous attempt, it tried to run again while it was running, and got an error because it couldn't re-bind to the same port.)

Addendum


There's no way I could have figured this out by myself, and I'm not sure that I'll be able to answer questions about it. Adam Hunter and I worked on it together, and he contributed more brainpower than I did. But after all the blind alleys and frustration, I was determined to write up what we did, and got Adam's help doing so. So: good luck replicating this. :)

Also, if you're looking to use Jasmine in a Rails 3.1 app with coffeescript, this blog post from Pivotal Labs may be more helpful. We got some ideas from it, too.