<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Effectif Development - Home</title>
  <id>tag:effectif.com,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  
  <link href="http://effectif.com/" rel="alternate" type="text/html" />
  <updated>2008-11-17T23:48:18Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/effectif-development" type="application/atom+xml" /><entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-11-17:153</id>
    <published>2008-11-17T23:36:00Z</published>
    <updated>2008-11-17T23:48:18Z</updated>
    <category term="automation" />
    <category term="merb" />
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/456553530/optimising-png-images-for-the-web" rel="alternate" type="text/html" />
    <title>Optimising PNG images for the web</title>
<content type="html">&lt;p&gt;Stoyan Stefanov has recently written an interesting series of articles on optimising image files for the web. In his &lt;a href="http://yuiblog.com/blog/2008/11/14/imageopt-3/"&gt;latest article&lt;/a&gt; he shows how to use &lt;a href="http://en.wikipedia.org/wiki/Pngcrush"&gt;pngcrush&lt;/a&gt; to safely shrink your files, one file at a time:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pngcrush -rem alla -brute -reduce src.png dest.png
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This evening I found myself wanting to repeat that command for all the PNG files in my current directory, and then (having reviewed the new images) overwrite the originals. Rather than do it by hand I did what all pragmatic programmers do these days, and wrote a script. Here it is in action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pngcrushall 
Crushing test4012.png ... ok
Crushing test9200a.png ... ok
Crushing test9200b.png ... ok
Overwrite original files? (y/N) y
Overwriting test4012.png ... ok
Overwriting test9200a.png ... ok
Overwriting test9200b.png ... ok
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can get it from github – &lt;a href="http://github.com/gma/gma-utils/tree/master/web/pngcrushall"&gt;download pngcrushall&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Obviously you’ll need to install &lt;a href="http://en.wikipedia.org/wiki/Pngcrush"&gt;pngcrush&lt;/a&gt; too. On a Mac this is pretty easy with &lt;a href="http://www.macports.org"&gt;MacPorts&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo port install pngcrush
&lt;/code&gt;&lt;/pre&gt;</content>  <feedburner:origLink>http://effectif.com/2008/11/17/optimising-png-images-for-the-web</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-11-11:151</id>
    <published>2008-11-11T23:20:00Z</published>
    <updated>2008-11-11T23:23:06Z</updated>
    <category term="automation" />
    <category term="merb" />
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/456553532/integration-testing-for-multiple-web-applications" rel="alternate" type="text/html" />
    <title>Integration Testing for Multiple Web Applications – Introducing Integral</title>
<content type="html">&lt;p&gt;I’ve recently been developing a Rails app that relies on a database that is maintained by another team as part of a different application. As you can imagine, unexpected changes to the database schema can bring our Rails app to it’s knees if they’re deployed to the live server before our application is updated.&lt;/p&gt;

&lt;p&gt;So far we’ve been lucky, but the issue has been at the back of our minds for a while. So this week I sat down and cooked up a solution, and we’ve called it &lt;a href="http://github.com/gma/integral/wikis"&gt;Integral&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Integral consists of some &lt;a href="http://yehudakatz.com/2008/05/12/by-thors-hammer/"&gt;Thor&lt;/a&gt; tasks that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run tests on your test server.&lt;/li&gt;
&lt;li&gt;Keep track of which versions of your applications work well together.&lt;/li&gt;
&lt;li&gt;Can be integrated into your deployment recipes to ensure that deploying an app should never break your live server again…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the Integral code is &lt;a href="http://github.com/gma/integral/tree/master"&gt;on github&lt;/a&gt;, and I’ve written some fairly extensive &lt;a href="http://github.com/gma/integral/wikis"&gt;documentation on the Wiki&lt;/a&gt;. Please try it out, give us some feedback, fork it, burn it, give us some feedback, etc. etc.&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/11/11/integration-testing-for-multiple-web-applications</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-10-05:145</id>
    <published>2008-10-05T08:36:00Z</published>
    <updated>2008-10-22T08:51:52Z</updated>
    <category term="merb" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/411750791/installing-merb-with-thor" rel="alternate" type="text/html" />
    <title>Installing merb with thor</title>
<content type="html">&lt;p&gt;&lt;strong&gt;Update (22 October):&lt;/strong&gt; Things move &lt;strong&gt;very&lt;/strong&gt; fast around here – the &lt;code&gt;merb.thor&lt;/code&gt; file has been overhauled and now all you have to do to get the latest edge is download a single .thor file and run one command.&lt;/p&gt;

&lt;p&gt;Matt Aimonetti wrote a neat post on &lt;a href="http://merbist.com/2008/10/04/get-on-merb-edge-pre-10/"&gt;installing merb edge with thor&lt;/a&gt;. &lt;a href="http://yehudakatz.com/2008/05/12/by-thors-hammer/"&gt;Thor&lt;/a&gt; seems to have become the defacto technique for installing merb edge these days, and I’m going to give it a go in preference to &lt;a href="/2008/7/14/merb-and-datamapper-on-the-edge"&gt;installing merb with sake&lt;/a&gt;, as I had been doing.&lt;/p&gt;

