While reading Yehuda Katz’ blog post concerning mental models about Ruby’s behavior, I was a bit rankled by his reference to implicit locals created by running regular expressions with match clauses.

I was nearly certain that the dollar-sign prefix on the variables ensured the variables were global, but had to verify for myself.

Surprisingly, I found that the matches truly were local.

class RegGlobalTester
  def hello
    [ $1, "hello".match(/h/), goodbye, $1 ]
  end
 
  def goodbye
    [ $1, "goodbye".match(/(g)/), $1 ]
  end
end

RegGlobalTester.new.hello
 => [nil, #<MatchData "h">, [nil, #<MatchData "g" 1:"g">, "g"], nil]

Previously, I demonstrated how to set up an encrypted store in Mac OS, but didn’t describe why you might want to do such a thing.

Encrypt

Using an encrypted store like this can help keep your company’s sensitive passwords safe should your computer be compromised.
We use Capistrano to deploy to production servers, and in our deploy.rb cap variables are read from environment variables, and then forwarded on to the production machines.

set :live_production_mysql_pass, ENV['PROD_MYSQL_PASS']

Now obviously, we don’t want these sensitive variables set all the time, only when it’s time to deploy. To achieve this, we simply execute a shell script, stored on the secure volume, which sets the appropriate variables.

Store Your Secrets

When the secure volume is mounted, a custom .bash_profile is loaded which bootstraps your original ~/.bash_profile and adds your secrets to the environment:

source ~/.bash_profile
export PROD_MYSQL_PASS='top-secret'
 
echo "Exported secure environment, please close this terminal when you're through"
export PS1="SECURE $PS1"

When this script is executed, the environment variables within it are set, and a warning to close the terminal is emitted.
In order to automate the steps of mounting the secure volume, launching the interactive shell, and unmounting the volume, we have to use a couple of different tools.

Mount, Execute, Eject

The first is hdid which mounts a volume by filename. The output of this command provides both the device file, like /dev/disk1 and the mount point, like /Volumes/Vault.

The mount point is used to construct the path to the custom bash profile which initializes sensitive environment variables in a new interactive shell, launched with a pristine environment. This results in an isolated terminal with mingled secure and user-specific environment variables and settings. Additionally, the secure volume remains mounted for the lifespan of this secure session, allowing your deploy to read files like production ssh keys, or any other restricted resource, from this secure location.

Finally, when the interactive terminal exits, hdiutil ejects the disk device for the mounted volume.

Set It Up

The code to do all of this is stored in a bash function. Add the following lines to your ~/.bash_profile or equivalent and set the VAULT_DMG variable to the name of your encrypted disk image.

# Read Secure Volume credentials for deploy
VAULT_DMG=~/Vault.dmg
function sv () {
    SECURE_MOUNT_INFO=`hdid $VAULT_DMG`;
    SECURE_MOUNT_DEVICE=`echo -e $SECURE_MOUNT_INFO | cut -d ' ' -f1`;
    SECURE_MOUNT_PATH=`echo -e $SECURE_MOUNT_INFO | cut -d ' ' -f2`;
    bash --init-file $SECURE_MOUNT_PATH/.bash_profile;
    hdiutil eject $SECURE_MOUNT_DEVICE > /dev/null;
    unset SECURE_MOUNT_INFO SECURE_MOUNT_PATH SECURE_MOUNT_DEVICE
}

The Problem

Using subdomains with Rails is kind of a pain. The only official support for subdomains is as asset hosts, as described in the AssetTagHelper documentation.

Matthew Hollingworth’s subdomain_routes covers most of the gaps in dealing with subdomains in Rails, including; generating subdomain routes, scoping resources to subdomains, and exposing subdomain information to controllers.

What I want to talk about is how I deal with subdomains in a development-environment context.

Hands off my /etc/hosts

Most of the resources I’ve seen regarding working with domain names in Rails involve manually modifying the system’s /etc/hosts file, though Eloy Duran’s PassengerPane makes it simple for those developing with Phusion Passenger.

Robby Russell calls out the gem ghost, which makes managing custom domains and subdomains drop-dead simple. The gem provides the ability to map domain names to arbitrary IPs, but in development you probably just want to map everything to the loopback address 127.0.0.1.

Putting it into practice

I like to have each application manage its own domain-to-ip mappings, so I need to make sure all of the domains the application will use are accessible. How you go about this is up to you, but here’s simple example showing how to use ghost to manage four cdn hosts, the www subdomain, and the canonical domain name from config/environments/development.rb.

if hostname = ENV['RAILS_HOSTNAME']
  require 'ghost'
  cdn_domain_templates = (1..4).map { |i| 'cdn%d.%%s' % i }
  (cdn_domain_templates + [ 'www.%s', '%s' ]).each do |template|
    Host.add(template % hostname)
  end
end

After starting your application in development mode, ghost will attempt to map these domain names if necessary. It escalates its permissions via sudo so you may be prompted to enter your password.

$ ghost list
Listing 6 host(s):
      cdn1.devdomain.com -> 127.0.0.1
      cdn2.devdomain.com -> 127.0.0.1
      cdn3.devdomain.com -> 127.0.0.1
      cdn4.devdomain.com -> 127.0.0.1
           devdomain.com -> 127.0.0.1
       www.devdomain.com -> 127.0.0.1

I typically leave these hostnames sitting around, but cleaning them up is as simple as issuing the command sudo ghost empty. The advantage to leaving the host entries in place is that the initial security escalation needed to establish the entries is bypassed on subsequent launches of the application.

Working in Parallels

If you use Parallels to run your application through its paces on Windows, it can be convenient to use the same domain names within the virtual machine and in OS X.

By default, virtual hosts within Parallels are set up to use Bridged Networking, causing the host to appear as a peer on the same LAN as the Mac on which it’s running. This means that in order to reach the Mac, the virtual host needs to know the Mac’s IP, which may be subject to change. To insulate yourself from this hassle, you can instead isolate the virtual host on a new subnet.

To do this, first go the Network Preferences in Parallels and enable DHCP for Shared Networking:
Parallels Global Preferences

Next, configure the virtual host to use Shared Networking:
Parallels Virtual Machine Preferences

Finally, update the virtual host’s hosts file, located at %SystemRoot%\system32\drivers\etc\ to map your application’s domains and subdomains to the IP belonging to the virtual network adapter managed by Parallels.

Configure Hosts

Now you should be able to access your application by hostname from the virtual host and can therefore copy and paste URLs between environments.

Another interesting technique I spotted in the gRaphaƫl code base is the use of a prefixed + used to cast a variable to a numeric type.

var data = [ undefined, null, 1, 10.2, new Date() ];
for (var i = 0, len = data.length; i < len; i++)
  console.log('cast %o: %o', data[i], +data[i]);

If you run this code, notice how casting undefined returns NaN which will ripple through your calculations. However, my favorite thing about this technique is how it handles Date objects. The following examples are equivalent.

var now = new Date();
console.log('now.valueOf: %o', now.valueOf());
console.log('+now: %o', +now);

Nice.

In hacking on the gRaphaĆ«l code base, I came across a recurring pattern syntax pattern I hadn’t encountered in JavaScript before.

Essentially, instead of using this very common conditional construct:

if (a) b;

The author uses:

!a && b;

Similarly,

if (a) b; else c;

Is written:

!a && b; a && c;

I was curious about the performance difference between the styles, and wrote a benchmark to compare them.

I only tested in WebKit nightly 53415, but I found that in every case, the if / if-else construct outperformed the pure-logic construct. The differences in performance are admittedly negligible, so I’ll be sticking to if-else for readability, and I’ll accept the performance benefit as a happy side-effect.

Cookies stored with a path option are treated somewhat differently in Internet Explorer than they are in many other browsers. The issues are especially prevalent in modern web applications with “clean” urls.

For example, a cookie stored with a path of /movies/the-wizard-of-speed-and-time is not visible to Internet Explorer users visiting /movies/the-wizard-of-speed-and-time, but is visible to Safari and to Firefox users.

The Wizard of Speed and Time

To deal with this issue it is necessary to issue the cookie with a path one directory higher than the specific page you’re looking at. Additionally, the cookie name needs to be disambiguated from other movie-specific cookies since the path scope /movies is no longer exclusive to a single movie.

Also remember, cookie paths are case-sensitive, so your application should either issue a cookie whose path matches the request the user issues, or the user should be redirected to a canonical, normalized url.

It’s important to be able to test your application across multiple versions of major browsers. Safari’s use of a system-wide Webkit makes this a little difficult, but fortunately enterprising developers have worked to package up a stand-alone version of Safari 3.2.1.

Download Safari 3.2.1 Stand-Alone.
Safari 3.2.1

When business logic dictates that something only happens on Saturday, this snippet can help keep your code and tests legible.

module DatePredicates
  Date::DAYNAMES.each_with_index do |day_name, i|
    define_method "#{day_name}?" do i == wday end
  end
end
 
class Date
  include DatePredicates
end

Date.today.Tuesday?
=> true

ActionScript’s ExternalInterface is a powerful tool, allowing you to execute and retrieve results from JavaScript in the browser.

Recently however, a strange bug was encountered where Flash running in one part of a page was exhibiting strange rendering issues, such as pieces of the background failing to draw, and Sprites flickering when ExternalInterface calls were made. To make things even more puzzling, the Flash exhibiting the rendering issues was not the one making the calls.

At first it seemed the issue was caused by css, as it only appeared when adding DOM nodes to a parent node styled overflow: auto. After further investigation, it was found found that manipulating the DOM within the ExternalInterface callback was the culprit.

In order to prevent the flickering, it was necessary to decouple the ExternalInterface call from the DOM work. The fix itself was simple.

var client = new Client();
function notifyClient() {
  var arg = arguments[0];
  setTimeout(function() { client.notify(arg); }, 0);
}

Notice how a local is explicitly created to lift out the first argument passed to the JavaScript function instead of using a named argument. In some browsers it was found that named locals were not threaded through to the client.

Using setTimeout with a delay of 0 simply schedules the provided anonymous function to be executed as soon as the singly-threaded JavaScript interpreter is available.

Whenever the result of an ExternalInterface call is not needed for consumption by ActionScript, consider using setTimeout to decouple the work performed by each component.

I really like Ruby, and I really like how the Prototype library makes javascript more Ruby-like. Ruby’s Hash provides a number of convenient methods that Prototype doesn’t ship with. Here is a small extension that borrows a little from Ruby.

Hash.prototype = Object.extend(Hash.prototype, {
  hasKey: function(key) {
    return this._object.hasOwnProperty(key);
  },
  fetch: function(key, fallback) {
    return (this.hasKey(key) ? this.get(key) : fallback);
  },
  getWithDefault: function(key, fn) {
    return (this.hasKey(key) ? this.get(key) : this.set(key, fn()));
  },
  getOrSet: function(key, val) {
    return (this.hasKey(key) ? this.get(key) : this.set(key, val));
  }
});

First, it should be simple to check for the existence of a key in a Hash, whether or not that key contains a falsy value. Since Prototype 1.6, a Hash’s inner object is stored independently of the Hash objects real keys, such as its methods, so the hasKey implementation will only work with Prototype 1.6.

Next up is fetch, which behaves the same as Ruby’s fetch, returning the value present in the Hash for the provided key if a value exists, and providing your supplied alternative otherwise.

getOrSet does essentially the same thing, but adds the alternative value to the Hash if no value was previously present.

Finally, getWithDefault takes a functional 2nd argument which is invoked only if the provided key is not present in the Hash, which is useful for memoizing expensive work.