Installing _why's Bloopsaphone on OS X

Posted on 13 Feb 2010

Inspired by a recent rush of nostalgia, I finally got around to playing with _why's Bloopsaphone recently. Give or take the odd crash, it works pretty well with whichever version of PortAudio MacPorts gave me.

sudo port install portaudio
sudo gem install bloopsaphone -- --with-opt-lib=/opt/local/lib --with-opt-include=/opt/local/include

There are a couple of Bloopsaphone tunes by freQvibez which are worth looking at if you want to hear the kind of thing you can create with this.

Far Future Expires Headers for CSS Images in Rails

Posted on 28 Sep 2009

Setting far future expires headers for your static assets noticeably improves the speed at which pages load and is easy to setup in Rails thanks to asset timestamps. All you need to do is:

  1. Use image_tag, stylesheet_link_tag, javascript_include_tag and friends in your views.
  2. Update your web server config to set the correct headers.

One problem that's not immediately obvious here is that while your web server is happily adding expires headers to the images you're using in CSS, those requests don't have the timestamp in the query string so the browser will continue to use the cached version after you have updated the file.

One solution is to instruct the web server to only add the expires header to requests that do include the asset timestamp. While this might be ok if you only have a few images in your CSS, if most of your images are specified this way then you're still not making the most of the browser's cache which was the whole point of the exercise in the first place.

An alternative solution is to use ERB templates to generate your stylesheets, and use the Rails' helpers to get asset timestamps in your CSS. It's dead easy, here's how:

Create a Stylesheets Controller and a Matching Route

class StylesheetsController < ApplicationController
  caches_page :application, :iphone
end
map.connect "/stylesheets/:action.css", :controller => "stylesheets", :format => "css"

This is just about as simple as you can imagine. We're using page caching to cache the stylesheet to disk, once rendered it will be served like any other static asset.

Move Stylesheets to the Views Directory

mv public/stylesheets/application.css app/views/stylesheets/application.css.erb
mv public/stylesheets/iphone.css app/views/stylesheets/iphone.css.erb

Use the image_path Helper

Wherever you reference an image in your stylesheet, use the image_path helper like so:

body { background: url(<%= image_path('fade.png') %>); }

When the template renders this will output something like:

body { background: url(/images/fade.png?1253089219); }

And that's all there is to it. After each deploy the cached stylesheet will disappear and the next time it's requested it will be regenerated with new timestamps, which in turn will cause the browser to fetch fresh copies of your images.

A Note on Asset Hosts

We're also using an asset host, for a couple of reasons:

  1. A separate host for static assets can itself improve page load speed.
  2. We can specify far-future headers on anything served from the asset host, safe in the knowledge that the URL will have been generated using the Rails helpers and will therefore include the timestamp in the query string.

This causes one additional complication with the approach described earlier however. Our asset host doesn't run Rails since it only serves static assets, but the first request for the stylesheet needs to go through Rails so the template can be rendered and written to disk.

Assuming you're using Capistrano, a simple solution is to add a task that fetches the stylesheets from the Rails host after each deploy. Adding this to deploy.rb will do the trick:

task :prime_cache, :roles => :app do
  run <<-CMD
    wget --spider http://#{domain}/stylesheets/application.css;
    wget --spider http://#{domain}/stylesheets/iphone.css
  CMD
end

after "deploy", :prime_cache
after "deploy:migrations", :prime_cache

Another Take on jQuery, Rails and respond_to

Posted on 08 May 2009

I been using jQuery to do AJAX with Rails a lot recently, and I love it. When I was starting out however, I hit the same problem that seems to trip up everyone: AJAX requests made from jQuery don't trigger format.js (or wants.js if you're cool) within the respond_to block of Rails controller actions.

The most common solution I've seen to this problem involves adding a one-liner to your Javascript to instruct jQuery to add a text/javascript Accept header to AJAX requests. Which works great in FireFox, but not in Safari.

The problem seems to be that in Safari, text/javascript is appended to the existing Accept header, so Rails sees something like text/html, */*, text/javascript which it still interprets as a request for HTML.

An alternate solution that I've been using is to add the following to environment.rb.

config.action_controller.use_accept_header = false

This instructs Rails to use the X-Requested-With rather than the Accept header to determine the request format. Since jQuery sets this header in both browsers, Rails controllers will behave as expected.

One thing to keep in mind is that if your app has an XML or JSON API, you might need to think carefully about whether this is the best way to fix this problem. For a while this became the default in Rails, although that didn't last very long.

Installing Passenger 2.1.1 Beta

Posted on 07 Mar 2009

Update: Passenger 2.1.2 (final) has now been released.

The current stable release of Passenger (2.0.6) isn't compatible with Rails 2.3 because of recent changes in Rack. In the app I'm working on, this manifested itself as cookies not been set correctly, making it impossible to log out of the site. The good news is that the latest beta of Passenger includes support for Rails 2.3, you can install it (on OS X) as follows:

curl -O http://phusion-passenger.googlecode.com/files/passenger-2.1.1.gem
sudo gem install passenger-2.1.1
sudo passenger-install-apache2-module

Follow the on-screen instructions on updating your config, restart Apache and you're done.

Rails I18n Translation Lookup in TextMate

Posted on 17 Dec 2008

I've been working on internationalizing a Rails app, and along the way I created a simple command to lookup Rails i18n translation keys from within TextMate. You use it like this:

  1. Highlight a translation key. e.g. 'activerecord.errors.messages.inclusion'
  2. Hit Shift-Command-i.
  3. The relevant translation is shown on a tool tip, in this case "is not included in the list".

As well as simple keys, the command also works with any additional parameters you'd pass to I18n.t when using interpolation or the alternate translation key scoping syntax. For example highlighting :greater_than, :scope => [:activerecord, :errors, :messages], :count => 100 before invoking the command would yield "must be greater than 100" on the tool tip. There's also support for replacing local and instance variables used for interpolation with placeholder strings.

Since Sven Fuchs has already started an experimental Rails i18n TextMate bundle I've forked his rails-i18n repository and added this to it. Here's how to set it up:

The command is included in Sven Fuchs' experimental Rails i18n TextMate bundle, here's how to set it up:

git clone git://github.com/svenfuchs/rails-i18n.git
cp -r rails-i18n/tools/ ~/Library/Application\ Support/TextMate/Bundles/
# You also need the i18n gem
sudo gem install mattetti-i18n --source http://gems.github.com

The command has the default locale set to :en and is only loading translations from config/locales/en.yml. If you need to do something different take a look at the command in TextMate's Bundle Editor and you'll see what you need to change to get things working for you.