<?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>jlaine.net - Home</title>
  <id>tag:jlaine.net,2008:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  
  <link href="http://jlaine.net/" rel="alternate" type="text/html" />
  <updated>2008-10-04T09:59:31Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/jlainenet" type="application/atom+xml" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-10-04:2858</id>
    <published>2008-10-04T09:58:00Z</published>
    <updated>2008-10-04T09:59:31Z</updated>
    <category term="life" />
    <category term="launch" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/411004372/build-your-green-home" rel="alternate" type="text/html" />
    <title>Build your green home</title>
<content type="html">
            &lt;p&gt;The “summer project” for &lt;a href="http://innovatebig.com/"&gt;Rod&lt;/a&gt;, me and &lt;a href="http://www.linkedin.com/in/lorenbaxter"&gt;Loren&lt;/a&gt;, &lt;a href="http://ecohomeresource.com/"&gt;EcoHomeResource&lt;/a&gt; is now live. The site is a hub of information and news for everyone wanting to build a green home or to make their current apartments more eco-friendly.&lt;/p&gt;


	&lt;p&gt;My dream has for quite some time (since reading &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;amp;#38;location=http%3A%2F%2Fwww.amazon.com%2FNatural-Capitalism-Creating-Industrial-Revolution%2Fdp%2F0316353000%2F&amp;amp;#38;tag=jlainenet-20&amp;amp;#38;linkCode=ur2&amp;amp;#38;camp=1789&amp;amp;#38;creative=9325"&gt;Natural Capitalism&lt;/a&gt; and &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;amp;#38;location=http%3A%2F%2Fwww.amazon.com%2FCradle-Remaking-Way-Make-Things%2Fdp%2F0865475873%2F&amp;amp;#38;tag=jlainenet-20&amp;amp;#38;linkCode=ur2&amp;amp;#38;camp=1789&amp;amp;#38;creative=9325"&gt;Cradle to Cradle&lt;/a&gt;, to be exact) been to build us a &lt;a href="http://www.redferret.net/?p=8707"&gt;carbon-positive home&lt;/a&gt;, so the project has been spot-on for me.&lt;/p&gt;


	&lt;p&gt;The actual blog/CMS is using Movable Type but the backend database for products and companies is built on &lt;a href="http://merbivore.org/"&gt;Merb&lt;/a&gt; and &lt;a href="http://datamapper.org/"&gt;Datamapper&lt;/a&gt;. The integration of the platforms has definitely been a challenge but the decision to use separate pieces loosely joined by web services gives us a chance to reuse the database easily in the future if need be.&lt;/p&gt;


	&lt;p&gt;Playing around with new tools such as Merb, DM and jQuery (and, err… perl) has been really educational and fun. The project also gave us a chance to help hone open source products such as Datamapper even further.&lt;/p&gt;


	&lt;p&gt;If you’re &lt;a href="http://ecohomeresource.com/2008/09/cooling-heating-and-insulation.html"&gt;building a new house&lt;/a&gt;, &lt;a href="http://ecohomeresource.com/2008/09/photovoltaic-electricity-produ.html"&gt;renovating your existing home&lt;/a&gt;, or just looking for &lt;a href="http://ecohomeresource.com/2008/09/how-to-light-efficiently.html"&gt;tips to be more eco-efficient with what you already got&lt;/a&gt;, go and check out &lt;a href="http://ecohomeresource.com/"&gt;EcoHomeResource&lt;/a&gt;! You won’t walk out empty-handed.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=kZPmM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=kZPmM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=P2fvM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=P2fvM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/10/4/build-your-green-home</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-10-03:2857</id>
    <published>2008-10-03T11:58:00Z</published>
    <updated>2008-10-03T12:00:41Z</updated>
    <category term="geeky" />
    <category term="life" />
    <category term="life" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/410201701/unplugged" rel="alternate" type="text/html" />
    <title>Unplugged</title>
<content type="html">
            &lt;p&gt;Early last year I was shopping for in-canal earplugs because I wanted a pair of reasonably sound-isolating plugs that &lt;strong&gt;stay in my ears&lt;/strong&gt;, even when running or biking. The standard iPod plugs are not meant for me. Even if I could stand the sound quality (which I don’t), all I have to do is to lean my head on one side and the earplug drops on the ground. The same goes pretty much for all the “normal” earplugs, thus I needed more drastic measures.&lt;/p&gt;


	&lt;p&gt;My first idea was to buy a pair of &lt;a href="http://www.amazon.com/Sennheiser-CX300-B-Earbuds-Black/dp/B000E6G9RI/"&gt;Sennheiser &lt;span class="caps"&gt;CX300&lt;/span&gt;&lt;/a&gt; plugs, cause I’d had a couple of different Sennheisers in the past and been fairly happy with all of them. &lt;a href="http://imaj.es/"&gt;James&lt;/a&gt; proposed that I’d get &lt;a href="http://www.amazon.com/Shure-E2c-n-Sound-Isolating-Earphones/dp/B000E5GKW8"&gt;Shure &lt;span class="caps"&gt;E2C&lt;/span&gt;’s&lt;/a&gt; instead; he’d used both and thought the Shures were vastly superior, sitting tighter in the ear and being better sound-isolating. I believed him and ordered a pair from Amazon.co.uk, which he then brought to our Caboose meetup in Paris.&lt;/p&gt;


	&lt;p&gt;In general I’ve been very happy with the earphones. They sound great, pretty much as good as my &lt;a href="http://www.amazon.com/Sennheiser-PX200-Collapsible-High-Performance-Headphones/dp/B000089GN4/"&gt;Sennheiser &lt;span class="caps"&gt;PX200&lt;/span&gt;&lt;/a&gt; headphones. And most of all, after you find the best fitting sleeve for your ear (they come with a selection of sleeves), they sit in your ear like plague.&lt;/p&gt;


	&lt;p&gt;However, while the Shures have worked really well in sometimes fairly rough use, their cables haven’t stood up the use as well. The rubber covering the cable first started cracking from behind my ears, and now there are even more cracks where the protective metal coil comes out of the cable covering.&lt;/p&gt;


	&lt;p&gt;Yesterday’s &lt;a href="http://twitter.com/lazyatom/statuses/942052102"&gt;tweet&lt;/a&gt; by &lt;a href="http://twitter.com/lazyatom"&gt;lazyatom&lt;/a&gt; finally pushed me over the edge to ask for a replacement. I started with the Finnish distributor even though I bought the pair from UK, just to try out my luck. And lucky I was (unlike &lt;a href="http://twitter.com/lazyatom/statuses/943469362"&gt;some others&lt;/a&gt;). The distributor promised to send me a replacement pair if I’d just mail them the phones. They’re now in the mail, fingers crossed that I’ve got a new pair soon. Kudos for that to &lt;a href="http://www.noretron.fi/"&gt;Noretron&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;In July, when we jumped on a train for our honeymoon in Norway, I forgot my &lt;span class="caps"&gt;E2C&lt;/span&gt;’s back home. Two weeks without earplugs just couldn’t do, so I went shopping in the airport to see if they’d have some good alternatives on sale. One reasonably priced model that looked liked it would fit the bill was &lt;a href="http://www.koss.com/koss/kossweb.nsf/p?openform&amp;amp;#38;pc%5Eeb%5EPLUG"&gt;Koss The Plug&lt;/a&gt;. Priced at less than €20, I figured I wouldn’t lose much even if they wouldn’t turn out to be good. Which they didn’t.&lt;/p&gt;


	&lt;p&gt;While The Plugs sit fairly well inside the ear canal, the foam plug is the only thing keeping them in place. The Shures, no the other hand, have the earphone body sitting inside the earlobe as well, and the cable going behind the ear. So sooner or later gravity will pull The Plug out of the ear, and that moment comes very soon if you’re both sweating and moving at the same time.&lt;/p&gt;


	&lt;p&gt;The biggest problem with the Koss plugs, however, is that (at least with my iPod Shuffle) they somehow hugely amplify the silent humming caused by a player when it’s on. That causes the phones to be nearly unusable on lower volumes, e.g. when I listen to a podcast before falling asleep. With the lowest volume I can hardly hear the voice of the hosts from the humming. This is a problem I haven’t encountered with any other pair of plugs, including the ones coming with iPods. Thus I don’t recommend buying The Plugs even though they are cheap. Cough up a few dozen bucks more and get a good pair of Shures instead. I’m at least eagerly waiting for my replacement Shure buds, that’s how big the difference between the two is.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=ZVSCM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=ZVSCM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=bOboM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=bOboM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/10/3/unplugged</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-10-02:2856</id>
    <published>2008-10-02T05:59:00Z</published>
    <updated>2008-10-02T06:40:26Z</updated>
    <category term="Apple" />
    <category term="geeky" />
    <category term="development" />
    <category term="geeky" />
    <category term="iphone" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/408980401/fernando" rel="alternate" type="text/html" />
    <title>Fernando</title>
<content type="html">
            &lt;p&gt;There was &lt;a href="http://developer.apple.com/iphone/program/"&gt;something in the air&lt;/a&gt; that night,&lt;br /&gt;
the stars were bright, Fernando.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://pragprog.com/"&gt;They&lt;/a&gt; were &lt;a href="http://blog.toolshed.com/2008/10/iphone-nda-lift.html"&gt;shining&lt;/a&gt; &lt;a href="http://pragprog.com/screencasts/v-bdiphone/writing-your-first-iphone-application"&gt;there&lt;/a&gt; for &lt;a href="http://pragmaticstudio.com/iphone/"&gt;you&lt;/a&gt; and &lt;a href="http://pragdave.blogs.pragprog.com/pragdave/2008/10/the-iphone-book.html"&gt;me&lt;/a&gt;,&lt;br /&gt;
for &lt;a href="http://furbo.org/2008/10/01/redacted/"&gt;liberty&lt;/a&gt;, Fernando.&lt;/p&gt;


	&lt;p&gt;- Björn Ulvaeus&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=OVI8M"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=OVI8M" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=gvV9M"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=gvV9M" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/10/2/fernando</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-09-24:2853</id>
    <published>2008-09-24T19:28:00Z</published>
    <updated>2008-09-24T19:49:04Z</updated>
    <category term="rails" />
    <category term="announcement" />
    <category term="workshop" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/402105280/a-week-of-ruby-rails-bdd-ajax-training-in-december" rel="alternate" type="text/html" />
    <title>A Week of Ruby/Rails/BDD/Ajax Training in December</title>
<content type="html">
            &lt;p&gt;After my last Ruby on Rails workshop held last year I’ve often been asked when there is going to be another one. Here it comes.&lt;/p&gt;


	&lt;p&gt;December 1st to 5th, we will join forces with &lt;a href="http://tarvainen.wordpress.com/"&gt;Antti Tarvainen&lt;/a&gt; from &lt;a href="http://leonidasoy.com/"&gt;Leonidas&lt;/a&gt; and give &lt;a href="http://rapidstraining.fi/"&gt;a week of one-day workshops&lt;/a&gt; in Helsinki with separate but closely related themes:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Beginning Ruby&lt;/li&gt;
		&lt;li&gt;Beginning Rails&lt;/li&gt;
		&lt;li&gt;Advanced Ruby&lt;/li&gt;
		&lt;li&gt;&lt;acronym title="Behaviour-Driven Development"&gt;BDD&lt;/acronym&gt; on Rails&lt;/li&gt;
		&lt;li&gt;Advanced Ajax on Rails&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;You can choose as many of the days to attend to as you want to (a smörgåsbord if I may), but &lt;em&gt;if you will join us for the whole week, the last day will be on us&lt;/em&gt;. The early bird price is 500€/day, with group and alumni discounts available. The price includes a plentiful lunch buffet (of course), kick-ass course materials and some goodies we’ll disclose a bit later. The course will be held in Finnish.&lt;/p&gt;


	&lt;p&gt;I’m really excited about the course. The last time I gave a Ruby workshop was real fun and I learned a ton from it. One thing I understood while attending Pragmatic Studios is that having more than one teacher really makes a big difference, since instead of a monologue you give the students a real &lt;em&gt;discussion&lt;/em&gt; about the topics. I know Antti from a while back and know from his classes at &lt;span class="caps"&gt;TUT&lt;/span&gt; that he’s a great instructor, so I really look forward to being able to teach together with him.&lt;/p&gt;


	&lt;p&gt;Read more and register yourself for the classes from our brand-new &lt;a href="http://rapidstraining.fi/"&gt;Rapids Training&lt;/a&gt; website. Hope to see you all in December!&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=rJbkL"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=rJbkL" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=YGeoL"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=YGeoL" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/9/24/a-week-of-ruby-rails-bdd-ajax-training-in-december</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-09-16:2831</id>
    <published>2008-09-16T13:00:00Z</published>
    <updated>2008-09-16T13:01:12Z</updated>
    <category term="geeky" />
    <category term="screen" />
    <category term="shell" />
    <category term="unix" />
    <category term="zsh" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/394191018/making-emacs-keybindings-work-with-zsh-and-screen" rel="alternate" type="text/html" />
    <title>Making emacs keybindings work with zsh and screen</title>
<content type="html">
            &lt;p&gt;I’ve always (as in from the early OpenACS days) been an emacs guy on linux. Sure, I do most of my development on TextMate these days, but for all text editing on servers I still prefer emacs and have its keybindings tattooed deep in my brain:&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Ctrl-a&lt;/em&gt;&lt;/th&gt;
			&lt;td&gt;Beginning of line&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Ctrl-e&lt;/em&gt;&lt;/th&gt;
			&lt;td&gt;End of line&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Ctrl-k&lt;/em&gt;&lt;/th&gt;
			&lt;td&gt;Kill the rest of the line&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;Of course, these are the default bindings in bash as well.&lt;/p&gt;


	&lt;p&gt;However, I’m using &lt;a href="http://www.mattcutts.com/blog/a-quick-tutorial-on-screen/"&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; screen&lt;/a&gt; to stay sane while working over unreliable server connections. Screen uses &lt;code&gt;Ctrl-a&lt;/code&gt; by default as its escape key so to make it work correctly, I’ve had this in my &lt;code&gt;.bash_profile&lt;/code&gt; files for a long time:&lt;/p&gt;


&lt;pre&gt;&lt;code class="shell"&gt;alias scr="TERM=vt100 ; screen -e^Oo" 
alias scd="TERM=vt100 ; screen -d -r" 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That makes (among other things) &lt;code&gt;Ctrl-o&lt;/code&gt; to be the escape key binding and &lt;em&gt;lets &lt;code&gt;Ctrl-a&lt;/code&gt; do the thing it’s supposed to do&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;However, I’ve heard so much talk about &lt;a href="http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/"&gt;zsh&lt;/a&gt; from many directions lately, that I had to try it out myself. With zsh (&lt;a href="http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/"&gt;&lt;code&gt;.zshrc&lt;/code&gt; downloaded from here&lt;/a&gt;) the keys worked fine without screen, but within a screen session they broke. Here’s what I had to do to make everything work.&lt;/p&gt;


	&lt;p&gt;First, setting the default escape key in the screen alias command didn’t work. I had to do it in the &lt;code&gt;~/.screenrc&lt;/code&gt; file instead:&lt;/p&gt;


&lt;pre&gt;&lt;code class="shell"&gt;escape ^Oo
startup_message off
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;(The second line just turns off the annoying splash screen)&lt;/p&gt;


	&lt;p&gt;However, with this and the default key bindings &lt;code&gt;Ctrl-a&lt;/code&gt; and friends still didn’t work in screen, they were just output as literals on the screen. Some determined googling finally &lt;a href="http://my.opera.com/blackbelt_jones/blog/2007/06/05/zsh-prompt-configuration-issue-solved"&gt;turned up the key&lt;/a&gt; (pun unintended) to the puzzle:&lt;/p&gt;


&lt;pre&gt;&lt;code class="shell"&gt;bindkey -e
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Adding that one line into my &lt;code&gt;.zshrc&lt;/code&gt; among the other keybindings solved the problem. Now I’m one happy zsh+screen camper, although my journey is still at a very early stage and I’m yet to learn the more advanced zsh goodies. The nice thing has been that without learning really anything new (or changing any habits), I’m still benefiting from using zsh.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=Lct7L"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=Lct7L" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=aZbpL"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=aZbpL" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/9/16/making-emacs-keybindings-work-with-zsh-and-screen</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-09-09:2825</id>
    <published>2008-09-09T17:09:00Z</published>
    <updated>2008-09-09T17:10:12Z</updated>
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/387839424/from-rails-ajax-helpers-to-low-pro-part-3-some-announcements" rel="alternate" type="text/html" />
    <title>From Rails Ajax helpers to Low Pro, Part 3 (+ some announcements)</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;This is the third part of my introduction to Low Pro series, something that has been taken… hmmm… a while. The two first parts can be found here:&lt;/em&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://jlaine.net/2007/8/3/from-rails-ajax-helpers-to-low-pro-part-i"&gt;Part 1&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://jlaine.net/2007/8/6/from-rails-ajax-helpers-to-low-pro-part-2"&gt;Part 2&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;em&gt;Coincidentally, all these pieces are also part of my new ebook, &lt;a href="http://peepcode.com/products/unobtrusive-prototypejs-draft"&gt;Unobtrusive Prototype&lt;/a&gt;, straight from the Peepcode oven. If you liked the articles, you might really enjoy the book. It will have all the code rewritten for Rails 2.1 (as has this article btw), it is professionally edited unlike my rumblings here, and has a much wider coverage of Low Pro, including writing your own Behaviors and event delegation.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;I also managed to give a &lt;a href="http://en.oreilly.com/railseurope2008/public/schedule/detail/3584"&gt;tutorial&lt;/a&gt; on the topics covered in the book in &lt;a href="http://en.oreilly.com/railseurope2008/public/content/home"&gt;RailsConf Europe&lt;/a&gt; in Berlin last week. The &lt;a href="http://www.slideshare.net/supervillain/accessible-ajax-on-rails-presentation/"&gt;tutorial slides can be found at Slideshare&lt;/a&gt;, where they also got a short featured treatment.&lt;/em&gt;&lt;/p&gt;


&lt;div&gt;
&amp;lt;object height="355" width="425"&gt;
&amp;lt;param /&gt;
&amp;lt;param /&gt;
&amp;lt;param /&gt;
  &amp;lt;embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=railsconfeurope2008-1220336237309478-9&amp;amp;#38;stripped_title=accessible-ajax-on-rails-presentation" height="355" width="425"&gt;
  &amp;lt;/embed&gt;
&amp;lt;/object&gt;
&lt;/div&gt;

	&lt;p&gt;&lt;em&gt;I moved the &lt;a href="http://github.com/jarkko/unobtrusive_book_code/"&gt;sample code for the articles and the book&lt;/a&gt; to &lt;a href="http://github.com/jarkko"&gt;my GitHub account&lt;/a&gt;. The &lt;a href="http://github.com/jarkko/unobtrusive_book_code/tree/chapter-5"&gt;Chapter 5 branch&lt;/a&gt; should be pretty much where this article starts at. If you’re not into git (yet), just click the “Download” button on the page to suck a zip file of the whole source code to your box.&lt;/em&gt;&lt;/p&gt;


	&lt;h3&gt;Going &lt;span class="caps"&gt;DRY&lt;/span&gt; with multiple elements&lt;/h3&gt;


	&lt;p&gt;Now that we have taken care of adding items to our to-do lists, let’s have a look at the the action of ticking items done and undone. The &lt;code&gt;index.html.erb&lt;/code&gt; view uses the Rails’ partial mechanism to display the lists of items. Here’s how the &lt;code&gt;_item.html.erb&lt;/code&gt; partial looks like:&lt;/p&gt;


&lt;pre&gt;&lt;code class="builder"&gt;&amp;lt;% @item = item %&amp;gt;
&amp;lt;li id="&amp;lt;%= item.state %&amp;gt;_&amp;lt;%= item.id %&amp;gt;"&amp;gt;
  &amp;lt;%= check_box("item[]", :done, :id =&amp;gt; "#{item.state}_box_#{item.id}") %&amp;gt;
  &amp;lt;label for="&amp;lt;%= "#{item.state}_box_#{item.id}" %&amp;gt;"&amp;gt;
    &amp;lt;%= item.description %&amp;gt;
  &amp;lt;/label&amp;gt;
  &amp;lt;%= observe_field("#{item.state}_box_#{item.id}", 
                    :url =&amp;gt; item_path(item), 
                    :method =&amp;gt; :put) %&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;code&gt;observe_field&lt;/code&gt; is a Rails helper that attaches an Javascript observer to the field in question. Whenever the field is changed (or every &lt;em&gt;n&lt;/em&gt; seconds, if the time n is given as a parameter to the &lt;code&gt;observe_field&lt;/code&gt; call), an Ajax call (in this case to &lt;code&gt;item_path(item)&lt;/code&gt;) is made. In our app, the responding &lt;code&gt;update&lt;/code&gt; action will then update the state of the item in the database and return Javascript that will move the item to the correct list on the page.&lt;/p&gt;


	&lt;p&gt;Here’s an example of what the list of items looks like to the browser:&lt;/p&gt;


&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;li id="undone_1"&amp;gt;
&amp;lt;input id="undone_box_1" name="item[1][done]" type="checkbox" value="1" /&amp;gt;
&amp;lt;input name="item[1][done]" type="hidden" value="0" /&amp;gt;
&amp;lt;label for="undone_box_1"&amp;gt;
  Buy carrots
&amp;lt;/label&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
//&amp;lt;![CDATA[
new Form.Element.EventObserver('undone_box_1',
                  function(element, value) {
                    new Ajax.Request('/items/1', 
                                     {asynchronous:true, 
                                      evalScripts:true, 
                                      method:'put', 
                                      parameters:value + '&amp;authenticity_token=' +
                encodeURIComponent('8d829cfcccdf4d2b494891ef47cc95893faa361e')})})
//]]&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;/li&amp;gt;
&amp;lt;li id="undone_2"&amp;gt;
&amp;lt;input id="undone_box_2" name="item[2][done]" type="checkbox" value="1" /&amp;gt;
&amp;lt;input name="item[2][done]" type="hidden" value="0" /&amp;gt;
&amp;lt;label for="undone_box_2"&amp;gt;
  Return bottles to recycling
&amp;lt;/label&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;
//&amp;lt;![CDATA[
new Form.Element.EventObserver('undone_box_2', 
                  function(element, value) {
                    new Ajax.Request('/items/2', 
                                     {asynchronous:true, 
                                       evalScripts:true, method:'put', 
                                       parameters:value + '&amp;authenticity_token=' +
                encodeURIComponent('8d829cfcccdf4d2b494891ef47cc95893faa361e')})})
//]]&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Imagine a list that has a couple dozen items. Not exactly &lt;span class="caps"&gt;DRY&lt;/span&gt;, is it, especially compared to how clean the source code of a Rails app tends to be?&lt;/p&gt;


	&lt;p&gt;Even if we set aside all the objections for the ugly code above, there is still the issue of the form not working at all without Javascript. Not good.&lt;/p&gt;


	&lt;p&gt;Let’s again start our round of refactoring by making the checkboxes work without javascript. For that, we’ll remove the &lt;code&gt;observe_field&lt;/code&gt; call from the partial:&lt;/p&gt;


&lt;pre&gt;&lt;code class="builder"&gt;&amp;lt;% @item = item %&amp;gt;
&amp;lt;li id="&amp;lt;%= item.state %&amp;gt;_&amp;lt;%= item.id %&amp;gt;"&amp;gt;
  &amp;lt;%= check_box("item[]", :done, :id =&amp;gt; "#{item.state}_box_#{item.id}") %&amp;gt;
  &amp;lt;label for="&amp;lt;%= "#{item.state}_box_#{item.id}" %&amp;gt;"&amp;gt;
    &amp;lt;%= item.description %&amp;gt;
  &amp;lt;/label&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, to make our form work again, we need to figure out what it’s supposed to do and where we should send it to. Thinking restfully, by submitting a form with multiple items checked or unchecked, we are modifying a &lt;em&gt;to-do list&lt;/em&gt;. Let’s thus create a simple controller for the imaginary List resource (remember, resources don’t need to map directly to ActiveRecord models).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;script/generate controller Lists&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then add the necessary route to &lt;code&gt;config/routes.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;  map.resources :items
  map.resource :list
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;For simplicity’s sake, let’s pretend our app can only handle a single to-do list (it’s our personal to-do list app, after all) and use the single form of resource routes with it.&lt;/p&gt;


	&lt;p&gt;In our to-do list page, we currently have a form that’s unable to submit anything. Let’s add a submit button to it and also change the form in &lt;code&gt;app/views/items/index.html.erb&lt;/code&gt; to point to the lists controller:&lt;/p&gt;


&lt;pre&gt;&lt;code class="builder"&gt;&amp;lt;% form_for :list, :url =&amp;gt; list_path, :html =&amp;gt; {:method =&amp;gt; :put} do |f| %&amp;gt;
  &amp;lt;h3&amp;gt;
    Not done:
  &amp;lt;/h3&amp;gt;

  &amp;lt;ul id="undone"&amp;gt;
    &amp;lt;%= render :partial =&amp;gt; "item", :collection =&amp;gt; @not_done %&amp;gt;
  &amp;lt;/ul&amp;gt;

  &amp;lt;h3&amp;gt;
    Done:
  &amp;lt;/h3&amp;gt;

  &amp;lt;ul id="done"&amp;gt;
    &amp;lt;%= render :partial =&amp;gt; "item", :collection =&amp;gt; @done %&amp;gt;
  &amp;lt;/ul&amp;gt;

  &amp;lt;p&amp;gt;
    &amp;lt;%= submit_tag "Save changes", :id =&amp;gt; "save_changes" %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now let’s create a really simple update action to our new controller for the mass assignment of items:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ListsController &amp;lt; ApplicationController
  def update
    params[:item].each do |key, values|
      item = Item.find(key)
      item.update_attributes(values)
    end

    redirect_to items_path
  end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you now test the application with Javascript turned off, updating the item state should work fine. We can thus continue to the hijacking phase.&lt;/p&gt;


	&lt;p&gt;First of all, let’s hide the submit button because we don’t need it in the Ajax’ed form.&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;Event.addBehavior({
  'body' : function() {
    $('add_form').hide();
    $('add_new_link').show();
    $('save_changes').hide();
  },
  '#add_new_link:click' : function(e) {
    $('add_form').toggle();
    e.stop();
  },
  '#add_form' : Remote.Form
});
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, what we need to do is to make clicking a checkbox to call the update action for the current item. This is easily done in the js file:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;Event.addBehavior({
  'body' : function() {
    $('add_form').hide();
    $('add_new_link').show();
    $('save_changes').hide();
  },
  '#add_new_link:click' : function(e) {
    $('add_form').toggle();
    e.stop();
  },
  '#add_form' : Remote.Form,
  'input[type=checkbox]:click' : function() {
    var id = this.id.match(/\d{1,}$/);
    var auth_token = this.up('form').
                          select('[name=authenticity_token]').
                          first().value;
    new Ajax.Request('/items/' + id, 
                     {asynchronous:true, 
                      evalScripts:true, 
                      method: 'put',
                      parameters: {
                        authenticity_token: auth_token
                      }});
  }
});
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We use the &lt;span class="caps"&gt;CSS3&lt;/span&gt; selector syntax to get every input of type checkbox, then fetch the item id from the element id using a regular expression and finally call the update method of the items controller to update the item. The cool thing about &lt;code&gt;addBehaviour&lt;/code&gt; is that the behaviour is attached to all elements returned by the selector. Thus adding a single call function to our javascript file automatically attaches the function to as many list items as needed.&lt;/p&gt;


	&lt;p&gt;Note that because of the spam-defense mechanism in Rails, we also need to send the authenticity token with our call. We use the cool Prototype selector functions to easily get to the current token inside the form.&lt;/p&gt;


	&lt;p&gt;An astute reader might have noticed that if you click an item in the list, and then try to re-click the same item after it’s moved to the opposing list, it’s not moved back automatically. This is because our Ajax update action created a new list item and added it to the list, and by default &lt;code&gt;Event.addBehaviour&lt;/code&gt; does not reattach behaviours after each Ajax call.&lt;/p&gt;


	&lt;p&gt;We have a couple of ways to fix the situation. The simplest would be to add this line to our Javascript file:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;Event.addBehavior.reassignAfterAjax = true;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;However, the simplest way is not always the best. By reassigning behaviours automatically after each Ajax call we can deteriorate the Javascript performance considerably, and the effect gets larger when there are more items watched.&lt;/p&gt;


	&lt;p&gt;Second, a bit more surgical option would be to reload the &lt;code&gt;addBehaviour&lt;/code&gt; rules in a callback of the Ajax call:&lt;/p&gt;


&lt;pre&gt;&lt;code class="javascript"&gt;onComplete : function() {
  Event.addBehavior.reload();
}
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This way the behaviours would only be reassigned after the particular Ajax call, not all of them. However, it’s still a bit heavy-handed.&lt;/p&gt;


	&lt;p&gt;Let’s take a step back and think how we could avoid reassigning all the behaviours for the new element. An obvious answer would of course be not to create a new element at all, but instead just move the existing one (with all the behaviours already attached).&lt;/p&gt;


	&lt;p&gt;In app/views/items/update.js.rjs we can see that the code first removes a list item and then adds a new one into the list of items in the opposite state:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;page["#{@item.opposite_state}_#{@item.id}"].remove
page.insert_html :top, @item.state, :partial =&amp;gt; "item" 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;We can fairly easily change that code to not delete/create a new node to the page, but instead move the list item to the correct place in the &lt;span class="caps"&gt;DOM&lt;/span&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code class="builder"&gt;page &amp;lt;&amp;lt; " 
  var el = $('#{@item.opposite_state}_#{@item.id}');
  $('#{@item.state}').insert({ top: el.remove() });
  el.id = '#{@item.state}_#{@item.id}';
" 
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This time we don’t use the &lt;span class="caps"&gt;RJS&lt;/span&gt; syntax but instead just output plain old Javascript back to the browser. We first fetch the list element we’re about to move. We then remove it from the &lt;span class="caps"&gt;DOM&lt;/span&gt; tree, just to again insert it to the bottom of the list it now belongs to. In the end we change the id of the item to reflect its new state as well.&lt;/p&gt;


	&lt;p&gt;If you now try the app again, you should be able to tick and untick the items at will, and everything should work just fine. The behaviour assigned to the list element on the page load sticks to it through all the moving and renaming of the element.&lt;/p&gt;


	&lt;p&gt;—&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://peepcode.com/products/unobtrusive-prototypejs-draft"&gt;&lt;img src="/assets/2008/9/9/unobtrusive-cover.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;If you enjoyed the article, consider grabbing a copy of my new ebook, &lt;a href="http://peepcode.com/products/unobtrusive-prototypejs-draft"&gt;Unobtrusive Prototype&lt;/a&gt;, straight from the Peepcode oven. It will have all the code rewritten for Rails 2.1, it is professionally edited unlike my rumblings here, and has a much wider coverage of Low Pro, including writing your own Behaviors and event delegation. &lt;strong&gt;If you’re quick and have a close look at my presentation slides in the beginning of this article, you might even find a way to get your copy for half the normal price&lt;/strong&gt;!&lt;/em&gt;&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=SOjsL"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=SOjsL" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=VXdLL"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=VXdLL" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/9/9/from-rails-ajax-helpers-to-low-pro-part-3-some-announcements</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-06-27:2529</id>
    <published>2008-06-27T16:10:00Z</published>
    <updated>2008-07-04T08:05:18Z</updated>
    <category term="apple" />
    <category term="iphone" />
    <category term="life" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/321430764/sonera-s-at-it-again" rel="alternate" type="text/html" />
    <title>Sonera's at it again</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;[UPDATE]&lt;/strong&gt; Now the people in the Nordic have followed the lead of &lt;a href="http://fuckyourogers.com"&gt;fuckyourogers.com&lt;/a&gt;:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.facebook.com/group.php?gid=22113926713"&gt;iPhone: Yes please – Sonera: No thank you&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.facebook.com/group.php?gid=16689679566&amp;amp;#38;ref=nf"&gt;Bedre Telia abonnement til iPhone 3G&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.facebook.com/group.php?gid=31332232832"&gt;Billigere iPhone til Norge!&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.facebook.com/group.php?gid=21660696603"&gt;Telia dÃ¶dar iPhone med kassa abonnemang.&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Sonera, the poor man’s AT&amp;T, the old Finnish national telcom that got “famous” in the dawn of the century by &lt;a href="http://robots.cnnfn.com/2000/08/17/europe/german_umts/index.htm"&gt;buying thin German air for $7.5 Billions&lt;/a&gt; (and later writing it off as worthless), is on fire again. The company that’s nowadays merged with its Swedish counterpart Telia, &lt;a href="http://www.teliasonera.com/press/pressreleases/item.page?prs.itemId=360269"&gt;announced&lt;/a&gt; a while ago that they will be the ones bringing the &lt;a href="http://www.apple.com/iphone/"&gt;3G iPhone&lt;/a&gt; to the Northern Europe. I guess some warning bells should have been in place considering the company is pretty much the only one that still doesn’t offer a reasonable unlimited data plan for its &lt;span class="caps"&gt;GSM&lt;/span&gt; customers. However, initially the excitement over iPhone finally (officially) reaching this corner of the world took over and I even considered becoming a Sonera client.&lt;/p&gt;


	&lt;p&gt;Today, the ugly truth was revealed when the &lt;a href="http://www.sonera.fi/iphone"&gt;iPhone 3G plans&lt;/a&gt; were announced. &lt;em&gt;Not a single plan has unlimited data&lt;/em&gt;. Not even the â‚¬90/month Large plan (which has 1GB/month of data). The small and medium plans come with measly 100 and 250 MB a month. Considering that watching a few YouTube movies consumes pretty much the whole monthly quota, the plans seem nothing but laughable&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;[UPDATE]&lt;/strong&gt; Here’s the whole pricing table:&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Plan&lt;/em&gt;&lt;/th&gt;
			&lt;th&gt;&lt;em&gt;Small&lt;/em&gt;&lt;/th&gt;
			&lt;th&gt;&lt;em&gt;Medium&lt;/em&gt;&lt;/th&gt;
			&lt;th&gt;&lt;em&gt;Large&lt;/em&gt;&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Price&lt;/em&gt;&lt;/th&gt;
			&lt;td&gt;31,69 â‚¬/month + 159 â‚¬/8 GB or 245 â‚¬/16 GB iPhone&lt;/td&gt;
			&lt;td&gt; 51,49 â‚¬/month + 79 â‚¬/8 GB or 165 â‚¬/16 GB iPhone&lt;/td&gt;
			&lt;td&gt;89,99 â‚¬/month + 1 â‚¬/8 GB or 85 â‚¬/16 GB iPhone &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Includes&lt;/em&gt;&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;(min/month)&lt;/td&gt;
			&lt;td&gt;100&lt;/td&gt;
			&lt;td&gt;250&lt;/td&gt;
			&lt;td&gt;1000&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;span class="caps"&gt;SMS&lt;/span&gt; messages/month&lt;/td&gt;
			&lt;td&gt;100&lt;/td&gt;
			&lt;td&gt;250&lt;/td&gt;
			&lt;td&gt;1000&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Data (MB/month)&lt;/td&gt;
			&lt;td&gt;100&lt;/td&gt;
			&lt;td&gt;250&lt;/td&gt;
			&lt;td&gt;1000&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Home Run hotspot usage&lt;/td&gt;
			&lt;td&gt;yes&lt;/td&gt;
			&lt;td&gt;yes&lt;/td&gt;
			&lt;td&gt;yes&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;th&gt;&lt;em&gt;Additional calls&lt;/em&gt;&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Starting a call&lt;/td&gt;
			&lt;td&gt;     0,049 â‚¬     &lt;/td&gt;
			&lt;td&gt;0,049 â‚¬     &lt;/td&gt;
			&lt;td&gt;0,049 â‚¬     &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Cost/min&lt;/td&gt;
			&lt;td&gt;     0,079 â‚¬     &lt;/td&gt;
			&lt;td&gt;0,079 â‚¬     &lt;/td&gt;
			&lt;td&gt;0,079 â‚¬     &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Additional text msg&lt;/td&gt;
			&lt;td&gt;     0,079 â‚¬     &lt;/td&gt;
			&lt;td&gt;0,079 â‚¬     &lt;/td&gt;
			&lt;td&gt;0,079 â‚¬     &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Data/MB&lt;/td&gt;
			&lt;td&gt; 1,49 â‚¬     &lt;/td&gt;
			&lt;td&gt;1,49 â‚¬     &lt;/td&gt;
			&lt;td&gt;1,49 â‚¬&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;Now, the plans might have been ok 5 years ago&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;, but they totally overlook the platform what iPhone has become in the countries it’s been on sale so far. An iPhone is not just a phone anymore, it’s a whole new computing platform, which pretty much needs an unlimited data plan.&lt;/p&gt;


	&lt;p&gt;One huge selling point for the new phone will no doubt be &lt;a href="http://www.apple.com/mobileme/"&gt;Mobile Me&lt;/a&gt;. The chance to automatically and wirelessly sync your life between your computers and your phone sounds almost too good to be true. With â‚¬1.49/MB for the over quota data transfer, the syncing doesn’t exactly sound like a realistic option anymore.&lt;/p&gt;


	&lt;p&gt;Fortunately everything is not lost for us. You &lt;em&gt;can&lt;/em&gt; buy the phone from Sonera even without the ridiculous plans. The 8GB and 16GB models cost â‚¬429 and â‚¬519 respectively if you don’t take any real plan with them. You &lt;strong&gt;do&lt;/strong&gt; have to sign up for a custom plan for 24 months, though, but the cheapest comes at â‚¬1.99/month and thus only adds â‚¬48 to the total cost of ownership. That might just about cut it for me, but for the masses? Not so much. I hope I’ll be wrong, but to me it seems that Sonera is once again going to kill something that would’ve had potential to be something disruptive.&lt;/p&gt;


	&lt;p&gt;Oh well, I hear they’re going to sell cheap unlocked iPhones in Italy…&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;[UPDATE]&lt;/strong&gt; Gruber links to &lt;a href="http://www.tuaw.com/2008/06/27/rogers-announces-iphone-rates-in-canada/"&gt;The Unofficial Apple Weblog’s entry about Rogers unveiling their plans&lt;/a&gt; as well, &lt;a href="http://daringfireball.net/linked/2008/06/27/rogers-canada"&gt;stating that ‘they suck’&lt;/a&gt;. However, compared to the offering from Sonera, Rogers’ plans seem to be downright cheap (even the cheapest plan comes with 400MB of data and 150 mins of weekday calls compared to 100MB and 100 mins all the time). Thanks also to Vesa for the comment about Rogers’ plans.&lt;/p&gt;


	&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; The prices seem even more laughable considering that pretty much every other operator offers unlimited data plans starting from â‚¬10/month.&lt;/p&gt;


	&lt;p&gt;&lt;sup&gt;2&lt;/sup&gt; Even though we did, in fact, have unlimited &lt;span class="caps"&gt;GPRS&lt;/span&gt; plans in here back then, something which was unheard of in the Middle Europe where I used to live those days.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=0dzcuI"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=0dzcuI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=jjlKXI"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=jjlKXI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/6/27/sonera-s-at-it-again</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-06-02:2520</id>
    <published>2008-06-02T10:00:00Z</published>
    <updated>2008-06-02T10:02:54Z</updated>
    <category term="datamapper" />
    <category term="merb" />
    <category term="migrations" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/302870411/specifying-indeces-in-datamapper" rel="alternate" type="text/html" />
    <title>Specifying indeces in DataMapper</title>
<content type="html">
            &lt;p&gt;I’ve been working with &lt;a href="http://merbivore.com/"&gt;Merb&lt;/a&gt; and &lt;a href="http://datamapper.org/"&gt;DataMapper&lt;/a&gt; in the context of a new project for a week now, and the experience has been both pleasant and interesting. On one hand the stack is solid and super-fast (like, desktop app fast), on the other there are a lot of things that catch you if you don’t manage to remove the Rails hat off your head. The youth of the frameworks still shows (especially in DataMapper which has recently seen a major refactoring to make it more modular the same way Merb was reworked a bit earlier) but at the same time I get the chance to help with some really cool up-and-coming open source software. If you don’t consider that a plus, maybe you should still wait a couple months before you consider these critters for a production app.&lt;/p&gt;


	&lt;p&gt;One clear symptom of the young age of both Merb and DataMapper is the lack of documentation. They both have documentation sections on their respective websites and there are other efforts such as Merbunity going on, but you still have to have the guts to dive into the source code if you want to find out how some of the less common use cases work.&lt;/p&gt;


	&lt;p&gt;Here’s a short piece on how to declare indeces for your DataMapper models. I plan to continue publishing this kind of tutorials for other functionality as well, and to contribute them back to the “official” docs when appropriate.&lt;/p&gt;


	&lt;h2&gt;The big difference&lt;/h2&gt;


	&lt;p&gt;The big conceptual different between ActiveRecord and DataMapper is that in ActiveRecord, the place where the properties of database tables are defined are the migration files. The actual tables are then built according to the migrations and the actual model classes build their property to methods from the database schema.&lt;/p&gt;


	&lt;p&gt;In DataMapper, the properties are defined in the actual model file. DM has so called auto migrations that compare the model file and the database schema, and modify the schema if the two don’t match.&lt;/p&gt;


	&lt;p&gt;Here’s an example DataMapper model:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class User
  include DataMapper::Resource

  property :id,         Integer, :serial =&amp;gt; true
  property :first_name, String
  property :last_name,  String
  property :bio,        Text
  property :single,     Boolean
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Seems clean, doesn’t it. Looking at a model it is clear what properties it has and what methods it supports. But what about indeces? In AR migrations, you would use the &lt;code&gt;create_index&lt;/code&gt; method. In DataMapper, &lt;code&gt;index&lt;/code&gt; is an option given to the &lt;code&gt;property&lt;/code&gt; method:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;property :last_name,    String, :index =&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Or, if you want the index to be unique:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;property :last_name,    String, :unique_index =&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;OK, but what if you need multi-column composite indeces? Easy. Instead of &lt;code&gt;true&lt;/code&gt;, give the index a name using a symbol:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;property :last_name,     String, :index =&amp;gt; :name
property :first_name,    String, :index =&amp;gt; :name
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will create an index called &lt;code&gt;index_products_name&lt;/code&gt; for the table, spanning columns &lt;code&gt;last_name&lt;/code&gt; and &lt;code&gt;first_name&lt;/code&gt;. &lt;strong&gt;The columns are added to the index in order of appearance&lt;/strong&gt;, so in this case the indexing order would be &lt;em&gt;last name, first name&lt;/em&gt;. If you want to change that order, just change the order of you &lt;code&gt;property&lt;/code&gt; calls in the model call definition.&lt;/p&gt;


	&lt;p&gt;There you have it! No rocket surgery, but something I had to dive into the source code to find out.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=U9i49I"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=U9i49I" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=Dla0CI"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=Dla0CI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/6/2/specifying-indeces-in-datamapper</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-05-25:2518</id>
    <published>2008-05-25T19:52:00Z</published>
    <updated>2008-05-25T19:54:24Z</updated>
    <category term="entrepreneurship" />
    <category term="life" />
    <category term="spirit" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/297918174/start-from-the-heart" rel="alternate" type="text/html" />
    <title>Start from the Heart</title>
<content type="html">
            &lt;p&gt;My friend &lt;a href="http://pinds.com/"&gt;Lars Pind&lt;/a&gt; is slowly migrating himself from a software developer to a coach. His new startup is called &lt;a href="http://startfromtheheart.com/"&gt;Start from the Heart&lt;/a&gt;, where Lars tries to help people start companies that represent their true soul. The guiding principle behind Start from the Heart is that there should be a deeper meaning in the business you pursue than just the money. As exactly that has been a driving force behind us at &lt;a href="http://dotherightthing.com"&gt;dotherightthing.com&lt;/a&gt;, it’s no wonder the premise of SftH really resonated with me.&lt;/p&gt;


	&lt;p&gt;Lars is putting up &lt;a href="http://startfromtheheart.com/blog/"&gt;a series of exercises&lt;/a&gt; for the participants of the program and giving out them for free. I worked through &lt;a href="http://startfromtheheart.com/heroes/"&gt;the first assignment&lt;/a&gt; and must say that it’s a great one, getting a smile on your face. If you’re thinking about starting your own company (or have ever contemplated it), I would highly recommend giving Start from the Heart a try. I’m certainly enjoying it from the bottom of my heart (no pun intended).&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=vBjXCH"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=vBjXCH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=l7r1IH"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=l7r1IH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/5/25/start-from-the-heart</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-05-08:2509</id>
    <published>2008-05-08T13:51:00Z</published>
    <updated>2008-05-26T05:24:45Z</updated>
    <category term="ampersand" />
    <category term="proc" />
    <category term="ruby" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/286084657/amp-lified" rel="alternate" type="text/html" />
    <title>&amp;amp;lified</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;&lt;/strong&gt; Now &lt;a href="http://ampersand.gosedesign.net/"&gt;ampersand even has its own blog&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Ampersand has received a lot of &lt;a href="http://www.typography.com/ask/showBlog.php?blogID=98"&gt;press&lt;/a&gt; &lt;a href="http://www.kottke.org/08/05/ampersands"&gt;lately&lt;/a&gt; and I decided to put my oar in as well.&lt;/p&gt;


	&lt;p&gt;My recent history with ampersand is kind of embarrassing, to say the least. I was giving a Ruby class in UK a few years back and during a class, I asked a participant whether there is some other term for the &lt;em&gt;at sign&lt;/em&gt; in English. “Sure”, she said, “it’s ampersand.” To this day I’m not sure whether she thought I said &lt;em&gt;et sign&lt;/em&gt;, or genuinely mixed up &lt;a href="http://en.wikipedia.org/wiki/Asperand"&gt;asperand&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Ampersand"&gt;ampersand&lt;/a&gt;. But for quite some time after that, I happily treated @ as ampersand.&lt;/p&gt;


	&lt;p&gt;But neither linguistics or typography is the topic of today’s article. Let’s rather talk about ampersand (the real one) in Ruby.&lt;/p&gt;


	&lt;p&gt;In Ruby, an ampersand denotes a block parameter. But let’s not get ahead of ourselves. A little background might be in place.&lt;/p&gt;


	&lt;p&gt;One of the coolest features in Ruby are &lt;em&gt;code blocks&lt;/em&gt;, or &lt;em&gt;closures&lt;/em&gt;. &lt;del&gt;They are basically anonymous functions, but as pretty much everything in Ruby, they are also objects.&lt;/del&gt; They are anonymous functions, that have little use just by themselves. However, you can turn them into &lt;code&gt;Proc&lt;/code&gt; objects either with the &lt;code&gt;Proc.new&lt;/code&gt; constructor or using the &lt;code&gt;lambda&lt;/code&gt; kernel method. The common best practice to mark code blocks is to use the curly braces with one-liners and &lt;code&gt;do..end&lt;/code&gt; with blocks that span multiple lines:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;yell = lambda { puts "AAARGH!!!" }
whisper = Proc.new do
 puts "whee" 
end
yell.call
whisper.call
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;âž¥&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;AAARGH!!!
whee&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Maybe the most useful application of &lt;code&gt;Proc&lt;/code&gt; objects in Ruby are block parameters. Anyone with some knowledge of Ruby is familiar with the following:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr = %w(apple orange kiwi)
=&amp;gt; ["apple", "orange", "kiwi"]
&amp;gt;&amp;gt; arr.each {|i| puts i[0,2]}
ap
or
ki
=&amp;gt; ["apple", "orange", "kiwi"]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, in this case you need to use neither &lt;code&gt;Proc.new&lt;/code&gt; nor &lt;code&gt;lambda&lt;/code&gt; with the block; it’s converted to a &lt;code&gt;Proc&lt;/code&gt; object implicitly. But as the method receives just a &lt;code&gt;Proc&lt;/code&gt; object as its parameter, you could also say something like this, right:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; put_two = lambda {|i| puts i[0,2]}
=&amp;gt; #&amp;lt;Proc:0x00329060@(irb):41&amp;gt;
&amp;gt;&amp;gt; arr.each(put_two)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Err, not quite. It turns out Ruby methods can take two kinds of parametersâ€”a number of normal parameters and a block parameter. In the code above the interpreter will think that the &lt;code&gt;put_two&lt;/code&gt; &lt;code&gt;Proc&lt;/code&gt; object is passed as a normal parameter to the &lt;code&gt;each&lt;/code&gt; call, and since &lt;code&gt;each&lt;/code&gt; doesn’t take any normal parameters, you will get an error:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr.each(put_two)
ArgumentError: wrong number of arguments (1 for 0)
    from (irb):42:in `each'
    from (irb):42&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And this is what brings us back to the ampersand:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr.each(&amp;put_two)
ap
or
ki
=&amp;gt; ["apple", "orange", "kiwi"]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So &lt;strong&gt;the ampersand is used to tell the interpreter that the following reference is the block parameter of the method&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;One fairly common idiom in the Rails world is this kind of construct:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr.map(&amp;:length)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;It is effectively the same as&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr.map {|i| i.length }
=&amp;gt; [5, 6, 4]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;However, if you start a plain irb session, you will notice something isn’t quite right:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr.map(&amp;:length)
TypeError: wrong argument type Symbol (expected Proc)
    from (irb):2&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That’s right. The cool shorthand method that worked so nicely in your Rails app doesn’t work in plain Ruby. That’s because there is some Rails magic behind the &lt;code&gt;&amp;:method&lt;/code&gt; call. This magic is e.g. the reason why &lt;a href="http://goruco2008.confreaks.com/06_zygmuntowicz.html"&gt;Ezra has prohibited using the shortcut in Merb framework code&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;But let’s have a closer look at what’s actually happening behind the scenes in the shortcut. The thing that’s different from our earlier calls is that there is a colon between the ampersand and the word “length”. This means that we’re not using a variable or method called &lt;code&gt;length&lt;/code&gt;, but the symbol &lt;code&gt;:length&lt;/code&gt;. If you’re not familiar with Ruby symbols (or even if you are), reading &lt;a href="http://blog.hasmanythrough.com/2008/4/19/symbols-are-not-pretty-strings"&gt;Josh’s recent article on symbols&lt;/a&gt; is a worthwhile read.&lt;/p&gt;


	&lt;p&gt;Now that we know that we’re trying to pass a symbol as the block parameter to a method (and that it’s not really working, as the error above indicates), we need a way to convert it to a &lt;code&gt;Proc&lt;/code&gt; object like expected by the method. Ruby has a slew of type conversion methods that are called implicitly whenever it’s clear that a certain type of object is needed. Inside a string for example, &lt;code&gt;to_s&lt;/code&gt; is called automatically for every object that is not a string itself:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; "Nice array: " + arr
TypeError: can't convert Array into String
    from (irb):6:in `+'
    from (irb):6
&amp;gt;&amp;gt; "Nice array: #{arr}" 
=&amp;gt; "Nice array: appleorangekiwi" 
&amp;gt;&amp;gt; "Nice array: " + arr.to_s
=&amp;gt; "Nice array: appleorangekiwi"&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In the same vein, since a block parameter of a method needs to be a &lt;code&gt;Proc&lt;/code&gt; object, &lt;code&gt;to_proc&lt;/code&gt; is called automatically for all other objects in an effort to get a hold of a proc.  So could it work if we just added a &lt;code&gt;to_proc&lt;/code&gt; method to the &lt;code&gt;Symbol&lt;/code&gt; class? Let’s find out!&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Symbol
  def to_proc
    lambda {|i| i.send(self)}
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;del&gt;Here we make &lt;code&gt;to_proc&lt;/code&gt; a lambda function that will use the &lt;code&gt;send&lt;/code&gt; method to call the method with the same name as the &lt;code&gt;Symbol&lt;/code&gt; object in question (self) for the element that’s passed to it.&lt;/del&gt; &lt;em&gt;(That got too confusing so let’s just use examples)&lt;/em&gt;.  So&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;arr.send(:length)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;is the same as&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;arr.length&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And thus&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;:length.to_proc&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;would become&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;lambda {|i| i.send(:length)}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, let’s see how our new method performs:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;&amp;gt;&amp;gt; arr.map(&amp;:reverse)
=&amp;gt; ["elppa", "egnaro", "iwik"]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Perfect!&lt;/p&gt;


	&lt;p&gt;While &lt;code&gt;Symbol#to_proc&lt;/code&gt; is a clever and perhaps an elegant hack, it’s still kind of a hack. So should you use it in your code? I tend to side with Ezra on this. If you’re writing framework code, you should probably err on the side of readability and common usage, and thus avoid “magical shortcuts” like these. But in application code, why not. I certainly do.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=Br6fxH"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=Br6fxH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=EpgUfH"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=EpgUfH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/5/8/amp-lified</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-05-05:2507</id>
    <published>2008-05-05T08:13:00Z</published>
    <updated>2008-05-05T08:15:08Z</updated>
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/283786466/making-capistrano-not-pant-on-cleanup" rel="alternate" type="text/html" />
    <title>Making capistrano not suffocate on cleanup</title>
<content type="html">
            &lt;p&gt;When trying to deploy an app on the production server, the &lt;code&gt;deploy:cleanup&lt;/code&gt; task always died for me like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;  * executing `deploy:cleanup'
  * executing "ls -x /opt/sites/mysite/releases" 
    servers: ["myserver"]
    [myserver] executing command
    command finished
 ** keeping 3 of 4 deployed releases
  * executing "rm -rf /opt/sites/mysite/releases/20080220092659" 
    servers: ["myserver"]
    [myserver] executing command
 ** [out :: myserver] sudo: no passwd entry for app!
 ** [out :: myserver] 
    command finished
command "rm -rf /opt/sites/mysite/releases/20080220092659" failed on myserver
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Turns out capistrano is for some reason trying to use a user called &lt;em&gt;app&lt;/em&gt; in the cleanup task even though the &lt;code&gt;:user&lt;/code&gt; parameter is set to something else in &lt;code&gt;config/deploy.rb&lt;/code&gt;. The solution was to set the &lt;code&gt;:runner&lt;/code&gt; parameter as well:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;set :runner, 'someotheruser'
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Don’t ask me why that worked. It seems a bit counterintuitive that the cleanup task uses the &lt;code&gt;runner&lt;/code&gt; param rather than &lt;code&gt;user&lt;/code&gt;. Found the hint towards the solution &lt;a href="http://groups.google.com/group/capistrano/browse_thread/thread/0d396a96d1946ba3"&gt;here&lt;/a&gt;.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=5jv9nH"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=5jv9nH" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=CvoWgH"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=CvoWgH" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/5/5/making-capistrano-not-pant-on-cleanup</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-04-22:2505</id>
    <published>2008-04-22T07:21:00Z</published>
    <updated>2008-04-22T07:22:42Z</updated>
    <category term="blunder" />
    <category term="sampo" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/275213795/hate-to-say" rel="alternate" type="text/html" />
    <title>Hate to say...</title>
<content type="html">
            &lt;h3&gt;December 2007&lt;/h3&gt;


	&lt;blockquote&gt;
		&lt;p&gt;For gawd’s sake, what did they smoke in your company’s Christmas party?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;em&gt;(A text message I sent to my buddy Thomas who works in Sampo Pankki in reference to the news that the bank (recently bought by Danske Bank) would deploy a new “security” system (that uses a Java applet) in their online banking solution).&lt;/em&gt;&lt;/p&gt;


	&lt;h3&gt;April 2008&lt;/h3&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The latest reactions inclule [sic] 52-year old male customer returing to the bank with an axe after hearing that his account is empty, money exchange company Forex stopping accepting payment cards from Sampo Bank and Sampo Bank customers not being able to buy train tickets online.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;(&lt;a href="http://janne.blogit.kauppalehti.fi/2008/04/03/finnish-sampo-banks-ict-problems-cause-extreme-reactions-in-their-clientele/"&gt;Finnish Sampo Bankâ€™s &lt;span class="caps"&gt;ICT&lt;/span&gt; problems cause extreme reactions in their clientele&lt;/a&gt;)&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=9GUlM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=9GUlM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=wXkgM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=wXkgM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/4/22/hate-to-say</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-03-11:2497</id>
    <published>2008-03-11T10:01:00Z</published>
    <updated>2008-03-11T10:01:28Z</updated>
    <category term="life" />
    <category term="brain" />
    <category term="life" />
    <category term="multitask" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/249411516/on-multitasking" rel="alternate" type="text/html" />
    <title>On Multitasking</title>
<content type="html">
            &lt;p&gt;Now, this has been &lt;a href="http://www.joelonsoftware.com/articles/fog0000000022.html"&gt;talked about in detail in the past&lt;/a&gt;, but here are two recent interesting discussions about multitasking. On the &lt;a href="http://podcast.rubyonrails.org/"&gt;Ruby on Rails Podcast&lt;/a&gt;, Geoff interviews Dr. John Medina in a “two-part series about his new book, &lt;a href="http://brainrules.net/"&gt;Brain Rules: 12 Principles for Surviving and Thriving at Work, Home, and School&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;One of the most interesting topic in the discussion is about human multitasking, and to be precise, the lack of it. One of the hot topics in this discussion is the debate about talking in phone while driving. Medina brings up &lt;a href="http://unews.utah.edu/p/?r=062206-1"&gt;recent studies&lt;/a&gt; that show talking while driving is as dangerous as drunk-driving, &lt;em&gt;no matter whether you use a hands-free set or not&lt;/em&gt;. As a reason, Medina proposes that when discussing with someone remote interactively, you build a mental image of the counterpart (just like you do when reading a novel) which takes your concentration away from driving. That sounds certainly believable. I have many times noticed that I’ve been driving for minutes while talking in the phone (with the iPhone headset, of course) and then suddenly kind of wake up back to the traffic.&lt;/p&gt;


	&lt;p&gt;Meanwhile, &lt;a href="http://www.randsinrepose.com/archives/2008/03/06/i_dont_multitask.html"&gt;Rands explains how he &lt;em&gt;doesn’t&lt;/em&gt; multitask&lt;/a&gt; even though it might appear as if he would to the outsider.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=Jcl8M"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=Jcl8M" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=zQ3tM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=zQ3tM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/3/11/on-multitasking</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-02-13:2490</id>
    <published>2008-02-13T13:25:00Z</published>
    <updated>2008-04-22T07:09:16Z</updated>
    <category term="apple" />
    <category term="news" />
    <category term="photo" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/234359632/a-few-photo-fyi-s" rel="alternate" type="text/html" />
    <title>A Track of Two</title>
<content type="html">
            &lt;p&gt;If you’re into photography, here’s a couple of quick links that might be of interest:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Scott Bourne and Alex Lindsay, of &lt;a href="http://www.twit.tv/mbw"&gt;MacBreak Weekly&lt;/a&gt; and many other fames, have started a new podcast under the &lt;a href="http://www.pixelcorps.tv/"&gt;Pixelcorps.tv&lt;/a&gt; umbrella: &lt;a href="http://twipphoto.com/"&gt;This Week in Photography&lt;/a&gt;. The guys are really great podcasters and the content is kind of semi-advanced so that it’s not boring even if you’re fairly competent (even pro, I would say) but also not overwhelmingly technical. Great stuff during long exercises like a track of two&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;. The third episode of &lt;span class="caps"&gt;TWIP&lt;/span&gt; discussed the state of Aperture and namely the lack of announcement of version 2 during the &lt;a href="http://www.pmai.org/index.cfm/ci_id/33573.htm"&gt;&lt;span class="caps"&gt;PMA&lt;/span&gt;&lt;/a&gt;. That gives us a nice segue to the next topic:&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.apple.com/aperture/"&gt;Aperture 2&lt;/a&gt; is here! Downloading it right now and have high hopes for the performance. Especially creating previews and exporting photos leaves a lot to be desired in 1.5, and if the first comments around the ‘net are to be trusted, the newcomer should be vastly better in this regard.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; A track of two (or “kakkosen latu” in Finnish) is a term that came from a two-hour cross-country skiing (preferably classic) exercise and is now a synonym for any longer training pass (run, ski, hike, whatever) of around or over two hours.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=LtHvM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=LtHvM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=11bTM"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=11bTM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/2/13/a-few-photo-fyi-s</feedburner:origLink></entry>
  <entry xml:base="http://jlaine.net/">
    <author>
      <name>jarkko</name>
    </author>
    <id>tag:jlaine.net,2008-02-12:2489</id>
    <published>2008-02-12T09:54:00Z</published>
    <updated>2008-02-12T09:57:35Z</updated>
    <category term="hd" />
    <category term="life" />
    <category term="tech" />
    <link href="http://feeds.feedburner.com/~r/jlainenet/~3/233658118/the-stupid-thing-aka-region-codes" rel="alternate" type="text/html" />
    <title>The best of times, the worst of times</title>
<content type="html">
            &lt;p&gt;I’m kind of sad that Blu-ray has taken the lead in the next generation digital video disc race, and that has little to do with the fact that &lt;a href="http://en.wikipedia.org/wiki/Sony_BMG#Controversy"&gt;I don’t really like Sony&lt;/a&gt;. The reason &lt;a href="http://arstechnica.com/news.ars/post/20080211-best-buy-netflix-join-hd-dvd-dogpile.html"&gt;the lurking death of &lt;span class="caps"&gt;HD DVD&lt;/span&gt;&lt;/a&gt; makes me really sad is that while it has smaller capacity than BD, it has one thing really going for it: &lt;strong&gt;it’s void of one of the pests of modern times: regional codes.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://adactio.com/journal/1404"&gt;Jeremy Keith recently wrote&lt;/a&gt; about &lt;span class="caps"&gt;DVD&lt;/span&gt;’s and Wii games that he bought during his Christmas trip to US &lt;em&gt;that he cannot use&lt;/em&gt; because they are limited to be played only by a player with the US region code. Now, there are region code-free players available, but that only makes the whole scheme more pointless.&lt;/p&gt;


	&lt;p&gt;Now, with &lt;span class="caps"&gt;HD DVD&lt;/span&gt; being free of the region codes, we could have gotten rid of them once and for all. However, with Blu-ray seemingly winning the war, we seem to be stuck with the same hassle into the unforeseeable future. And people wonder why Pirate Bay is the #1 movie distribution channel in Europe these days…&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=3AeUmtE"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=3AeUmtE" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jlainenet?a=SfQfpJE"&gt;&lt;img src="http://feeds.feedburner.com/~f/jlainenet?i=SfQfpJE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content>  <feedburner:origLink>http://jlaine.net/2008/2/12/the-stupid-thing-aka-region-codes</feedburner:origLink></entry>
</feed>
