<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <title>&lt;3! — Chris Kampmeier on Ruby, Rails, and other delights</title>
  <id>tag:www.shiftcommathree.com,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://www.shiftcommathree.com/feed/atom.xml" rel="self" type="application/atom+xml" />
  <link href="http://www.shiftcommathree.com/" rel="alternate" type="text/html" />
  <updated>2009-10-24T22:36:41Z</updated>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2009-08-10:786</id>
    <published>2009-08-10T06:05:00Z</published>
    <updated>2009-10-24T22:36:41Z</updated>
    <link href="http://www.shiftcommathree.com/articles/how-to-install-mongodb-on-os-x" rel="alternate" type="text/html" />
    <title>How to install MongoDB on OS X</title>
<content type="html">
            &lt;p&gt;I started playing with &lt;a href="http://www.mongodb.org"&gt;MongoDB&lt;/a&gt; this weekend. It’s a cool little database, and John Nunemaker’s &lt;a href="http://mongomapper.com"&gt;MongoMapper&lt;/a&gt; gem is a treat. Mongo’s maintainers are nice enough to provide pre-compiled binaries for OS X, but you still have to do a little setup and configuration. (There’s actually a portfile on MacPorts, but it wasn’t up-to-date with the latest version when I found it).&lt;/p&gt;

&lt;p&gt;Here’s how I got the server installed and running as a daemon in OS X, for local development.&lt;/p&gt;

&lt;p&gt;Download, unpack, and install the pre-compiled 64-bit binaries:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;curl -O http://downloads.mongodb.org/osx/mongodb-osx-x86_64-1.0.1.tgz&lt;tt&gt;
&lt;/tt&gt;tar xzf mongodb-osx-x86_64-1.0.1.tgz&lt;tt&gt;
&lt;/tt&gt;sudo mv mongodb-osx-x86_64-1.0.1 /usr/local/mongodb&lt;tt&gt;
&lt;/tt&gt;sudo mkdir /usr/local/mongodb_data /var/log/mongodb&lt;tt&gt;
&lt;/tt&gt;sudo chown -R root /usr/local/mongodb&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;(If you’re on a 32-bit machine, substitute in &lt;code&gt;i386&lt;/code&gt; for each &lt;code&gt;x86_64&lt;/code&gt; above.)&lt;/p&gt;

&lt;p&gt;Next, you’ll want to make a config file so you can change the server’s options without fiddling with command-line arguments.&lt;/p&gt;

&lt;p&gt;Save as: &lt;strong&gt;&lt;code&gt;/usr/local/mongodb/mongod.conf&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;# Store data alongside MongoDB instead of the default, /data/db/&lt;tt&gt;
&lt;/tt&gt;dbpath = /usr/local/mongodb_data&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;# Only accept local connections&lt;tt&gt;
&lt;/tt&gt;bind_ip = 127.0.0.1&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Now, we’ll make a &lt;code&gt;launchd&lt;/code&gt; job to register the server as an OS X daemon. &lt;code&gt;launchd&lt;/code&gt; will start the server at startup, stop it before shutdown, make sure it stays up, and redirect its output to a nice log file.&lt;/p&gt;

&lt;p&gt;Save as: &lt;strong&gt;&lt;code&gt;/Library/LaunchDaemons/org.mongodb.mongod.plist&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="pp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="pp"&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot;&lt;tt&gt;
&lt;/tt&gt;  &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="an"&gt;version&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;org.mongodb.mongod&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/local/mongodb/bin/mongod&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;run&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;--config&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/local/mongodb/mongod.conf&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;true&lt;/span&gt;&lt;span class="ta"&gt;/&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;KeepAlive&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;true&lt;/span&gt;&lt;span class="ta"&gt;/&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;WorkingDirectory&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/local/mongodb&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StandardErrorPath&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/var/log/mongodb/output.log&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;StandardOutPath&lt;span class="ta"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="ta"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/var/log/mongodb/output.log&lt;span class="ta"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="ta"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Now we just need to load the &lt;code&gt;launchd&lt;/code&gt; job:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;sudo launchctl load /Library/LaunchDaemons/org.mongodb.mongod.plist&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;And that should do it! Try visiting &lt;a href="http://localhost:28017"&gt;http://localhost:28017&lt;/a&gt; to see the status console for your database.&lt;/p&gt;

&lt;p&gt;One last thing: you should probably stick &lt;code&gt;/usr/local/mongodb/bin&lt;/code&gt; in your &lt;code&gt;$PATH&lt;/code&gt;. That way you can use the other binaries that ship with MongoDB, like the &lt;code&gt;mongo&lt;/code&gt; console, &lt;code&gt;mongoexport&lt;/code&gt;, and so on.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/SaF9Sv935Y8" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2009-07-26:735</id>
    <published>2009-07-26T06:38:00Z</published>
    <updated>2009-07-26T06:51:47Z</updated>
    <link href="http://www.shiftcommathree.com/articles/make-your-rails-maintenance-page-respond-with-a-503" rel="alternate" type="text/html" />
    <title>Use a 503 for your Rails maintenance page</title>
<content type="html">
            &lt;p&gt;Most of the docs out there about how to configure Apache for Capistrano’s &lt;code&gt;deploy:web:disable&lt;/code&gt; task use a quick &lt;code&gt;RewriteRule&lt;/code&gt; to the maintenance page.&lt;/p&gt;