&lt;p&gt;Since Matt wrote his article the &lt;code&gt;merb.thor&lt;/code&gt; file underwent a serious overhaul during the sprint at MerbCamp – what you need to do these days is quite a bit simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;curl -L http://merbivore.com/merb.thor &amp;gt; merb.thor
sudo thor merb:stack:install --edge
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The source code for all the Merb gems will be checked out into a directory called &lt;code&gt;./src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To get the full low down on how to use Thor with Merb, head over to the &lt;a href="http://wiki.merbivore.com/howto/installation/thor"&gt;Thor Howto&lt;/a&gt; on the excellent new &lt;a href="http://wiki.merbivore.com/"&gt;Merb wiki&lt;/a&gt;.&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/10/5/installing-merb-with-thor</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-10-02:143</id>
    <published>2008-10-02T22:24:00Z</published>
    <updated>2008-10-02T22:26:57Z</updated>
    <category term="mac" />
    <category term="merb" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/409688306/building-do_mysql-on-a-64-bit-mac" rel="alternate" type="text/html" />
    <title>Building do_mysql on a 64-bit Mac</title>
<summary type="html">&lt;p&gt;Whilst &lt;a href="/2008/7/14/merb-and-datamapper-on-the-edge"&gt;installing merb with edgy&lt;/a&gt; I’ve had run into some trouble building the &lt;code&gt;do_mysql&lt;/code&gt; gem on my Macbook Pro. It’s a 64-bit machine, so I installed the 64-bit version of MySQL, and that was my first mistake…&lt;/p&gt;</summary><content type="html">&lt;p&gt;Whilst &lt;a href="/2008/7/14/merb-and-datamapper-on-the-edge"&gt;installing merb with edgy&lt;/a&gt; I’ve had run into some trouble building the &lt;code&gt;do_mysql&lt;/code&gt; gem on my Macbook Pro. It’s a 64-bit machine, so I installed the 64-bit version of MySQL, and that was my first mistake…&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;do_mysql&lt;/code&gt; gem installed fine. I didn’t realise there was a problem until I tried to run some migrations in a blank database:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ merb -i
 ~ Loaded DEVELOPMENT Environment...
 ~ loading gem 'dm-validations' ...
 ~ loading gem 'merb_datamapper' ...
 ~ loading gem 'merb-haml' ...
 ~ loading gem 'dm-core' ...
 ~ Merb::Orms::DataMapper::Connect block.
 ~ Connecting to database...
 ~ Checking if we need to use DataMapper sessions
 ~ Merb::Orms::DataMapper::Connect complete
 ~ Parent pid: 9932
 ~ Compiling routes...
&amp;gt;&amp;gt; Post.auto_migrate!
dyld: lazy symbol binding failed: Symbol not found: _mysql_init
  Referenced from: /Library/Ruby/Gems/1.8/gems/do_mysql-0.9.6/lib/do_mysql_ext.bundle
  Expected in: dynamic lookup