&lt;p&gt;That looks OK, but it doesn’t change the status code of the response: clients will usually get a &lt;code&gt;200 OK&lt;/code&gt;, indicating that your server is fine and that you’re sending the normal response. The correct status code to respond with is &lt;code&gt;503 Service Unavailable&lt;/code&gt;. With a 503, you’ll hopefully prevent search engines from indexing your maintenance page, make life easier on API consumers, enable AJAX requests to correctly deal with the site being down, and so on.&lt;/p&gt;

&lt;p&gt;Here’s the configuration I’m using now:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;# Show maintenance page if it exists&lt;tt&gt;
&lt;/tt&gt;ErrorDocument 503 /system/maintenance.html&lt;tt&gt;
&lt;/tt&gt;RewriteEngine On&lt;tt&gt;
&lt;/tt&gt;RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|png)$&lt;tt&gt;
&lt;/tt&gt;RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f&lt;tt&gt;
&lt;/tt&gt;RewriteCond %{SCRIPT_FILENAME} !maintenance.html&lt;tt&gt;
&lt;/tt&gt;RewriteRule ^.*$  -  [redirect=503,last]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;About that suspicious looking &lt;code&gt;redirect=503&lt;/code&gt; flag, here’s an excerpt from the &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#redirect"&gt;flags section of the mod_rewrite docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;While this is typically used for redirects, any valid status code can be given here.
    If the status code is outside the redirect range (300-399), then the &lt;em&gt;Substitution&lt;/em&gt;
    string is dropped and rewriting is stopped as if the &lt;code&gt;L&lt;/code&gt; flag was used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So technically speaking, you can give &lt;code&gt;RewriteRule&lt;/code&gt; anything for that second argument, and the &lt;code&gt;last&lt;/code&gt; flag doesn’t need to be specified because it’s automatically applied. I just find it more intention-revealing to use the path “&lt;code&gt;-&lt;/code&gt;” and stick the &lt;code&gt;last&lt;/code&gt; flag on there anyway.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/2ZFNS5j_CZw" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2009-05-10:591</id>
    <published>2009-05-10T02:49:00Z</published>
    <updated>2009-05-10T02:51:03Z</updated>
    <link href="http://www.shiftcommathree.com/articles/how-to-prevent-database-contention-in-continuous-integration" rel="alternate" type="text/html" />
    <title>How to prevent database contention in continuous integration</title>
<content type="html">
            &lt;p&gt;We’ve used a few different continuous integration stacks for Rails over the last year at work—first &lt;a href="http://cruisecontrolrb.thoughtworks.com"&gt;CruiseControl.rb&lt;/a&gt;, which we found a little too complex to administer, then a custom bash script (which worked well, but took a lot of tweaking to get just right). When we eventually switched to git last year, we took the opportunity to try &lt;a href="http://integrityapp.com"&gt;Integrity&lt;/a&gt;, a cute lil’ Sinatra app.&lt;/p&gt;

&lt;p&gt;Integrity mostly “just works,” and it’s been a happy switch. One thing we lost in the move, though, was code that protected against resource contention when two builds are running at once. This is definitely a problem with Rails, since a typical &lt;code&gt;database.yml&lt;/code&gt; tells Active Record to use the same database for all test runs. So you’ve got multiple builds hitting the database at once, dropping tables, creating records, and so on. Yikes.&lt;/p&gt;

&lt;p&gt;Our old bash script used a filesystem lock and a queue to only run one build at a time, in order. In theory, this is the most sound approach, but hey—our build server has 8 cores and 16 GB of RAM, plenty of room for parallelism. During a pair-programming session this week with &lt;a href="http://www.jaredgrippe.com"&gt;Jared Grippe&lt;/a&gt;, we decided that the best approach is to solve the contention issues and allow multiple simultaneous builds. We figured that’d keep the &lt;a href="http://martinfowler.com/articles/continuousIntegration.html#KeepTheBuildFast"&gt;rapid feedback&lt;/a&gt; up-to-speed when the commits are flying in.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stop putting code in that little “build script” box in Integrity’s configuration page. Instead, drop it in a rake task, so it’s versioned and kept safe.&lt;/li&gt;
&lt;li&gt;In your build script, set a unique database name for the current build, and use ERB in the server’s &lt;code&gt;database.yml&lt;/code&gt; to interpolate it in.&lt;/li&gt;
&lt;li&gt;Have the build script run &lt;code&gt;rake db:create&lt;/code&gt; and &lt;code&gt;rake db:drop&lt;/code&gt;, so that your databases are created and cleaned-up automatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s an example script:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;desc &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Run continuous integration suite&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;task &lt;span class="sy"&gt;:build&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] = &lt;span class="co"&gt;RAILS_ENV&lt;/span&gt; = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# use ERB in config/database.yml to make this the database name:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# database: &amp;lt;%= ENV[&amp;quot;DB_NAME&amp;quot;] %&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  now = &lt;span class="co"&gt;Time&lt;/span&gt;.now.utc&lt;tt&gt;
&lt;/tt&gt;  identifier = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;&lt;span class="co"&gt;Process&lt;/span&gt;.pid&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;now.to_i&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;now.usec&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;ENV&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;DB_NAME&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;myapp_test_&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;identifier&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Rake&lt;/span&gt;::&lt;span class="co"&gt;Task&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;db:create&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].invoke&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Rake&lt;/span&gt;::&lt;span class="co"&gt;Task&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;db:test:load&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].invoke&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Rake&lt;/span&gt;::&lt;span class="co"&gt;Task&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].invoke&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;ensure&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;Rake&lt;/span&gt;::&lt;span class="co"&gt;Task&lt;/span&gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;db:drop&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].invoke&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Appending the process ID and time in microseconds to the database name is about as unique as you can get, without generating a UUID or something. Note how we wrap the build in a block, and perform &lt;code&gt;db:drop&lt;/code&gt; in the &lt;code&gt;ensure&lt;/code&gt; section: that way, the database is removed even if the build fails (which would normally abort your rake task).&lt;/p&gt;