dyld: Symbol not found: _mysql_init
  Referenced from: /Library/Ruby/Gems/1.8/gems/do_mysql-0.9.6/lib/do_mysql_ext.bundle
  Expected in: dynamic lookup
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh dear. I did some Googling, and found a few articles from people having similar problems (e.g. Ben Novakovic, who had &lt;a href="http://blog.bmn.name/2008/02/issues-with-mysql-27-gem/"&gt;problems with the mysql gem&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;It turns out that the gems cannot be compiled properly against a 64-bit version of MySQL, as they don’t take proper notice of the output of &lt;code&gt;mysql_config&lt;/code&gt;. Chris Cruft &lt;a href="http://cho.hapgoods.com/wordpress/?p=158"&gt;investigated the problem&lt;/a&gt; and ended up working around it by using the 32-bit version.&lt;/p&gt;

&lt;p&gt;Setting the &lt;code&gt;ARCHFLAGS&lt;/code&gt; environment variable (as suggested in Chris’s article) to the output of &lt;code&gt;mysql_config --cflags&lt;/code&gt; didn’t work for me either, so I’ve gone for the same solution as Chris and installed the &lt;a href="http://dev.mysql.com/downloads/mysql/5.0.html#macosx-dmg"&gt;i386 build of MySQL&lt;/a&gt;. The &lt;code&gt;do_mysql&lt;/code&gt; gem now works fine.&lt;/p&gt;

&lt;p&gt;If you check the comments on &lt;a href="http://cho.hapgoods.com/wordpress/?p=158"&gt;Chris’s post&lt;/a&gt; you’ll see that some people have managed to get the &lt;code&gt;mysql&lt;/code&gt; gem to build properly against 64-bit MySQL. I’ve opted not to bother trying to shovel lots of command line switches at the problem because I’m &lt;a href="/2008/7/14/merb-and-datamapper-on-the-edge"&gt;installing merb with edgy&lt;/a&gt;, and am getting by fine with the 32-bit version for now…&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/10/2/building-do_mysql-on-a-64-bit-mac</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-10-02:142</id>
    <published>2008-10-02T19:59:00Z</published>
    <updated>2008-10-02T20:27:04Z</updated>
    <category term="javascript" />
    <category term="mac" />
    <category term="web" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/409599604/debugging-javascript-in-webkit" rel="alternate" type="text/html" />
    <title>Debugging JavaScript in WebKit</title>
<summary type="html">&lt;p&gt;If you do much web development you’re probably a big fan of the &lt;a href="http://getfirebug.com"&gt;Firebug&lt;/a&gt; plugin for Firefox. It really is a rare gem in the web developer’s arsenal. When I’m not developing I prefer to use &lt;a href="http://www.apple.com/safari/"&gt;Safari&lt;/a&gt; – it seems faster and leaner, so I often find that I’ve got both browsers open at once.&lt;/p&gt;

&lt;p&gt;A couple of days ago something rather fantastic happened – Safari got a makeover…&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you do much web development you’re probably a big fan of the &lt;a href="http://getfirebug.com"&gt;Firebug&lt;/a&gt; plugin for Firefox. It really is a rare gem in the web developer’s arsenal. When I’m not developing I prefer to use &lt;a href="http://www.apple.com/safari/"&gt;Safari&lt;/a&gt; – it seems faster and leaner, so I often find that I’ve got both browsers open at once.&lt;/p&gt;

&lt;p&gt;A couple of days ago something rather fantastic happened – Safari got a makeover.&lt;/p&gt;

&lt;p&gt;More specifically, the &lt;a href="http://webkit.org/blog/197/web-inspector-redesign/"&gt;WebKit Web Inspector got a makeover&lt;/a&gt;, and now seems to be a viable competitor to Firebug. Here’s a quick screenshot of the debugger in action:&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/webkit-debugger.png" alt="Screenshot of the WebKit JavaScript debugger" /&gt;&lt;/p&gt;

&lt;p&gt;I’m also a big fan of the JavaScript code completion in the console. Here’s an example, with the code completion reminding me of the name of Prototype’s &lt;code&gt;_getElementsByXPath()&lt;/code&gt; function (which I rarely manage to type correctly in Firebug, but find very useful for debugging my XPath statements):&lt;/p&gt;

&lt;p&gt;&lt;img src="/assets/webkit-code-completion.png" alt="Screenshot of the WebKit's JavaScript code completion" /&gt;&lt;/p&gt;

&lt;p&gt;You can see from the position of the cursor that I’ve typed &lt;code&gt;document._get&lt;/code&gt;, and that Web Inspector is suggesting “ElementsByXPath”. Pressing tab cycles between matching names, and the right cursor key completes the function, moving the cursor to the end of the line. It’s the little things…&lt;/p&gt;

&lt;p&gt;You can open the console at any time by pressing Esc (or clicking the second icon from the left at the bottom of the Web Inspector window).&lt;/p&gt;

&lt;p&gt;There are loads more features. Check out the &lt;a href="http://webkit.org/blog/197/web-inspector-redesign/"&gt;WebKit blog post that covers the redesign&lt;/a&gt;, or get yourself over to the &lt;a href="http://nightly.webkit.org/"&gt;WebKit nightly build page&lt;/a&gt; and download a copy (it doesn’t affect your existing installation of Safari, but can function as a drop in replacement, so there’s no risk and you can flip between them at will).&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/10/2/debugging-javascript-in-webkit</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-09-13:131</id>
    <published>2008-09-13T06:22:00Z</published>
    <updated>2008-09-13T12:37:45Z</updated>
    <category term="rails" />
    <category term="sysadmin" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/391328753/configure-the-expires-header-on-your-rails-site-with-nginx" rel="alternate" type="text/html" />
    <title>Configure the Expires header for Rails under nginx</title>
<summary type="html">&lt;p&gt;The images, CSS and JavaScript files served up by your &lt;a href="http://rubyonrails.org/"&gt;Rails&lt;/a&gt; application can usually be cached by the web browser, rather than being downloaded (or checked) every time the browser loads a page on your site. For a properly configured site the net effect is faster page load times and a vastly improved user experience. Rails gives you some help here, but it doesn’t happen automatically – you need to configure your web server to set the HTTP Expires header. This article explains how to configure the expires header for a Rails application running behind the &lt;a href="http://wiki.codemongers.com/"&gt;nginx HTTP proxy server&lt;/a&gt;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;The images, CSS and JavaScript files served up by your &lt;a href="http://rubyonrails.org/"&gt;Rails&lt;/a&gt; application can usually be cached by the web browser, rather than being downloaded (or checked) every time the browser loads a page on your site. For a properly configured site the net effect is faster page load times and a vastly improved user experience. Rails gives you some help here, but it doesn’t happen automatically – you need to configure your web server to set the HTTP Expires header. This article explains how to configure the expires header for a Rails application running behind the &lt;a href="http://www.codemongers.com/"&gt;nginx HTTP proxy server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nginx is popular amongst Rails developers for fronting a cluster of mongrel web servers. I’ll not say much more about it, on the assumption that this article probably won’t be of much interest to you if you’re not already using it.&lt;/p&gt;

&lt;h2&gt;So how do we speed your Rails site up?&lt;/h2&gt;

&lt;p&gt;When a web browser downloads a web page for the first time it also retrieves copies of the images, CSS and JavaScript files that are required to display it. On subsequent requests it will typically make a new connection to the web server to verify whether each of these files has been updated. When you know that the files won’t have changed you can gain a significant performance increase by telling the browser when it first downloads the file that it doesn’t need to check it again. More information on the Expires header (and other great performance enhancing tips) can be found amongst Yahoo’s &lt;a href="http://developer.yahoo.com/performance/rules.html#expires"&gt;Best Practices for Speeding Up Your Web Site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Files that don’t change between requests are known in the Rails community as “static assets”. When running in production mode your Rails application will append all URLs for static assets with the file’s timestamp (in seconds since the 1 January 1970). Here’s an example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://effectif.com/stylesheets/blog.css?1221178271
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we were to edit the file and redeploy the application the timestamp would be updated, and the browser would realise that it needed to download a new copy of the file.&lt;/p&gt;

&lt;p&gt;The Rails &lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html"&gt;documentation for AssetTagHelper&lt;/a&gt; covers how to configure a far future expires header under Apache (scroll down to the section entitled “Using asset timestamps”).&lt;/p&gt;

&lt;p&gt;The equivalent nginx configuration looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ($request_uri ~* ".(ico|css|js|gif|jpe?g|png)\?[0-9]+$") {
    expires max;
    break;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that we’re matching suitable file types, but only setting the expires header for files that have a timestamp appended.&lt;/p&gt;

&lt;p&gt;Here’s the configuration again, in the context of a &lt;code&gt;location&lt;/code&gt; directive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;location / {
    root /var/apps/myapp/current/public;
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect false;

    if ($request_uri ~* ".(ico|css|js|gif|jpe?g|png)\?[0-9]+$") {
        expires max;
        break;
    }
    if (-f $request_filename) {
        break;
    }
    if (-f $request_filename/index.html) {
        rewrite (.*) $1/index.html break;
    }
    if (-f $request_filename.html) {
        rewrite (.*) $1.html break;
    }

    proxy_pass http://mymongrels;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Testing your configuration&lt;/h2&gt;

&lt;p&gt;It’s all well and good sticking the config in nginx and restarting it, but it’s nice to know that the stuff works, right? If you’re not already using it, get a copy of &lt;a href="http://www.getfirefox.com/"&gt;Firefox&lt;/a&gt; and install &lt;a href="http://getfirebug.com/"&gt;Firebug&lt;/a&gt;. Then install Yahoo’s &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; plugin for Firebug.&lt;/p&gt;

&lt;p&gt;I recommend that you read Yahoo’s &lt;a href="http://developer.yahoo.com/yslow/"&gt;introduction to YSlow&lt;/a&gt; to learn how to use it. You can check whether the expires header is set for all the assets required by your web page using the Components view, a screenshot of which I’ve cheekily purloined here:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://us.i1.yimg.com/us.yimg.com/i/rt/yslow/compsview.png" alt="YSlow copmonents view, showing the value of the expires header" /&gt;&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/9/13/configure-the-expires-header-on-your-rails-site-with-nginx</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-06-18:67</id>
    <published>2008-06-18T22:15:00Z</published>
    <updated>2008-06-19T06:38:18Z</updated>
    <category term="erlang" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/314984833/learning-erlang-screencasts" rel="alternate" type="text/html" />
    <title>Learning Erlang with the Pragmatic Programmer Screencasts</title>
<summary type="html">&lt;p&gt;I’ve been meaning to get around to playing with &lt;a href="http://www.erlang.org/" title="Erlang"&gt;Erlang&lt;/a&gt; for a while now. Tonight I set aside 30 minutes to watch the first of the Pragmatic Programmer’s Erlang Screencasts by Kevin Smith: &lt;a href="http://pragprog.com/screencasts/v-kserl/erlang-by-example" title="The Pragmatic Bookshelf | Erlang By Example"&gt;Erlang By Example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each screencast is very reasonably priced at $5 a piece. I bought the first one, in which you learn how to build a simple chat system. I downloaded it immediately, excited to think that in only 30 minutes time I’d know lots more about Erlang than I did when I woke up this morning.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I’ve been meaning to get around to playing with &lt;a href="http://www.erlang.org/" title="Erlang"&gt;Erlang&lt;/a&gt; for a while now. Tonight I set aside 30 minutes to watch the first of the Pragmatic Programmer’s Erlang Screencasts by Kevin Smith: &lt;a href="http://pragprog.com/screencasts/v-kserl/erlang-by-example" title="The Pragmatic Bookshelf | Erlang By Example"&gt;Erlang By Example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each screencast is very reasonably priced at $5 a piece. I bought the first one, in which you learn how to build a simple online chat system (see &lt;a href="http://screencasts.pragprog.com/v-kserl-intro.mov"&gt;the introductory video&lt;/a&gt; for an overview of what’s covered in the entire series). I downloaded it immediately, excited to think that in only 30 minutes time I’d know lots more about Erlang than I did when I woke up this morning.&lt;/p&gt;

&lt;h2&gt;Installing Erlang&lt;/h2&gt;

&lt;p&gt;While the video was downloading I kicked off the installation of Erlang on my Mac with &lt;a href="http://www.macports.org/" title="The MacPorts Project -- Home"&gt;MacPorts&lt;/a&gt;…&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo port install -d erlang
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and grabbed a copy of the Erlang TextMate bundle:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd ~/Library/Application\ Support/TextMate/Bundles
$ svn co https://macromates.com/svn/Bundles/trunk/Bundles/Erlang.tmbundle
$ osascript -e 'tell app "TextMate" to reload bundles'
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Following Along&lt;/h2&gt;

&lt;p&gt;If you’ve never done any Erlang at all (and to all intents and purposes, I hadn’t) then you’ll see quite a bit of new syntax during this screencast. It won’t all be explained to you straight away, but don’t worry about that as it doesn’t detract from what’s going on.&lt;/p&gt;

&lt;p&gt;Kevin edits his code in Emacs and compiles it with some magic incantation using an Erlang interpreter that is running in an Emacs buffer. It seems to be assumed that when you start watching the screencast you already know how to compile a code module. Worry not; if you’re trying to run the examples in a terminal, you should be able to get by with something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ erl
Erlang (BEAM) emulator version 5.6.2 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.6.2  (abort with ^G)
1&amp;gt; c('message_router').
{ok,message_router}
2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;“c” means “compile”. Note the “.” character, which is used as a terminator in Erlang (it’s strange that this should seem noteworthy, given that this is exactly how we use it in English!). Incidentally, if you’re an Emacs fan then Kevin has written up his &lt;a href="http://weblog.hypotheticalabs.com/?p=265"&gt;Emacs configuration&lt;/a&gt; on his blog.&lt;/p&gt;

&lt;p&gt;Kevin does a good job of giving you a the flavour of concurrent programming in Erlang. Concentrating on the syntax would have distracted from the overall message, without contributing much to your understanding (and if you really must know the syntax, there’s plenty of &lt;a href="http://www.erlang.org/doc/"&gt;Erlang documentation&lt;/a&gt; that will fill in the gaps).&lt;/p&gt;

&lt;p&gt;Once the simple chat system was put together the code was refactored. While recompiling my edits and fixing my typos I picked up some useful tips on using the interactive interpreter.&lt;/p&gt;

&lt;p&gt;So in summary, I enjoyed it. I’m a long way from being able to claim that I know Erlang, but I know hell of a lot more about it than I did half an hour ago, and you can’t say fairer than that! For $5 a throw, the screencasts are a bargain.&lt;/p&gt;

&lt;h2&gt;Useful Links&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="http://pragprog.com/screencasts/v-kserl/erlang-by-example" title="The Pragmatic Bookshelf | Erlang By Example"&gt;Erlang By Example Screencasts&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.erlang.org/starting.html" title="Getting started"&gt;Getting Started with Erlang&lt;/a&gt; (also available as a &lt;a href="http://www.erlang.org/doc/pdf/getting_started.pdf" title="Getting Started with Erlang"&gt;PDF&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://weblog.hypotheticalabs.com/" title="Hypothetical Labs"&gt;Kevin Smith’s blog&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content>  <feedburner:origLink>http://effectif.com/2008/6/18/learning-erlang-screencasts</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-05-24:49</id>
    <published>2008-05-24T11:05:00Z</published>
    <updated>2008-05-27T09:13:03Z</updated>
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/297169560/database-yml-should-be-checked-in" rel="alternate" type="text/html" />
    <title>database.yml should be checked in</title>
<summary type="html">&lt;p&gt;It’s generally acknowledged to be good practice to keep your production &lt;code&gt;database.yml&lt;/code&gt; file away from your version control system. Why? So that people snooping around your version control system don’t find your database password. There are plenty of examples out there that tell you how to achieve this with &lt;a href="http://capify.org"&gt;Capistrano&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m talking about the &lt;code&gt;database.yml&lt;/code&gt; file that you use during development.&lt;/p&gt;</summary><content type="html">&lt;p&gt;It’s generally acknowledged to be good practice to keep your production &lt;code&gt;database.yml&lt;/code&gt; file away from your version control system. Why? So that people snooping around your version control system don’t find your database password. There are plenty of examples out there that tell you how to achieve this with &lt;a href="http://capify.org"&gt;Capistrano&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When I say that &lt;code&gt;database.yml&lt;/code&gt; should be checked in, I’m talking the version that you use during development.&lt;/p&gt;

&lt;p&gt;Teams often resist sharing database config files so they can keep their individual database passwords private and specify operating system specific settings (such as the location of MySQL’s socket file).&lt;/p&gt;

&lt;p&gt;Can you share configuration between different developers? A couple of approaches spring to mind.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don’t store &lt;code&gt;database.yml&lt;/code&gt; in version control, but create &lt;code&gt;database.yml.example&lt;/code&gt; instead. Force each developer to edit it themselves when they check out the code.&lt;/li&gt;
&lt;li&gt;Persuade your team mates to use the same password and check that in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neither is satisfactory. When I check my code out I expect it to just work, and I’m sure as hell not going to give anybody who can access the source a free run at my laptop’s database.&lt;/p&gt;

&lt;p&gt;Read on for my solution.&lt;/p&gt;

&lt;p&gt;So how do you check in &lt;code&gt;database.yml&lt;/code&gt; without storing your password in version control? I’m using MySQL at the moment. As we’ve &lt;a href="/2008/3/29/opening-ruby-gems-in-textmate"&gt;already established&lt;/a&gt;, I’m a lazy &lt;a href="/tags/git"&gt;git&lt;/a&gt;, so I hate having to specify a password when I connect to MySQL. I’ve set my local database password in the &lt;code&gt;~/.my.cnf&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat ~/.my.cnf
[mysql]
user = root
password = gumo4Gum
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s a good idea to set the permissions on that file so that only you can read it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chmod 600 ~/.my.cnf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now I can just connect without any trouble. Neat.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mysql myapp_development
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.0.45-Debian_1ubuntu3.3-log Debian etch distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once you’ve gone to the trouble to make it easy to login to MySQL, why not let Rails connect using the same settings when it starts up?&lt;/p&gt;

&lt;p&gt;This is how I’ve been doing it (“Oh my God! He’s used Python!”):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;%
def get_mysql_password
  script =&amp;lt;&amp;lt;EOF
import ConfigParser
parser = ConfigParser.SafeConfigParser()
parser.read("#{ENV['HOME']}/.my.cnf")
print parser.get("mysql", "password")
EOF
  %x(python -c '#{script}')
end
%&amp;gt;

mysql: &amp;amp;mysql
  adapter: mysql
  username: root
  password: &amp;lt;%= get_mysql_password %&amp;gt;
  host: localhost
  socket: &amp;lt;%= [
    '/var/lib/mysql/mysql.sock',
    '/var/run/mysqld/mysqld.sock',
    '/tmp/mysqld.sock',
    '/tmp/mysql.sock',
  ].detect { |socket| File.exist?(socket) } %&amp;gt;

development:
  database: myapp_development
  &amp;lt;&amp;lt;: *mysql

test: &amp;amp;test
  database: myapp_test
  &amp;lt;&amp;lt;: *mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Before I explain the Python, note the sneaky socket trick that allows Rails to try lots of different locations for MySQL’s Unix socket—it allows you to develop the same app on a Mac, or various flavours of Linux/BSD, without editing &lt;code&gt;database.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So then. This Python code. I suspect there’s a rather good way of doing it in Ruby, but when I first started developing with Rails I’d just spent five years doing Python full time, and I knew that the &lt;a href="http://docs.python.org/lib/module-ConfigParser.html" title="9.2 ConfigParser -- Configuration file parser"&gt;ConfigParser module&lt;/a&gt; was designed to read files like &lt;code&gt;~/.my.cnf&lt;/code&gt;. So I used it, and it stuck.&lt;/p&gt;

&lt;h3&gt;Send me improvements!&lt;/h3&gt;

&lt;p&gt;How would you do it?&lt;/p&gt;

&lt;p&gt;Can you write a neat snippet of Ruby that achieves the same thing as the Python code?&lt;/p&gt;

&lt;p&gt;If anybody knows a way to make this trick work with &lt;a href="http://www.merbivore.com/" title="Merb | Looking for a hacker's framework?"&gt;Merb&lt;/a&gt; I’d love to hear it. Last time I tried, Merb wasn’t processing the database config file with &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/" title="erb: Ruby Standard Library Documentation"&gt;erb&lt;/a&gt;…&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/5/24/database-yml-should-be-checked-in</feedburner:origLink></entry>
  <entry xml:base="http://effectif.com/">
    <author>
      <name>graham</name>
    </author>
    <id>tag:effectif.com,2008-04-24:27</id>
    <published>2008-04-24T23:13:00Z</published>
    <updated>2008-05-24T11:06:46Z</updated>
    <category term="automation" />
    <category term="git" />
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/effectif-development/~3/277243659/easy-git-svn-for-rails" rel="alternate" type="text/html" />
    <title>Easy git-svn for Rails (or "git-me-up")</title>
<summary type="html">&lt;p&gt;I’ve been trying to persuade &lt;code&gt;git-svn&lt;/code&gt; to work properly with Rails plugins that have been installed via &lt;code&gt;svn:externals&lt;/code&gt;. Whilst working out how to do it I stumbled across several great articles, but I couldn’t get any of the solutions presented to work perfectly. &lt;a href="http://blog.alieniloquent.com/2008/03/08/git-svn-with-svnexternals/" title="Alieniloquent: Blog"&gt;Samuel Tesla’s article&lt;/a&gt; is especially informative, but for a long time I couldn’t stop &lt;code&gt;git-svn&lt;/code&gt; from trying to commit Git metadata back into my Subversion repository…&lt;/p&gt;

&lt;p&gt;After a bit of head scratching I got it sorted, and wrapped the process up in a little utility called &lt;a href="/2008/4/24/easy-git-svn-for-rails" title="Easy git-svn for Rails (or git-me-up)"&gt;git-me-up&lt;/a&gt;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;I’ve been trying to persuade &lt;code&gt;git-svn&lt;/code&gt; to work properly with Rails plugins that have been installed via &lt;code&gt;svn:externals&lt;/code&gt;. Whilst working out how to do it I stumbled across several great articles, but I couldn’t get any of the solutions presented to work perfectly. &lt;a href="http://blog.alieniloquent.com/2008/03/08/git-svn-with-svnexternals/" title="Alieniloquent: Blog"&gt;Samuel Tesla’s article&lt;/a&gt; is especially informative, but for a long time I couldn’t stop &lt;code&gt;git-svn&lt;/code&gt; from trying to commit Git metadata back into my Subversion repository…&lt;/p&gt;

&lt;p&gt;After a bit of head scratching I got it sorted, and wrapped the process up in a little utility called &lt;a href="/2008/4/24/easy-git-svn-for-rails" title="Easy git-svn for Rails (or git-me-up)"&gt;git-me-up&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;What does git-me-up do?&lt;/h2&gt;

&lt;p&gt;In a nutshell, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clones the latest version of the source in your Subversion repository into a new local Git repository. It doesn’t import any history for performance reasons.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recreates empty directories that &lt;code&gt;git-svn&lt;/code&gt; ignored (but that your app might need).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Converts any &lt;code&gt;svn:ignore&lt;/code&gt; Subversion properties into entries in the &lt;code&gt;.git/info/exclude&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checks for Rails plugins installed via &lt;code&gt;svn:externals&lt;/code&gt; and clones them into their own git repositories. Each external plugin is then symlinked into &lt;code&gt;vendor/plugins&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creates a local working branch.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words, it takes all the hard work out of creating a local Git repository that points at your Subversion repo.&lt;/p&gt;

&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;You need &lt;code&gt;git-svn&lt;/code&gt; installed first. On a Mac, install &lt;a href="http://www.macports.org/" title="The MacPorts Project -- Home"&gt;MacPorts&lt;/a&gt; and then type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo port install -u git-core +svn +bash_completion
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the package has finished building run these commands to benefit from bash completion:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cp /opt/local/etc/bash_completion.d/git ~/.git-bash-completion.sh
$ echo '[ -f ~/.git-bash-completion.sh ] &amp;amp;&amp;amp; . ~/.git-bash-completion.sh' \
    &amp;gt;&amp;gt; ~/.bashrc
$ . ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On Ubuntu Linux:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo apt-get install git-svn
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Installing git-me-up&lt;/h3&gt;

&lt;p&gt;The source is hosted on &lt;a href="http://github.com/gma/git-me-up/tree" title="gma's git-me-up at master &amp;amp;mdash; GitHub"&gt;GitHub&lt;/a&gt;. You can either &lt;a href="http://github.com/gma/git-me-up/tarball/master"&gt;download the tar ball&lt;/a&gt; or pull the source with &lt;code&gt;git&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/gma/git-me-up.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;Makefile&lt;/code&gt; will install it into &lt;code&gt;/usr/local/bin&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd git-me-up
$ sudo make install
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Using git-me-up&lt;/h2&gt;

&lt;p&gt;This is pretty easy. Let’s start with an empty directory so you can see what gets created:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ pwd
/home/graham/test
$ git-me-up https://myhost.com/path/to/myproject/trunk myproject
git-me-up: finding latest revision of https://myhost.com/path/to/myproject/trunk
git-me-up: creating git repository in /home/graham/test/myproject
git-me-up: making empty directory: app/views/comments
git-me-up: making empty directory: app/views/pages
git-me-up: making empty directory: components
git-me-up: making empty directory: log
git-me-up: making empty directory: test/mocks/development
git-me-up: making empty directory: test/mocks/test
git-me-up: making empty directory: tmp/cache
git-me-up: making empty directory: tmp/pids
git-me-up: making empty directory: tmp/sessions
git-me-up: making empty directory: tmp/sockets
git-me-up: setting ignored files from subversion (this can take a while)
git-me-up: checking for plugins installed with svn:externals
git-me-up: finding latest revision of https://myhost.com/path/to/plugin/trunk
git-me-up: creating git repository in /home/graham/test/myproject/../plugins/site_theme
git-me-up: setting ignored files from subversion (this can take a while)
git-me-up: symlinking site_theme into myproject/vendor/plugins
git-me-up: creating 'work' branch on /home/graham/test/myproject
Switched to a new branch "work"
$ ls
myproject/  plugins/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you’re running on a Mac you may see this error message part way through the output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;No such file or directory: PROPFIND request failed on '/app': Could not open the requested SVN filesystem at /opt/local/bin/git-svn line 1872
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It appears as though the &lt;code&gt;git svn show-ignore&lt;/code&gt; command (using the current version of git from MacPorts–version 1.5.4.4) doesn’t work on my Mac. If you see this too don’t worry about it; it will only mean that Git doesn’t know which files you’ve chosen to ignore in your Subversion repo.&lt;/p&gt;

&lt;p&gt;Now we’re ready to use our new Git repo. Note that we’ve got a work branch by default:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd myproject
$ git branch
  master
* work
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to call the branch something else, set the &lt;code&gt;BRANCH&lt;/code&gt; environment variable before you run &lt;code&gt;git-me-up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Samuel &lt;a href="http://blog.alieniloquent.com/2008/03/08/git-svn-with-svnexternals/" title="Alieniloquent: Blog"&gt;recommends a good work flow&lt;/a&gt; for working with Subversion (skip down to “Step Five: Using this thing”) . When you want to update your working branch from subversion, try this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git checkout master  # switches to local master branch
$ git svn rebase       # pulls recent changes from subversion
$ git checkout work    # switches to local work branch
$ git rebase master    # pulls recent changes to master into work
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There’s a good description of &lt;a href="http://jbowes.dangerouslyinc.com/2007/01/26/git-rebase-keeping-your-branches-current/" title="James Bowes &amp;amp;rsaquo; git rebase: keeping your branches current"&gt;why rebase is so great&lt;/a&gt; on James Bowes’s blog.&lt;/p&gt;

&lt;p&gt;When you want to commit changes back into subversion:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git checkout work    # you were probably there already
... run your tests ...
$ git commit -a -m "Blah blah blah..."
$ git checkout master
$ git merge work
$ git svn rebase       # checks for fresh changes in subversion
... run tests again if rebase pulled any changes ...
$ git svn dcommit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make sure that you use &lt;code&gt;git svn rebase&lt;/code&gt; to pull upstream changes into your &lt;code&gt;master&lt;/code&gt; branch before you check in.&lt;/p&gt;

&lt;h3&gt;What git-me-up does with svn:externals plugins&lt;/h3&gt;

&lt;p&gt;The Rails app that I cloned above has a plugin that is installed via &lt;code&gt;svn:externals&lt;/code&gt; called &lt;code&gt;site_theme&lt;/code&gt;. I usually use &lt;a href="http://piston.rubyforge.org/" title="Piston ~ Easy Vendor Branch Management"&gt;piston&lt;/a&gt; or &lt;a href="http://evil.che.lu/projects/braid" title="evil.che.lu - projects - braid"&gt;braid&lt;/a&gt; to install Rails plugins, but when the plugin is stored on my own servers I’ve always preferred to pull in the source directly by setting the &lt;code&gt;svn:externals&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;I initially tried to convert &lt;code&gt;svn:externals&lt;/code&gt; into Git submodules, but it didn’t work well. No matter what I tried, I couldn’t persuade &lt;code&gt;git-svn&lt;/code&gt; to ignore the submodule when committing back to Subversion. It turns out that it’s easy to achieve with a symbolic link.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git-me-up&lt;/code&gt; cloned the &lt;code&gt;site-theme&lt;/code&gt; plugin into a Git repository, then made it available with a symbolic link:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ ls
myproject/  plugins/
$ ls plugins/
site_theme/
$ ls -l myproject/vendor/plugins/ | grep site_theme
lrwxrwxrwx  1 graham development   32 Apr 24 18:41 site_theme -&amp;gt; ../../../plugins/site_theme/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To avoid checking the symlink into Subversion, &lt;code&gt;git-me-up&lt;/code&gt; told Git to ignore it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ grep site_theme myproject/.git/info/exclude
/vendor/plugins/site_theme
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The result is a trouble free alternative to submodules that allows you to integrate Git with &lt;code&gt;svn:externals&lt;/code&gt; in your Subversion repo.&lt;/p&gt;</content>  <feedburner:origLink>http://effectif.com/2008/4/24/easy-git-svn-for-rails</feedburner:origLink></entry>
</feed>