&lt;p&gt;Keep in mind that the database might not be the only shared resource used by your build—watch out for filesystem use, in particular. You can probably use a similar strategy to solve that problem.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/bcACnEV3GDU" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2009-02-19:330</id>
    <published>2009-02-19T07:24:00Z</published>
    <updated>2009-11-11T04:16:03Z</updated>
    <link href="http://www.shiftcommathree.com/articles/the-steamroller" rel="alternate" type="text/html" />
    <title>The steamroller</title>
<content type="html">
            &lt;p&gt;One thing I do here and there at &lt;a href="http://www.rupture.com"&gt;Rupture&lt;/a&gt; is interview Rubyists who have applied to work with us. The Mythical Man and his Month notwithstanding, we could use a few more pairs of able hands. You know, so I can work less and blog more.&lt;/p&gt;

&lt;p&gt;Our interview process has two parts: pair programming, and then some mostly-unstructured talk about the non-code aspects of software projects. Today I had the pleasure of talking with Josh Ferguson, and we ended up in a conversation about Rails’ new direction. Josh was concerned that as Rails matures, it becomes less opinionated, and therefore less attractive to the people who identified with the movement in the first place.&lt;/p&gt;

&lt;p&gt;I’m still thinking about that, but the whole thing reminded me of a note I submitted to Obie Fernandez for inclusion in &lt;a href="http://www.amazon.com/Rails-Way-Addison-Wesley-Professional-Ruby/dp/0321445619/"&gt;The Rails Way&lt;/a&gt;. It’s been more than a year since his book was published, and I never got around to cross-posting here… Obie had asked for contributors to answer the question: “what does The Rails Way mean to you?”&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;There’s a line at the beginning of the SICP lectures—a famous course on
    functional programming—where Harold Abelson is defining “computer science”
    for his class:&lt;/p&gt;
    
    &lt;blockquote&gt;
        &lt;p&gt;“Computer science” is a terrible name for this business. First of all, it’s not
        a science; it might be engineering, or it might be art… It’s also not very
        much about computers, in the same sense that physics is not really about
        particle accelerators, and biology is not really about microscopes and Petri
        dishes, and geometry is not really about using surveying instruments.&lt;/p&gt;
        
        &lt;p&gt;The reason that we think that computer science is about computers is pretty much
        the same reason that the Egyptians thought that measuring their plots after the
        flooding of the Nile was about surveying instruments, and not geometry: when
        some field is just getting started, and you don’t really understand it very
        well, it’s very easy to confuse the essence of what you’re doing with the tools
        that you use.&lt;/p&gt;
    &lt;/blockquote&gt;
    
    &lt;p&gt;In the same way, my sense of “the Rails way” is not really about Rails, Ruby, or
    any of these new tools we’re using. Its “essence” is an uncompromising drive to
    optimize for productivity and happiness. It’s a hard-learned pragmatism:
    processes for people who refuse to solve the same problem twice, who are annoyed
    enough by the speed bumps their tools sometimes introduce that they happily gas
    up the steamroller.&lt;/p&gt;
    
    &lt;p&gt;A necessary corollary to the idea that Rails’ secret sauce is distinct from the
    code frozen to our vendor directories is that one day, a better instantiation of
    these practices will come along. I love Ruby, Rails, and their communities, but
    I know that we’ll all move on at some point. When that day comes, and some new
    10-minute screencast makes us squeal like kids, we should have the sense to jump
    into it head-first, with the same abandon with which we dropped all that stuff
    we &lt;em&gt;used&lt;/em&gt; to do for a living.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anyway, if you’re interested in the SICP lectures, they’re pretty much canonical. (Nathan Sobo introduced me to them, and made me think about functional programming in general, when we were living in Venice. I’m a lucky guy.) A good way to get started is the set of &lt;a href="http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/"&gt;lecture videos&lt;/a&gt; recorded at HP in 1986 by Abelson and Sussman, who started the course. Their &lt;a href="http://mitpress.mit.edu/sicp/"&gt;SICP book&lt;/a&gt; is available online for free, too.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/d0qCvpzX6Qo" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2008-06-02:35</id>
    <published>2008-06-02T19:44:00Z</published>
    <updated>2008-07-08T11:11:28Z</updated>
    <link href="http://www.shiftcommathree.com/articles/irb-tip-get-last-returned-value" rel="alternate" type="text/html" />
    <title>irb tip: get last returned value</title>
<content type="html">
            &lt;p&gt;Just use underscore.&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;gt;&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Chunky bacon&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Chunky bacon&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; _&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Chunky bacon&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The fruits of an investigation I started when Jon Baudanza at Rupture offered a brownie bite for the first person to figure it out. I’ll do pretty much anything for a brownie bite…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; you can also use &lt;code&gt;conf.last_value&lt;/code&gt;, as well as its aliases &lt;code&gt;context.last_value&lt;/code&gt; and &lt;code&gt;irb_context.last_value&lt;/code&gt;.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/aW4eIFibK5c" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2008-02-04:14</id>
    <published>2008-02-04T04:30:00Z</published>
    <updated>2008-11-30T08:42:43Z</updated>
    <link href="http://www.shiftcommathree.com/articles/testing-your-dependencies" rel="alternate" type="text/html" />
    <title>Testing your dependencies with RSpec</title>
<content type="html">
            &lt;p&gt;I’m finding that managing my projects’ code dependencies is smelling worse and worse as time goes on. Code bases get bigger and acquire libraries as they grow; a part of your project sits untouched for a few months and its particulars leave your medium-term memory, and so on.&lt;/p&gt;

&lt;p&gt;In Rails, we can freeze lots of stuff to our &lt;code&gt;vendor&lt;/code&gt; directories. I do that as much as possible—gems that I only use for Rails apps get frozen to &lt;code&gt;vendor/gems&lt;/code&gt; and then uninstalled system-wide; I use the &lt;code&gt;gemsonrails&lt;/code&gt; plugin for this. If the little gem bits aren’t necessary, you can just pistonize a repository. Old news.&lt;/p&gt;

&lt;p&gt;That’s not going to fly for platform-compiled gems, or even compiled libraries that aren’t gems at all (since you’re possibly running several different platforms between development and production). So I’ve been cooking up ways to keep myself sane:&lt;/p&gt;

&lt;p&gt;The Simplest Thing That Could Possibly Work, I think, is just a quick test failure when a dependency is missing. If you’re already &lt;code&gt;autotest&lt;/code&gt;ing locally, and automatically running your test suite on each production machine as part of your deployment recipe, a quick, obvious exception could save you a little misery.&lt;/p&gt;

&lt;h3&gt;What I mean by “obvious”&lt;/h3&gt;

&lt;p&gt;This all came about because I went through two development platform switches recently: first, a clean install of Leopard, and just last week, a move to Intel from my old PowerBook. Both of those hosed my gems, and although I got test failures for each “broken” part of the app, certain libraries’ lazy/quiet-loading techniques don’t raise exceptions in a way that’s obvious.&lt;/p&gt;

&lt;p&gt;For example, Rick Olson’s fantastic &lt;code&gt;attachment_fu&lt;/code&gt; plugin is meant to work just fine for non-image files, so if you don’t have a compatible image processing library installed, it’ll just skip the thumbnailing for images and move right along. So my image-uploading tests failed on not creating the right number of files and records. It took me way too long to figure out what was going on, so I think it’d be better if I was checking for known dependencies directly.&lt;/p&gt;

&lt;h3&gt;First try&lt;/h3&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="co"&gt;User&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;depends on one of three image processing libraries&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    processors = &lt;span class="s"&gt;&lt;span class="dl"&gt;%w(&lt;/span&gt;&lt;span class="k"&gt;image_science RMagick mini_magick&lt;/span&gt;&lt;span class="dl"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    lambda {&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        require processors.shift&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;rescue&lt;/span&gt; &lt;span class="co"&gt;LoadError&lt;/span&gt;, &lt;span class="co"&gt;MissingSourceFile&lt;/span&gt; =&amp;gt; e&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;retry&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; processors.any? &lt;span class="r"&gt;or&lt;/span&gt; raise e, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Make sure an image processing library is available&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    }.should_not raise_error&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Pretty good, although so much space between &lt;code&gt;it&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; makes me sad. Also, &lt;code&gt;attachment_fu&lt;/code&gt;’s requirements are kind of an edge-case; I want to be able to spec a requirement for only one library, or several all at once.&lt;/p&gt;

&lt;h3&gt;Less sadness with matchers&lt;/h3&gt;

&lt;p&gt;Read up: &lt;a href="http://tuples.us/2007/10/23/if-you-arent-writing-matchers-you-arent-using-rspec"&gt;if you aren’t using matchers, you aren’t using RSpec.&lt;/a&gt;&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="co"&gt;User&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;depends on an image processing library for attachment_fu&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    one_of(&lt;span class="sy"&gt;:image_science&lt;/span&gt;, &lt;span class="sy"&gt;:RMagick&lt;/span&gt;, &lt;span class="sy"&gt;:mini_magick&lt;/span&gt;).should be_loadable&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;depends on SHA libraries for password hashing&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    both_of(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;digest/sha1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;digest/sha2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;).should be_loadable&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;describe &lt;span class="co"&gt;Event&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;depends on chronic for date/time string processing&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="sy"&gt;:chronic&lt;/span&gt;.should be_loadable&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;describe &lt;span class="co"&gt;Post&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;depends on a text processing library for Markdown support&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    either_of(&lt;span class="sy"&gt;:maruku&lt;/span&gt;, &lt;span class="sy"&gt;:RedCloth&lt;/span&gt;).should be_loadable&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  it &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;depends on some XML libraries&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    all_of(&lt;span class="sy"&gt;:hpricot&lt;/span&gt;, &lt;span class="sy"&gt;:builder&lt;/span&gt;, &lt;span class="sy"&gt;:haml&lt;/span&gt;).should be_loadable&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The matcher I wrote to do this is a little beefy, around 60 lines. To check it out, you can grab it from &lt;a href="https://svn.shiftcommathree.com/rails_plugins/rspec_matchers/be_loadable_matcher.rb"&gt;svn&lt;/a&gt; (or &lt;a href="http://code.shiftcommathree.com/railsplugins/browser/rspec_matchers/be_loadable_matcher.rb"&gt;in the &amp;lt;3 warehouse&lt;/a&gt;), or from &lt;a href="http://pastie.caboo.se/147106"&gt;pastie&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m now using this all over the place, and it’s saved me at least a couple headaches. It’s really helpful for making sure your CI and deployment environments are up to spec, as well.&lt;/p&gt;

&lt;p&gt;I’m sure there’s more to do—like checking gem versions. How are you checking your dependencies from platform to platform?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update on Nov. 30, 2008:&lt;/strong&gt; well, this was a useful experiment in writing matchers, but these days I’m just using Rails’ built-in &lt;code&gt;config.gem&lt;/code&gt; tool. Highly recommended.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/HlyhAHR6fxw" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2007-08-06:2</id>
    <published>2007-08-06T04:00:00Z</published>
    <updated>2009-05-10T03:04:46Z</updated>
    <link href="http://www.shiftcommathree.com/articles/operating-ruby-style" rel="alternate" type="text/html" />
    <title>Operating Ruby-style</title>
<content type="html">
            &lt;p&gt;&lt;img class="article_image" src="http://www.shiftcommathree.com/assets/2007/8/4/2_operator_1.png" alt="Operator game board with Ruby operator symbols for bones" /&gt;&lt;br /&gt;
At work I sometimes have occasion to write number-crunching C code, so I’m used to the &lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;|&lt;/code&gt; operators standing for bitwise &lt;code&gt;AND&lt;/code&gt; and &lt;code&gt;OR&lt;/code&gt;. I’m also a reformed PHP hacker (aren’t we all?), so I’m used to &lt;code&gt;===&lt;/code&gt; meaning “equality without type coercion”. These definitions are only occasionally true in Ruby, because meaning depends on context: one thing I’ve come to appreciate is how many Ruby “operators” are just methods, and so they often have different implementations depending on the object receiving the method call.&lt;/p&gt;

&lt;p&gt;Thing is, you gotta learn how to operate, Ruby-style.&lt;/p&gt;

&lt;h3&gt;Unusual operator expressions&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/strong&gt; — In an integer context (&lt;code&gt;Fixnum&lt;/code&gt; and &lt;code&gt;Bignum&lt;/code&gt;), this is indeed a bitwise &lt;code&gt;AND&lt;/code&gt;. But in a logical context, it’s just like &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; (logical &lt;code&gt;AND&lt;/code&gt;), but without short-circuiting when the receiver (that is, the left operand) evaluates to &lt;code&gt;false&lt;/code&gt; or &lt;code&gt;nil&lt;/code&gt;. Both operands are always evaluated. This is because &lt;code&gt;&amp;amp;&lt;/code&gt; is implemented as an instance method for the singletons &lt;code&gt;TrueClass&lt;/code&gt;, &lt;code&gt;FalseClass&lt;/code&gt;, and &lt;code&gt;NilClass&lt;/code&gt;, and arguments to a method are evaluated when it’s called. (&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, on the other hand, is not a method. Like all the non-method operators and other punctuation, it’s picked up by the parser and handled in C. &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; is logically implemented in Ruby’s expression-evaluation function.) &lt;/p&gt;

&lt;p&gt;Why would you want a logical &lt;code&gt;AND&lt;/code&gt; without short-circuiting? Got me. In fact, I have a theory that the lack of short-circuiting is just a side-effect of the method-based implementation, and that the real reason for this operator to be defined for logical evaluation is to have a stricter &lt;code&gt;AND&lt;/code&gt; that doesn’t allow duck typing in certain scenarios, since the receiver has to be &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, or &lt;code&gt;nil&lt;/code&gt;:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="i"&gt;5&lt;/span&gt; &amp;amp; &lt;span class="pc"&gt;true&lt;/span&gt;     &lt;span class="c"&gt;# =&amp;gt; TypeError: can't convert true into Integer&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="i"&gt;5&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class="pc"&gt;true&lt;/span&gt;    &lt;span class="c"&gt;# =&amp;gt; true&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;I pretty much just made that up, though, and I’m all ears if you have other ideas. It strikes me that all the obvious reasons to not want short-circuiting don’t cut it in this situation: wanting to ensure that the side-effect of the right operand happens seems very un-Ruby (say, opening a file or inline assignment—why force it into a logical expression?), and wanting to have arbitrary return values for the expression doesn’t actually work because &lt;code&gt;&amp;amp;&lt;/code&gt; expressions always return &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. It works for &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, though:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# returns false or integer representation of privileges for user&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;administrative_privilege_level&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    is_admin? &amp;amp;&amp;amp; privileges.to_i&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;|&lt;/code&gt;&lt;/strong&gt; — Same as &lt;code&gt;&amp;amp;&lt;/code&gt;, but for &lt;code&gt;OR&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;^&lt;/code&gt;&lt;/strong&gt; — Exclusive &lt;code&gt;OR&lt;/code&gt;: evaluates to true if exactly one of the operands is non-&lt;code&gt;false&lt;/code&gt; and non-&lt;code&gt;nil&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since these are just methods, you can call them using the normal syntax. Take &lt;code&gt;==&lt;/code&gt;, another operator-as-method: evaluating &lt;code&gt;Class == Class&lt;/code&gt; is the same as calling &lt;code&gt;Class.==(Class)&lt;/code&gt;, that is, passing the argument &lt;code&gt;Class&lt;/code&gt; to the instance method &lt;code&gt;==&lt;/code&gt; on the receiver, &lt;code&gt;Class&lt;/code&gt;, which itself is an instance of type… &lt;code&gt;Class&lt;/code&gt;. Amen.&lt;/p&gt;

&lt;h3&gt;A few more&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;===&lt;/code&gt;&lt;/strong&gt; — Used for checking, um, &lt;em&gt;equaly-ness&lt;/em&gt; in &lt;code&gt;case&lt;/code&gt; expressions. &lt;code&gt;===&lt;/code&gt; is a synonym of &lt;code&gt;==&lt;/code&gt; for many objects, but some will override &lt;code&gt;===&lt;/code&gt; to create cool &lt;code&gt;case&lt;/code&gt; idioms. For example, &lt;code&gt;Range#===&lt;/code&gt; evaluates to true if the argument is a member of the range, so you can do things like this:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;election_table&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  last_initial = &lt;span class="iv"&gt;@last_name&lt;/span&gt;[&lt;span class="i"&gt;0&lt;/span&gt;].chr.downcase&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;case&lt;/span&gt; last_initial&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;..&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;then&lt;/span&gt; &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;..&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;then&lt;/span&gt; &lt;span class="i"&gt;2&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Note that &lt;code&gt;===&lt;/code&gt; is called on the &lt;code&gt;when&lt;/code&gt; expressions, passing the &lt;code&gt;case&lt;/code&gt; object as the argument. This is backwards from what you might assume at first glance, but it’s actually much more useful this way.&lt;/p&gt;

&lt;p&gt;Take &lt;code&gt;Module#===&lt;/code&gt;: it evaluates to true if the operand is an instance of the module or one of its descendants—essentially a backwards &lt;code&gt;is_a?&lt;/code&gt;, something like &lt;code&gt;is_class_of?&lt;/code&gt;. So you could use it in a &lt;code&gt;case&lt;/code&gt; statement to classify objects by class. (You should have a good reason to do this, though. The benefits of duck-typing come from letting go of this explicit type-checking style.) Another is &lt;code&gt;Regexp&lt;/code&gt;, where &lt;code&gt;===&lt;/code&gt; evaluates to true when the operand matches. So we can classify strings by regular expression.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Regexp&lt;/code&gt;: &lt;code&gt;~&lt;/code&gt;&lt;/strong&gt; — a unary operator that is just like the more-common &lt;code&gt;=~&lt;/code&gt;, except it always matches against &lt;code&gt;$_&lt;/code&gt;. (&lt;a href="http://docs.shiftcommathree.com/ruby?content=http%3A//docs.shiftcommathree.com/ruby/language.html%23inputoutputvariables"&gt;The Pickaxe&lt;/a&gt; says: &lt;code&gt;$_&lt;/code&gt;, a &lt;code&gt;String&lt;/code&gt;, is “the last line read by &lt;code&gt;Kernel#gets&lt;/code&gt; or &lt;code&gt;Kernel#readline&lt;/code&gt;. Many string-related functions in the &lt;code&gt;Kernel&lt;/code&gt; module operate on &lt;code&gt;$_&lt;/code&gt; by default. The variable is local to the current scope.”) Anyway, you can do this:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="gv"&gt;$_&lt;/span&gt; = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;rebarbative barbarism&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;~ &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;barb&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;             &lt;span class="c"&gt;# =&amp;gt; 2&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This leaves a bad taste in my mouth, though, like something shiny you find inside a mollusk. Add a few more layers of &lt;a href="http://en.wikipedia.org/wiki/Nacre"&gt;nacre&lt;/a&gt;, and skip the punctuation entirely using a &lt;code&gt;Regex&lt;/code&gt; literal as a condition:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;gets                   &lt;span class="c"&gt;# reads until \n and stores input in $_&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;return&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;q(uit)?&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;    &lt;span class="c"&gt;# operates on $_ magically&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;But that’s even worse. It’s deprecated now and you’ll get a warning if you try it. In my opinion, the only implicit receiver you should roll with is &lt;code&gt;self&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;String&lt;/code&gt;: &lt;code&gt;%&lt;/code&gt;&lt;/strong&gt; — Used for &lt;code&gt;sprintf&lt;/code&gt;ing with a single argument or &lt;code&gt;Array&lt;/code&gt; of arguments, like this:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%04x&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; % &lt;span class="i"&gt;61453&lt;/span&gt;               &lt;span class="c"&gt;# =&amp;gt; &amp;quot;f00d&amp;quot;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%s%.2f&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; % [&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="fl"&gt;821.3333&lt;/span&gt;]   &lt;span class="c"&gt;# =&amp;gt; &amp;quot;$821.33&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;&lt;/strong&gt; — Not redefinable, but worth mentioning: these function identically to &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;, and &lt;code&gt;!&lt;/code&gt;, but with super-low precedence. &lt;code&gt;not&lt;/code&gt; has the next-higher precedence from &lt;code&gt;and&lt;/code&gt; and &lt;code&gt;or&lt;/code&gt;, which for some reason share the same precedence (&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; beats out &lt;code&gt;||&lt;/code&gt; usually). You can get into trouble with these:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
&lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;b = &lt;span class="i"&gt;3&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;a = b &lt;span class="r"&gt;or&lt;/span&gt; &lt;span class="i"&gt;5&lt;/span&gt;      &lt;span class="c"&gt;# =&amp;gt; 3, and a is set to 3&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;b = &lt;span class="pc"&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;a = b || &lt;span class="i"&gt;5&lt;/span&gt;      &lt;span class="c"&gt;# =&amp;gt; 5, and a is set to 5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;a = b &lt;span class="r"&gt;or&lt;/span&gt; &lt;span class="i"&gt;5&lt;/span&gt;      &lt;span class="c"&gt;# =&amp;gt; 5, but a is set to false (!)&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;That happened because Ruby evaluated the expression as &lt;code&gt;(a = b) or 5&lt;/code&gt;, since &lt;code&gt;=&lt;/code&gt; has a higher precedence than &lt;code&gt;or&lt;/code&gt;. I have to guess that this is just another feature imported from Perl that isn’t as idiomatically useful in Ruby.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Rolling your own&lt;/h3&gt;

&lt;p&gt;Now, just because many Ruby operators are implemented as methods (and can thus be overridden) doesn’t mean you can define new operators using whatever characters you want. The ability to call methods using operator syntax is hardcoded into the parser for the operators that are already defined (they’re tokens in the parser), so &lt;code&gt;receiver operator argument&lt;/code&gt; and the unary version &lt;code&gt;operator receiver&lt;/code&gt; won’t work. You can’t even use &lt;code&gt;receiver.operator&lt;/code&gt; or &lt;code&gt;receiver::operator&lt;/code&gt;, because the parser only recognizes that syntax with a name that follows the method naming conventions: a lowercase letter or underscore followed by upper- or lower-case letters, digits, or underscores, and optionally ending in &lt;code&gt;!&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, or &lt;code&gt;=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, you can go and define all the new operators you want, but you’ll be using &lt;code&gt;send&lt;/code&gt; to call them, since the parser won’t recognize the syntax.&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Hash&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  define_method(&lt;span class="sy"&gt;&lt;span class="sy"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;&amp;lt;--&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    inspect&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;gadget = {&lt;span class="sy"&gt;:watch&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:laser&lt;/span&gt;, &lt;span class="sy"&gt;:hat&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:helicopter&lt;/span&gt;}&lt;tt&gt;
&lt;/tt&gt;gadget &amp;lt;--               &lt;span class="c"&gt;# =&amp;gt; parse error&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;gadget.&amp;lt;--               &lt;span class="c"&gt;# =&amp;gt; parse error&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;gadget.send(&lt;span class="sy"&gt;&lt;span class="sy"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;&amp;lt;--&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)      &lt;span class="c"&gt;# =&amp;gt; &amp;quot;{:watch=&amp;gt;:laser, :hat=&amp;gt;:helicopter}&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Not much point to that. However, feel free to redefine the existing operator methods in your classes. Everything will just work like you’d expect, and your objects will be good Ruby citizens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: check out &lt;a href="http://jicksta.com/articles/2007/08/29/superators-add-new-operators-to-ruby"&gt;Jay Phillips’ Superators gem&lt;/a&gt;, an interesting hack to add certain new operators to Ruby DSLs by overriding the existing binary and unary operators in sequence.&lt;/p&gt;

&lt;h3&gt;References and further reading&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://docs.shiftcommathree.com/ruby?content=http%3A//docs.shiftcommathree.com/ruby/language.html%23table_18.4"&gt;Table 18.4 from &lt;em&gt;Programming Ruby&lt;/em&gt;&lt;/a&gt; — a nice summary of which operators are implemented as methods, sorted by precedence&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/100511"&gt;How to Duck Type?&lt;/a&gt; — A very readable paper on approaches to duck-typing in Ruby&lt;/li&gt;
&lt;li&gt;&lt;a href="http://eli.thegreenplace.net/2007/06/02/logical-operators-in-perl-and-ruby/"&gt;Logical operators in Perl and Ruby&lt;/a&gt; — All about &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, and &lt;code&gt;not&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.shiftcommathree.com/ruby?content=http%3A//docs.shiftcommathree.com/ruby/language.html%23inputoutputvariables" /&gt;Input/output variable listing from &lt;em&gt;Programming Ruby&lt;/em&gt;&lt;/a&gt; — &lt;code&gt;$_&lt;/code&gt; and friends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="http://azita.org"&gt;Azita Mirzaian&lt;/a&gt; for the illustration.&lt;/em&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/1J_jYsUpeyg" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://www.shiftcommathree.com/">
    <author>
      <name>chrisk</name>
    </author>
    <id>tag:www.shiftcommathree.com,2007-07-30:1</id>
    <published>2007-07-30T17:33:00Z</published>
    <updated>2009-05-10T03:05:21Z</updated>
    <link href="http://www.shiftcommathree.com/articles/templated-attributes" rel="alternate" type="text/html" />
    <title>Templated attributes in ActiveRecord</title>
<content type="html">
            &lt;p&gt;&lt;img class="article_image" src="/assets/2007/8/7/1_templated_attributes_2.png" alt="Vandal spraypainting a wall using an 'http://' template" /&gt;&lt;br /&gt;
On a recent project, we decided it would be nice to have “templated attributes” for certain fields in a form. A templated attribute has a helpful initial value—kind of like a default value—except that these aren’t valid data or saved in the database. They’re suggestions to the user about the expected formatting or content of a field.&lt;/p&gt;

&lt;p&gt;So the game is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;keep these values out of the database&lt;/li&gt;
&lt;li&gt;specify these values once in the model, super-duper-DRY&lt;/li&gt;
&lt;li&gt;create a user experience that clearly implies that these values are just templates for valid data&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Case one: a &lt;code&gt;website&lt;/code&gt; attribute&lt;/h3&gt;

&lt;p&gt;We wanted a &lt;code&gt;website&lt;/code&gt; attribute to be prefilled with &lt;code&gt;http://&lt;/code&gt; as a suggestion to the user about proper URL formatting—most users will just enter “example.com” when prompted for a URL. This is to avoid XSS problems with &lt;code&gt;javascript:&lt;/code&gt; URIs and the like, and to keep browsers from resolving short URLs to be internal—nothing quite like being sent to &lt;code&gt;http://yoursite.com/www.theirsite.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;(Aside: there are better ways to handle this specific situation: a &lt;code&gt;:before_validation&lt;/code&gt; callback to fix invalid URLs and check for XSS attacks, or the fantastic &lt;a href="http://weblog.techno-weenie.net/2006/9/3/white-listing-plugin-for-rails"&gt;white_list plugin&lt;/a&gt;. But for now I’m interested in the general case.)&lt;/p&gt;

&lt;p&gt;This attribute needed certain behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the user hits the form, the field should be pre-filled with &lt;code&gt;http://&lt;/code&gt; if the real value is empty or nil.&lt;/li&gt;
&lt;li&gt;If the field is left as &lt;code&gt;http://&lt;/code&gt;, we should convert it to nil before validation.&lt;/li&gt;
&lt;li&gt;Client-side: to imply that the initial value is a suggestion, we’ll make the text color gray until the user makes a change. If the user’s only change is to empty the field, we should reset it to &lt;code&gt;http://&lt;/code&gt; and gray again on blur.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Case two: label attributes&lt;/h3&gt;

&lt;p&gt;There’s another use case, which you’ve seen before: a text field’s initial value is used as a replacement for its label. When the user clicks in the field, the “label” disappears. My example of this is a &lt;code&gt;phone&lt;/code&gt; attribute, where we’d like to suggest a standard US area code format. Something like &lt;code&gt;(123) 555-1234&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We don’t want the user to have to delete our dummy numbers and put in their own; it’s too much work. Instead we think that the reminder will help coax the right format out of the user by itself—so this field gets blanked on focus, unlike the &lt;code&gt;website&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;You also see this pattern used for content suggestions instead of formatting hints: for example, search fields and login forms which are space-constrained, like the built-in search in Firefox and Safari.&lt;/p&gt;

&lt;h3&gt;Get on with the plugin, already&lt;/h3&gt;

&lt;p&gt;OK, OK. So we have two kinds of templated attributes: those with &lt;strong&gt;starting values&lt;/strong&gt;, which are potentially the start of valid data, and &lt;strong&gt;labels&lt;/strong&gt;, which are just helpful, ephemeral reminders.&lt;/p&gt;

&lt;p&gt;Check out the goods:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  templated_attribute &lt;span class="sy"&gt;:website&lt;/span&gt;, &lt;span class="sy"&gt;:starting_value&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;http://&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  templated_attribute &lt;span class="sy"&gt;:phone&lt;/span&gt;, &lt;span class="sy"&gt;:label&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;(123) 555-1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Validations work as expected, since unchanged template values get removed in a &lt;code&gt;:before_validation&lt;/code&gt; callback. So you can sprinkle on a little &lt;code&gt;:validates_presence_of&lt;/code&gt; and &lt;code&gt;:validates_format_of&lt;/code&gt; for a really good time.&lt;/p&gt;

&lt;p&gt;There’s also some nice, unobtrusive Javascript you can generate to get the behavior I mentioned above. If you’re using &lt;code&gt;form_for&lt;/code&gt;, it’s totally automatic. It gets installed when you install the plugin, or you can install and remove manually with these &lt;code&gt;rake&lt;/code&gt; tasks:&lt;/p&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;rake templated_attribute&lt;span class="sy"&gt;:install&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;rake templated_attribute&lt;span class="sy"&gt;:remove&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;To turn off the Javascript for a given &lt;code&gt;templated_attribute&lt;/code&gt;—say, because the generated stuff doesn’t jibe with your fancy-pantsy, AJAX-validating, Grey Poupon of a form—just throw &lt;code&gt;:templated_javascript =&amp;gt; false&lt;/code&gt; in the options hash for &lt;code&gt;text_field&lt;/code&gt; or &lt;code&gt;text_area&lt;/code&gt;. You’ll have to do any styling and event handling by yourself.&lt;/p&gt;

&lt;p&gt;I’d like to make this work for fields other than &lt;code&gt;text_field&lt;/code&gt; and &lt;code&gt;text_area&lt;/code&gt;; the other contenders were &lt;code&gt;file_field&lt;/code&gt;, which we can’t do because the Javascript security model doesn’t let us touch its value at runtime, and &lt;code&gt;password_field&lt;/code&gt;, which I haven’t done because showing the template value would require dynamically switching the element to a &lt;code&gt;text_field&lt;/code&gt; and back (to avoid all those asterisks). That one’s on the list, though.&lt;/p&gt;

&lt;h3&gt;Plugin resources&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Browse the code:&lt;/strong&gt;&lt;br /&gt;
&lt;a href="http://railsplugins.code.shiftcommathree.com/browser/templated_attribute" class="code"&gt;&lt;code&gt;http://railsplugins.code.shiftcommathree.com/browser/templated_attribute&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generated rdocs (with installation instructions):&lt;/strong&gt;&lt;br /&gt;
&lt;a href="http://docs.shiftcommathree.com/rails_plugins/templated_attribute" class="code"&gt;&lt;code&gt;http://docs.shiftcommathree.com/rails_plugins/templated_attribute&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw svn action:&lt;/strong&gt;&lt;br /&gt;
&lt;a href="https://svn.shiftcommathree.com/rails_plugins/templated_attribute" class="code"&gt;&lt;code&gt;https://svn.shiftcommathree.com/rails_plugins/templated_attribute&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feed for svn changesets:&lt;/strong&gt;&lt;br /&gt;
&lt;a href="http://railsplugins.code.shiftcommathree.com/changesets.atom" class="code"&gt;&lt;code&gt;http://railsplugins.code.shiftcommathree.com/changesets.atom&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="http://azita.org"&gt;Azita Mirzaian&lt;/a&gt; for the illustration.&lt;/em&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/shiftcommathree-blog/~4/5U1NGM6fRAc" height="1" width="1"/&gt;</content>  </entry>
</feed>
