<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;AkUHSHc9cSp7ImA9Wx5TEks.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806</id><updated>2010-07-28T00:03:59.969+02:00</updated><title>public interface</title><subtitle type="html">news from conan's brain</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.conandalton.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>102</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/PublicInterface" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="publicinterface" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0AMQXs8fSp7ImA9WxFUFEQ.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-1097568082963280626</id><published>2010-06-25T23:03:00.000+02:00</published><updated>2010-06-25T23:03:00.575+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-25T23:03:00.575+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="politics" /><title>Go to prison for sharing music with your friends</title><content type="html">&lt;p&gt;According to a leaked document obtained by La Quadrature du Net, our delightful EU leaders want to &lt;a href="http://www.laquadrature.net/en/leak-eu-pushes-for-criminalizing-non-commercial-usages-in-acta"&gt;criminalise not-for-profit music&lt;/a&gt; sharing, as part of ongoing ACTA negotiations. In other words, you do some free marketing on behalf of Big Content Industry, they put you in jail. Is this the kind of world you want to live in?&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="http://www.boingboing.net/2010/06/24/eu-secretly-pushing.html"&gt;boingboing&lt;/a&gt; for the link.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-1097568082963280626?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/r-8AHvi9I6c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/1097568082963280626/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/06/go-to-prison-for-sharing-music-with.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/1097568082963280626?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/1097568082963280626?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/06/go-to-prison-for-sharing-music-with.html" title="Go to prison for sharing music with your friends" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;CUYMQXw-eCp7ImA9WxFVGEQ.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-690335000226124298</id><published>2010-06-18T22:33:00.000+02:00</published><updated>2010-06-18T22:33:00.250+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-18T22:33:00.250+02:00</app:edited><title>"PassengerEnabled off" not working</title><content type="html">&lt;p&gt;We needed to disable a Rails site for a little bit and figured &lt;code&gt;PassengerEnabled off&lt;/code&gt; and a little bit of apache mod_rewrite would do the trick in the least painful way ... but Passenger refused to turn itself off and kept serving our (slightly broken) rails app!
&lt;/p&gt;

&lt;p&gt;After some hours of bewildered searching and starting to doubt our sanity, we found the culprit: &lt;code&gt;PassengerHighPerformance on&lt;/code&gt; - cut that line and &lt;code&gt;PassengerEnabled off&lt;/code&gt; works as advertised.&lt;p&gt;

&lt;p&gt;This is not even slightly &lt;a href="http://www.modrails.com/"&gt;Phusion&lt;/a&gt;'s fault, btw - &lt;code&gt;PassengerHighPerformance&lt;/code&gt; is clearly marked as experimental and flaky in their &lt;a href="http://www.modrails.com/documentation/Users%20guide.html"&gt;excellent docs&lt;/a&gt;. What we need to do, in the general case, is figure out a foolproof way of advertising the presence of a potentially buggy option in our config files (whatever the software product is) so it's easy for any team member to eliminate likely causes of incorrect behaviour when the bug-hunt is on.&lt;/p&gt;

&lt;p&gt;This article is a start, I guess :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-690335000226124298?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/GRYdWN3Vz44" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/690335000226124298/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/690335000226124298?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/690335000226124298?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html" title="&quot;PassengerEnabled off&quot; not working" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;D0YCSXsyfSp7ImA9WxBWGU8.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-9144914386771847036</id><published>2010-02-11T22:15:00.005+01:00</published><updated>2010-02-11T22:52:48.595+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-11T22:52:48.595+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>ActionMailer and Multiple SMTP Accounts (useful with gmail)</title><content type="html">&lt;p&gt;
ActionMailer works with only one smtp account; a single google apps account is limited to 500 (or 2000) mails per day; my app legitimately needs more. Besides, I'd rather notifications come from an appropriately named account rather than a generic "no-reply@example.com" address. Here's what I came up with. Firstly, &lt;code&gt;config/smtp.yml&lt;/code&gt; describes my various accounts - I settled on one per mailer class. Secondly, a patch to &lt;code&gt;ActionMailer::Base&lt;/code&gt; enables switching smtp accounts based on the mailer class.
&lt;/p&gt;

&lt;p&gt;
Here's an example with four mailers: an account mailer, an exception notifier (works with the lovely &lt;a href="http://github.com/rails/exception_notification"&gt;ExceptionNotifier plugin&lt;/a&gt;), a "share this" mailer so your site can be all viral and stuff, and a prize mailer for the good news.
&lt;/p&gt;

&lt;h4&gt;config/smtp.yml&lt;/h4&gt;

&lt;pre&gt;defaults: &amp;defaults
  address:        smtp.gmail.com
  port:           587
  domain:         example.com
  authentication: !ruby/sym plain

account_mailer:
  &lt;&lt;: *defaults
  user_name:      accounts@example.com
  password:       "pw1"

prize_mailer:
  &lt;&lt;: *defaults
  user_name:      winner@example.com
  password:       "pw2"

exception_notifier:
  &lt;&lt;: *defaults
  user_name:      dev_team_obviously_sucks@example.com
  password:       "pw3"

share_this_mailer:
  &lt;&lt;: *defaults
  user_name:      share_this@example.com
  password:       "pw4"
&lt;/pre&gt;


&lt;h4&gt;ActionMailer::Base patch&lt;/h4&gt;
&lt;pre&gt;require 'smtp_tls'

module ActionMailer
  class Base
    cattr_accessor :smtp_config

    self.smtp_config = YAML::load(File.open("#{RAILS_ROOT}/config/smtp.yml"))

    &lt;strong&gt;def smtp_settings
      smtp_config[mailer_name].symbolize_keys
    end&lt;/strong&gt;
  end
end
&lt;/pre&gt;

&lt;p&gt;
I put this in &lt;code&gt;config/initializers/action_mailer.rb&lt;/code&gt;. 

And that's it! 

No changes required to your mailers or email templates or anything else in your application. 

As you can see, the patch merely overrides ActionMailer's smtp_settings class method 
and replaces it with an instance method that decides at sending-time which smtp configuration to use.
&lt;/p&gt;

&lt;p&gt;
We needed to do this because sendmail was failing erratically - 
some users weren't getting any mail from our app at all - 
presumably due to hypersensitive spam filters somewhere on the chain, 
maybe related to my not understanding how SPF records are supposed to work. 
&lt;/p&gt;

&lt;p&gt;
You could easily fancify this to switch SMTP config based on the time of day, 
or based on your user's locale 
(so you can use a nicely localised "from" address - Google overrides the "from" address sent by ActionMailer), 
or even based on whether the Moon is in Scorpio if you cared.

Just replace the call to &lt;code&gt;mailer_name&lt;/code&gt; with a call to your config-switching method.
&lt;/p&gt;

&lt;p&gt;
I understand that rails 3 is beautifuller in many ways including the way ActionMailer works so this might well be obsolete in a few months except for you suckers working on legacy systems. 

I hope this helps, let me know one way or the other.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-9144914386771847036?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/AudgUEDks58" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/9144914386771847036/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/02/actionmailer-and-multiple-smtp-accounts.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/9144914386771847036?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/9144914386771847036?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/02/actionmailer-and-multiple-smtp-accounts.html" title="ActionMailer and Multiple SMTP Accounts (useful with gmail)" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkYGRns8eyp7ImA9WxBWFUs.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-6266136076119816488</id><published>2010-02-07T19:41:00.000+01:00</published><updated>2010-02-07T19:42:07.573+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-07T19:42:07.573+01:00</app:edited><title>it wasn't git actually</title><content type="html">&lt;p&gt;Ouch! Panic!&lt;/p&gt;

&lt;pre&gt;$ git push origin master
fatal: unable to fork&lt;/pre&gt;

&lt;p&gt;and later,&lt;p&gt;

&lt;pre&gt;$ git push origin master
fatal: git-pack-objects failed (Resource temporarily unavailable)&lt;/pre&gt;

&lt;p&gt;But it had nothing to do with git or a corrupted repository as google seemed to be trying to
suggest; it was rather my trusty mac running out of something. The solution: shut down itunes
and try again.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-6266136076119816488?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/yTN5SO-w1-8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/6266136076119816488/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/02/it-wasnt-git-actually.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/6266136076119816488?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/6266136076119816488?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/02/it-wasnt-git-actually.html" title="it wasn't git actually" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUAGQX8_eip7ImA9WxBXGEU.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-8903406092366824672</id><published>2010-01-30T22:42:00.001+01:00</published><updated>2010-01-30T22:42:00.142+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-30T22:42:00.142+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Upgrading Gutsy to Hardy</title><content type="html">&lt;p&gt;
My slicehost slice was running Gutsy (Ubuntu 7.10), but when I switched my projects from my personal svn server to github, gutsy only had an early version of git that doesn't support &lt;code&gt;submodule&lt;/code&gt; ... the only way to upgrade git was to upgrade my ubuntu.
&lt;/p&gt;

&lt;p&gt;
After a quick mysql backup, these are the instructions that worked:
&lt;/p&gt;

&lt;pre&gt;
sudo vi /etc/apt/sources.list
# [ replace each "gutsy" with "hardy" ]
sudo apt-get update
sudo apt-get dist-upgrade
&lt;/pre&gt;

&lt;p&gt;
I found this solution on &lt;a href="http://www.ubuntugeek.com/upgrade-ubuntu-710-gutsy-gibbon-to-ubuntu-804-lts-hardy-heron.html"&gt;ubuntugeek.com&lt;/a&gt;.
It worked first time, like a charm. Congratulations ubuntu team ... linux has come a long, long way
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-8903406092366824672?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/87xAPSYJiA8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/8903406092366824672/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/01/upgrading-gutsy-to-hardy.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8903406092366824672?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8903406092366824672?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/01/upgrading-gutsy-to-hardy.html" title="Upgrading Gutsy to Hardy" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkUGRX0zfip7ImA9WxBWFUs.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-2571102706977623228</id><published>2010-01-29T22:47:00.001+01:00</published><updated>2010-02-07T19:43:44.386+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-07T19:43:44.386+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Back up your mysql database with mysqldump</title><content type="html">&lt;p&gt;
I don't use this often so I end up googling it every time I need it.
&lt;/p&gt;

&lt;pre&gt;
mysqldump -u root -p database_name &amp;gt; sql_dump_file
&lt;/pre&gt;


&lt;p&gt;
Now I know exactly where to find it and I don't have to scan a whole article just to get the syntax.
&lt;/p&gt;

&lt;p&gt;
Change "root" to the user you normally use; you an also specify &lt;code&gt;-ppassword&lt;/code&gt; (no space between &lt;code&gt;-p&lt;/code&gt; and the password) so you don't have to enter the password interactively ... security issues etc but if you're running this from a script I'm not sure what the alternative is.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-2571102706977623228?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/-SbXBOBb6o0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/2571102706977623228/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/01/back-up-your-mysql-database-with.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2571102706977623228?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2571102706977623228?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/01/back-up-your-mysql-database-with.html" title="Back up your mysql database with mysqldump" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DU8MQHs-eyp7ImA9WxBXF0g.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-4918375545055280560</id><published>2010-01-28T22:42:00.000+01:00</published><updated>2010-01-29T10:38:01.553+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-29T10:38:01.553+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="politics" /><title>What kind of World do You want to inhabit?</title><content type="html">Whatever you think of Stallman, go have a look at this &lt;a href="http://www.gnu.org/philosophy/right-to-read.html"&gt;quick dystopia&lt;/a&gt;, and imagine what kind of world you would like to live in. Then head over to boingboing and learn about &lt;a href="http://boingboing.net/2009/11/03/secret-copyright-tre.html"&gt;ACTA&lt;/a&gt;. I preferred the days when Russia and China were the bad guys, and they were far away.&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-4918375545055280560?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/gjW9_15KU6I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/4918375545055280560/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/01/what-kind-of-world-do-you-want-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/4918375545055280560?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/4918375545055280560?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/01/what-kind-of-world-do-you-want-to.html" title="What kind of World do You want to inhabit?" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0INQHg4cCp7ImA9WxBXF0w.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-1019102268705058541</id><published>2010-01-27T21:48:00.003+01:00</published><updated>2010-01-28T22:53:11.638+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-28T22:53:11.638+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>It should have no missing translations!</title><content type="html">&lt;p&gt;
I'm a big fan of rspec and of rails' I18n, and I don't like having to study yml translation files over and
over to make sure every key has a translation in every language; so I wrote
&lt;code&gt;it_should_have_no_missing_translations&lt;/code&gt; to test my templates for missing
translations.
&lt;/p&gt;

&lt;p&gt;
Previously, I needed this for every template:
&lt;/p&gt;

&lt;pre&gt;
  it "should have no missing translations in fr" do
    I18n.locale = "fr"
    do_render
    response.should_not have_tag("span.translation_missing")
  end

  it "should have no missing translations in en" do
    I18n.locale = "en"
    do_render
    response.should_not have_tag("span.translation_missing")
  end
&lt;/pre&gt;

&lt;p&gt;
Where &lt;code&gt;do_render&lt;/code&gt; knows how to render the template I'm testing.
If you're like me, and I presume you are, you're thinking the duplication up there is a
bit annoying and someone should do something about it. Well, here you go:
&lt;/p&gt;

&lt;pre&gt;
  it_should_have_no_missing_translations
&lt;/pre&gt;

&lt;p&gt;
You like? Obviously, &lt;code&gt;it_should_have_no_missing_translations&lt;/code&gt; needs a bit of context, like
an implementation of &lt;code&gt;do_render&lt;/code&gt;, and any other setup you need. Here's the implementation,
under the &lt;a href="http://sam.zoy.org/wtfpl/"&gt;WTFPL&lt;/a&gt;. Copy it into your specs or make a helper out
of it that you include in your spec, or publish it in a gem and become famous.
&lt;/p&gt;

&lt;pre lang="ruby"&gt;
  def it_should_have_no_missing_translations
    INSTALLED_LANGUAGES.each do |lang|
      it "should not have translations missing in #{lang}" do
        I18n.locale = lang
        do_render
        response.should_not have_missing_translations
      end
    end
  end
&lt;/pre&gt;

&lt;p&gt;
  &lt;code&gt;have_missing_translations&lt;/code&gt; is defined thus:
&lt;/p&gt;

&lt;pre lang="ruby"&gt;
  INSTALLED_LANGUAGES = [:en, :fr] unless defined?(INSTALLED_LANGUAGES)

  class TranslationsMissing
    def initialize(scope)
      @scope = scope
    end

    def matches? response
      if response.is_a? String
        root_node = HTML::Document.new(response, false, false).root
      else
        root_node = HTML::Document.new(response.body, false, false).root
      end
      m = @scope.css_select root_node, ".translation_missing"
      @missing_translations = []
      m.each do |mt|
        @missing_translations &amp;lt;&amp;lt; mt.children.first
      end
      m.size &gt; 0
    end

    def failure_message
      "expected that response would contain a translation_missing element, but it didn't"
    end

    def negative_failure_message
      "expected that response would contain no missing translations, but it contained these \n#{@missing_translations.join("\n")}"
    end
  end

  def have_missing_translations
    TranslationsMissing.new self
  end

&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-1019102268705058541?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/vAfXNsxx60k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/1019102268705058541/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2010/01/it-should-have-no-missing-translations.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/1019102268705058541?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/1019102268705058541?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2010/01/it-should-have-no-missing-translations.html" title="It should have no missing translations!" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkQMRnYzfip7ImA9WxBXFk8.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-551176099183465048</id><published>2009-11-17T22:00:00.001+01:00</published><updated>2010-01-27T22:39:47.886+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-27T22:39:47.886+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nonsense" /><category scheme="http://www.blogger.com/atom/ns#" term="france" /><title>FOODOPI - coming soon to a nation near you!</title><content type="html">&lt;p&gt;
IP news from France. My translation probably isn't perfect. There are other things to worry about, too.
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p style="text-align:justify"&gt;
Watching the evilly smug faces of recording industry executives following France's recent adoption of Hadopi, restaurant owners have decided they deserved a slice of the IP pie, too. Watch out for the new law to be introduced later this year: FOODOPI!
&lt;/p&gt;
&lt;p style="text-align:justify"&gt;
Restaurant managers, owners, and chefs who have dedicated years of their talent, skill, and secret sauce to creating irresistible mouthwatering dishes have watched in dismay as food pirates illegally copy their ideas, recreating such classics as Ratatouille, Chicken Curry with Rice, and Spaghetti Bolognese with impunity in their own homes.
&lt;/p&gt;
&lt;p style="text-align:justify"&gt;
This is all going to change and the impoverished actors of the restauration industry will finally see their hard work rewarded and &lt;i&gt;protected&lt;/i&gt;. The new FOODOPI law, if adopted, will allow restaurant industry executives name individuals suspected of recipe pirating and, after three warnings, those individuals will be prohibited from cooking for a length of time varying from six months to ten years.
&lt;/p&gt;
&lt;p style="text-align:justify"&gt;
Although the lack of judicial review during the prohibition process has raised concerns among civil liberties groups, a spokesperson for a French restaurateur's association observed "the justice system is already overstretched and it makes no sense to burden it even further. This law is a huge win for the public, ensuring continued innovation in the food service industry. It would be a disservice to the public and a drain on limited taxpayer resources to push this through the courts."
&lt;/p&gt;
&lt;p style="text-align:justify"&gt;
A spokesperson for a US-based organisation conducting cutting-edge research on genetic improvement of popular crops said while they would vigourously defend their IP in France under this new law, "currently we have no intention of prosecuting the most widespread violation of our intellectual property: the use of sodium chloride as a food additive for flavour enhancement". &lt;i&gt;[A lawyer friend has advised me that this patent may not be applicable in France anyway as the use of "table salt" (to use pirate jargon) is a popular custom in this country, dating back centuries - ed.]&lt;/i&gt;
&lt;/p&gt;
&lt;p style="text-align:justify"&gt;
While the details of the new system have yet to be worked out, a leaked document obtained by this site indicates some of the strategies being considered -
&lt;/p&gt;
&lt;ul&gt;
&lt;li style="text-align:justify"&gt;Government-mandated cooking equipment for all new domestic kitchen installations with remote sensing equipment for ambient atmospheric analysis, allowing FOODOPI investigators detect potential violations of food industry IP by comparing chemicals and food traces in the air with a database of protected recipes.&lt;/li&gt;
&lt;li style="text-align:justify"&gt;Food retailers will report purchases to a central database that will apply sophisticated pattern-matching algorithms to identify individuals who may be planning IP violations. As an example, the document describes a hypothetical shopper in the process of acquiring 500g basmati rice, 8 chicken thighs, unflavoured yoghurt, turmeric, ginger, and garlic. The proposed pattern-matching software would flag this shopper as a potential pirate about to prepare Chicken Curry with Rice for 4.&lt;/li&gt;
&lt;li style="text-align:justify"&gt;Repeat offenders would ultimately have all kitchen equipment confiscated and perhaps have a camera installed in their homes to deter future violations&lt;/li&gt;
&lt;/ul&gt;

&lt;p style="text-align:justify"&gt;
The document also noted some concerns of IP holders, including the threat of violations by picknickers and people using obsolete or camping equipment, where monitoring systems are less feasible.
&lt;/p&gt;
&lt;/blockquote&gt;

Put that in your pipe and smoke it.&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-551176099183465048?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/1seYwqsVtiQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/551176099183465048/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/11/foodopi-coming-soon-to-nation-near-you.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/551176099183465048?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/551176099183465048?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/11/foodopi-coming-soon-to-nation-near-you.html" title="FOODOPI - coming soon to a nation near you!" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUUDQn44cCp7ImA9WxNXE0k.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-8996456899586280647</id><published>2009-09-30T22:37:00.002+02:00</published><updated>2009-09-30T22:41:13.038+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-30T22:41:13.038+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>mass file rename using mv and sed</title><content type="html">&lt;p&gt;I wanted to re-organise my config/locale directory because translation files for the same stuff were too far from each other. I had&lt;/p&gt;

&lt;pre&gt;config/locales
  en
    foo.yml
    bar.yml
  fr
    foo.yml
    bar.yml
&lt;/pre&gt;

&lt;p&gt;It was too much of a pain to switch quickly between en/foo.yml and fr/foo.yml. So now I have&lt;/p&gt;

&lt;pre&gt;config/locales
  foo.en.yml
  foo.fr.yml
  bar.en.yml
  bar.fr.yml
&lt;/pre&gt;

&lt;p&gt;except it's not four files, it's dozens. So I needed a mass-rename shell script to rename many files at once:&lt;/p&gt;

&lt;pre&gt;
PATTERN=$1
shift
for file in $*
do
mv "$file" `echo "$file" | sed ${PATTERN}`
done
&lt;/pre&gt;

&lt;p&gt;It combines mv and sed to rename files based on patterns in their names. Invoke thus:&lt;/p&gt;

&lt;pre&gt;
cd config/locales/en
mvsed s/yml/en.yml/g *.yml
&lt;/pre&gt;

&lt;p&gt;Repeat for each language, and then just move all the yml files up to the parent directory, and you're done. You can use this for lots of renaming operations, and as you will have noticed, you don't need to be a sed guru to figure out basic patterns. This script works with bash on my macos 10.5; I imagine it will work with little alteration on the sensible non-MSDOS shell you're using.&lt;/p&gt;

&lt;p&gt;Acknowledgements to &lt;a href="http://www.linuxforums.org/forum/linux-newbie/152699-need-script-mass-rename-files-recursively.html"&gt;linuxforums.org / dnielsen78&lt;/a&gt; for the inspiration for this script, and to everyone else who wrote this first.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-8996456899586280647?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/T6YozXlt33s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/8996456899586280647/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/09/mass-file-rename-using-mv-and-sed.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8996456899586280647?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8996456899586280647?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/09/mass-file-rename-using-mv-and-sed.html" title="mass file rename using mv and sed" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEcFQ304cCp7ImA9WxJUEEg.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-2804770469814627423</id><published>2009-07-08T14:22:00.007+02:00</published><updated>2009-07-08T14:26:52.338+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-08T14:26:52.338+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parenting" /><title>Don't misunderestimate your children</title><content type="html">&lt;p&gt;I was reading a Wallace and Gromit story to my (now 5-year-old) son, and he energetically pointed out&lt;/p&gt;

&lt;table class="drama"&gt;
  &lt;tr&gt;
    &lt;th&gt;son&lt;/th&gt;
    &lt;td&gt;Look, a grandfather clock!&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;me&lt;/th&gt;
    &lt;td&gt;Yes, that's a grandfather clock. It's about to fall on top of Wallace!&lt;/td&gt;
  &lt;tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Wallace&lt;/th&gt;
    &lt;td&gt;That's just the thing, my lad, we'll have to turn back the clock ...&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;son&lt;/th&gt;
    &lt;td&gt;What's "turn back the clock" ?&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;me&lt;/th&gt;
    &lt;td&gt;Well, suppose something happened yesterday that you weren't happy about, so you decide to &amp;lt;blah blah long-winded explanation of expression with digression into the role of metaphor in language&amp;gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;son&lt;/th&gt;
    &lt;td&gt;Oh, you mean he builds a &lt;i style="font-size:100%;"&gt;time machine&lt;/i&gt;?&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Duh. I should have realised time travel is a standard part of every 5-year-old's vocabulary.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-2804770469814627423?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/gL1uFeFSpVw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/2804770469814627423/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/07/dont-misunderestimate-your-children.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2804770469814627423?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2804770469814627423?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/07/dont-misunderestimate-your-children.html" title="Don't misunderestimate your children" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkMAR3c-eSp7ImA9WxJXFU4.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-7503602930886516891</id><published>2009-06-09T11:05:00.002+02:00</published><updated>2009-06-09T11:07:26.951+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-09T11:07:26.951+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iconfu" /><title>New Iconfu</title><content type="html">&lt;p&gt;The latest iconfu, released yesterday, sports these improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;undo/redo with ctl-z and ctl-shift-z, respectively.&lt;/li&gt;
&lt;li&gt;save as BMP! (careful though, BMP has no transparency, so transparent pixels are likely to come out black. You should edit your chosen icon and add an opaque background)&lt;/li&gt;
&lt;li&gt;The default paypal page is now English, not French. Thanks to Paul Graham for &lt;a href="http://news.ycombinator.com/item?id=636499"&gt;pointing out this problem&lt;/a&gt;, and thanks to &lt;a href="http://blog.brains4all.com/brainblog/archives/2008/04/paypal_language.html"&gt;brains4all&lt;/a&gt; for the solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This release comes with thanks to Utku Karatas for some great suggestions.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-7503602930886516891?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/0fRGbRNYjkg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/7503602930886516891/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/06/new-iconfu.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/7503602930886516891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/7503602930886516891?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/06/new-iconfu.html" title="New Iconfu" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0cHRHg_fip7ImA9WxVaFk8.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-2283173275825021845</id><published>2009-04-13T12:22:00.004+02:00</published><updated>2009-04-13T13:10:35.646+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-13T13:10:35.646+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iconfu" /><title>The Many Faces of Iconfu</title><content type="html">&lt;p&gt;Not all colours are equal, and not all backgrounds are white. What do you do when you're designing an icon for a site with a dark background? You change the background of your &lt;a href="http://iconfu.com"&gt;favourite icon editor&lt;/a&gt;, of course!
&lt;/p&gt;&lt;p&gt;
&lt;img src="http://2.bp.blogspot.com/_7sjE3SRdZhk/SeMS4HGQAZI/AAAAAAAAAIk/czD-SCnhGM0/s400/Picture+156.png" alt="iconfu" /&gt;
&lt;/p&gt;&lt;p&gt;
&lt;img src="http://4.bp.blogspot.com/_7sjE3SRdZhk/SeMS36wvaFI/AAAAAAAAAIc/TVv1xvMgDOk/s400/Picture+155.png" alt="iconfu"/&gt;
&lt;/p&gt;&lt;p&gt;
&lt;img src="http://2.bp.blogspot.com/_7sjE3SRdZhk/SeMSsfK_rzI/AAAAAAAAAIM/IHkVkx27zhk/s400/Picture+153.png" alt=""/&gt;
&lt;/p&gt;&lt;p&gt;
&lt;img src="http://4.bp.blogspot.com/_7sjE3SRdZhk/SeMSsH82zCI/AAAAAAAAAIE/iHumo1z5qY0/s400/Picture+152.png" alt=""/&gt;
&lt;/p&gt;&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/_7sjE3SRdZhk/SeMSr0ZMzFI/AAAAAAAAAH8/62J4zmiyMO4/s400/Picture+151.png" alt=""/&gt;
&lt;/p&gt;&lt;p&gt;
&lt;img src="http://1.bp.blogspot.com/_7sjE3SRdZhk/SeMSrqLdr_I/AAAAAAAAAH0/8i5B_mDZ5_M/s400/Picture+150.png" alt=""/&gt;
&lt;/p&gt;&lt;p&gt;
It's easy to do: in the colour chooser, choose the colour you want to use for the background, open the "appearance" panel on the bottom right, and click "use current colour" for "background". Voilà!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-2283173275825021845?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/5N_nezZXsrw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/2283173275825021845/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/04/many-faces-of-iconfu.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2283173275825021845?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2283173275825021845?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/04/many-faces-of-iconfu.html" title="The Many Faces of Iconfu" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_7sjE3SRdZhk/SeMS4HGQAZI/AAAAAAAAAIk/czD-SCnhGM0/s72-c/Picture+156.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUIAQX05eSp7ImA9WxVaEU8.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-8383078105546498620</id><published>2009-04-07T18:58:00.000+02:00</published><updated>2009-04-07T18:59:00.321+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-07T18:59:00.321+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iconfu" /><title>New iconfu</title><content type="html">The &lt;a href="http://iconfu.com"&gt;latest and greatest iconfu&lt;/a&gt; is here:

&lt;ul&gt;
&lt;li&gt;A shiny new colour selector with HSV sliders as well as RGB sliders and a palette of basic colours (with instant conversion between HSV and RGB)&lt;/li&gt;
&lt;li&gt;Automatic preview-as-favicon of your work in progress&lt;/li&gt;
&lt;li&gt;Comment on icons&lt;/li&gt;
&lt;li&gt;"who's online" so you know you're not alone&lt;/li&gt;
&lt;li&gt;Three quick built-in tutorials so you can start using the most powerful iconfu features straight away&lt;/li&gt;
&lt;li&gt;Gravatar integration so you have more control over your online identity&lt;/li&gt;
&lt;li&gt;Search for icons within a particular collection while editing&lt;/li&gt;
&lt;li&gt;Easliy draw anti-aliased straight lines&lt;/li&gt;
&lt;li&gt;Fixed GIF downloading - some icons would fail to download as GIF due to internal errors&lt;/li&gt;
&lt;/ul&gt;


Enjoy! And &lt;a href="http://www.killerstartups.com/Web-App-Tools/iconfu-com-editing-icons-the-web-2-0-way"&gt;go vote for iconfu at killerstartups.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-8383078105546498620?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/hlJDypqFA2o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/8383078105546498620/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/04/new-iconfu.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8383078105546498620?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8383078105546498620?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/04/new-iconfu.html" title="New iconfu" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkQDRHY5cSp7ImA9WxVbEkk.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-6385599742071134203</id><published>2009-03-28T12:14:00.007+01:00</published><updated>2009-03-28T13:46:15.829+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-28T13:46:15.829+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Chart in Javascript</title><content type="html">&lt;p&gt;

There aren't enough bar-chart-drawing implementations out there yet, so this article will present the best one yet. It looks like this:

&lt;/p&gt;&lt;p&gt;

&lt;img src="http://1.bp.blogspot.com/_7sjE3SRdZhk/Sc4HZihq53I/AAAAAAAAAHk/aGwCy_tiSBQ/s400/Picture+144.png" alt="a chart made with javascript" id="BLOGGER_PHOTO_ID_5318196345317287794" border="0" /&gt;

&lt;/p&gt;&lt;p&gt;

Or several little charts in a row, like this:

&lt;/p&gt;&lt;p&gt;

&lt;img src="http://4.bp.blogspot.com/_7sjE3SRdZhk/Sc4bVnl1rhI/AAAAAAAAAHs/yJYd0o4l7BI/s400/Picture+146.png" alt="several bar charts in a row" id="BLOGGER_PHOTO_ID_5318218268190027282" border="0" /&gt;

&lt;/p&gt;&lt;p&gt;

Features:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Really easy to use&lt;/li&gt;
&lt;li&gt;mouse move highlights bar under mouse&lt;/li&gt;
&lt;li&gt;pops up tooltip with information for the bar under the mouse&lt;/li&gt;
&lt;li&gt;All colours are configurable&lt;/li&gt;
&lt;li&gt;Scales data automatically to height of canvas&lt;/li&gt;
&lt;li&gt;Calculates thickness of bars automatically so all fit in the width of the canvas&lt;/li&gt;
&lt;li&gt;Redraw data as often as you want - for example with data from an ajax call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

The tooltip is missing from this screenshot. My mac hides the tooltip before it takes the screenshot unfortunately.

&lt;/p&gt;&lt;p&gt;

Anyway, I'd like to convince you that it's really, really easy to use. Supply your data in JSON format like this:

&lt;/p&gt;

&lt;pre&gt;
var data = [
[ "week 1", "1000" ],
[ "week 2", "2000" ],
[ "week 3", "3000" ]
];
&lt;/pre&gt;

&lt;p&gt;

Declare a &lt;code&gt;canvas&lt;/code&gt; element:

&lt;/p&gt;

&lt;pre&gt;
&amp;lt;canvas id="weekly_chart" width="200" height="80"&amp;gt;&amp;lt;/canvas&amp;gt;
&lt;/pre&gt;

&lt;p&gt;

Then just call the &lt;code&gt;Chart(canvas_element, bar_colour, bg_colour, hilite_colour)&lt;/code&gt; constructor:

&lt;/p&gt;

&lt;pre&gt;
var chart = new Chart($('weekly_chart'), "rgb(128,128,255)", "rgb(0,0,0)", "rgb(255,255,128)");
&lt;/pre&gt;

&lt;p&gt;

Then, draw your data

&lt;/p&gt;

&lt;pre&gt;
chart.draw(data);
&lt;/pre&gt;

&lt;p&gt;

It couldn't be simpler!

&lt;/p&gt;&lt;p&gt;

Here's the code. Just include it somwhere in your page. It's free under a &lt;a href="http://creativecommons.org/licenses/by-sa/3.0/"&gt;Creative Commons Attribution Share-Alike 3.0&lt;/a&gt; license - you can use, re-use, modify, redistribute, as long as you link back to this page and (re)distributions carry the same or a compatible license. It has a slight dependency on Prototype (2 calls) but you jQuery people will fix that quickly (in fact, you might even leave a comment with the jQuery alternative). Theoretically, it will work on Internet Exploder using Google's &lt;a href="http://excanvas.sourceforge.net/"&gt;excanvas&lt;/a&gt;, although I haven't tested this configuration.

&lt;/p&gt;

&lt;pre&gt;
(function() {
  function max(data) {
    var max = 0;
    for (var i = 0; i &lt; data.length; i++) {
      if (data[i][1] &gt; max) {
        max = data[i][1];
      }
    }
    return max;
  }

  function coords(event, element, f) {
    var offset = $(element).cumulativeOffset();   // $ from prototype
    var p = Event.pointer(event || window.event); // Event.pointer from prototype
    var y = p.y - offset.top;
    var x = p.x - offset.left;
    f(y, x);
  }

  window.Chart = function(canvas, fg, bg, hilite) {
    if (!canvas || !canvas.getContext) {
      return;
    }

    var cx = canvas.getContext('2d');

    this.draw = function(data) {
      cx.clearRect(0, 0, canvas.width, canvas.height);
      var thick = canvas.width / data.length;
      var scale = canvas.height / max(data);

      function highlightBars(index) {
        cx.lineWidth = 1;

        for (var i = 0; i &lt; data.length; i++) {
          if (i == index || i == (index + 1)) {
            cx.strokeStyle = hilite;
          } else {
            cx.strokeStyle = bg;
          }
          cx.beginPath();
          cx.moveTo((i * thick) + 0.5, 0);
          cx.lineTo((i * thick) + 0.5, canvas.height);
          cx.stroke();
        }
      }

      cx.fillStyle = bg;
      cx.fillRect(0, 0, canvas.width, canvas.height);

      cx.fillStyle = fg;

      for (var i = 0; i &lt; data.length; i++) {
        var h = data[i][1] * scale;
        if (!isNaN(h)) {
          cx.fillRect(i * thick, canvas.height - h, thick, h);
        }
      }

      highlightBars(-2);


      canvas.onmouseout = function(event) {
        highlightBars(-2);
      };

      canvas.onmousemove = function(event) {
        coords(event, canvas, function(y, x) {
          var index = ((x-1) / thick).floor();
          if (index &lt; 0) {
            index = 0;
          }
          highlightBars(index);

          var bar = data[index];
          if (bar) {
            canvas.title = bar[0] + " : " + bar[1];
          }
        });
      };
    };
  };
})();
&lt;/pre&gt;

&lt;p&gt;

This is the simple version. Feel free to comment with improvements, I'll keep the code up to date with my favourite suggestions.

&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-6385599742071134203?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/f_kyD5ba3Rk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/6385599742071134203/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/chart-in-javascript.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/6385599742071134203?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/6385599742071134203?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/chart-in-javascript.html" title="Chart in Javascript" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_7sjE3SRdZhk/Sc4HZihq53I/AAAAAAAAAHk/aGwCy_tiSBQ/s72-c/Picture+144.png" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;C0AMRXYzcSp7ImA9WxVbEEo.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-5379193970350924772</id><published>2009-03-26T12:43:00.003+01:00</published><updated>2009-03-26T13:49:44.889+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-26T13:49:44.889+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Spidering Internal Pages</title><content type="html">&lt;p&gt;
A url within an anchor tag in html may be &lt;i&gt;absolute&lt;/i&gt; or &lt;i&gt;relative&lt;/i&gt;. Absolute links look like &lt;code&gt;&amp;lt;a href='&lt;b&gt;http://iconfu.com&lt;/b&gt;'&amp;gt;iconfu ...&amp;lt;/a&amp;gt;&lt;/code&gt; - they start with a protocol. Relative links look like &lt;code&gt;&amp;lt;a href='&lt;b&gt;bar.html&lt;/b&gt;'&amp;gt;bar info ...&amp;lt;/a&amp;gt;&lt;/code&gt;. When you link to &lt;code&gt;bar.html&lt;/code&gt; from &lt;code&gt;http://example.com/pages/foo.html&lt;/code&gt;, the browser constructs the full reference and requests &lt;code&gt;http://example.com/pages/bar.html&lt;/code&gt;.
&lt;/p&gt;&lt;p&gt;
So far, so good.
&lt;/p&gt;&lt;p&gt;
Relative links may also be of the form &lt;code&gt;&amp;lt;a href='?browse=arrow'&amp;gt;arrow icons&amp;lt;/a&amp;gt;&lt;/code&gt;. A browser requesting this link from &lt;code&gt;http://iconfu.com/tags/list/0.html&lt;/code&gt; will construct this url: &lt;code&gt;http://iconfu.com/tags/list/0.html?browse=arrow&lt;/code&gt;
&lt;/p&gt;&lt;p&gt;
This can be convenient when the code or script that handles the requested page is separate from the code or script that handles the request parameters. This doesn't happen often, but when it does, it's useful to be able to construct the url without needing to know the originating page. For example, a login handler might be implemented as a filter before the page is rendered, so the login request would simply be &lt;code&gt;?username=foo&amp;password=bar&lt;/code&gt; ... this gets expanded by the browser into &lt;code&gt;http://example.com/pages/foo.html?username=foo&amp;password=bar&lt;/code&gt;. On the server, your login filter handles the login parameters, and your example/page script handles the rest of the url.
&lt;/p&gt;&lt;p&gt;
The bad news is that some spidering implementations handle this incorrectly (google's works fine). Instead of requesting &lt;code&gt;http://iconfu.com/tags/list/0.html?browse=arrow&lt;/code&gt; from the earlier example, they request &lt;code&gt;http://iconfu.com/tags/list?browse=arrow&lt;/code&gt; - they chop out "0.html". My code doesn't like this, and returns an error. Dumb MF spider implementations.
&lt;/p&gt;&lt;p&gt;
So that was that. Well, here's another bit of news: about 95% of visitors who come to iconfu through search, come from google. There are two ways to explain this: (1) google is the world's dominant search engine, who uses yahoo/live/ask.com anyway; (2) the clever people behind google analytics use some clever reporting techniques to show that google is the world's dominant search engine so why bother with the others.
&lt;/p&gt;&lt;p&gt;
We can eliminate (2) because as you know googlers Do No Evil. But today, in a flash of insight, I realised (3) perhaps those other search engines are sending me no visitors because they think my site is full of bugs and holes and 500 Internal Server Errors.
&lt;/p&gt;&lt;p&gt;
I'll fix that today and I'll let you know if I get a little more love from those unloved search engines. And then you can add "be careful with relative urls containing only a query string" to your SEO toolkit.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-5379193970350924772?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/CBreJsOO4bk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/5379193970350924772/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/spidering-internal-pages.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/5379193970350924772?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/5379193970350924772?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/spidering-internal-pages.html" title="Spidering Internal Pages" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C04ERXc5fyp7ImA9WxVbEEo.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-8519556193598259253</id><published>2009-03-26T12:40:00.002+01:00</published><updated>2009-03-26T13:51:44.927+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-26T13:51:44.927+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="social networking" /><category scheme="http://www.blogger.com/atom/ns#" term="france" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>Open Coffee Club Paris: For Sale</title><content type="html">&lt;p&gt;Open Coffee Club, Paris, 26 March 2009
&lt;/p&gt;&lt;p&gt;
A dude is making a speech about legal issues for startups. I don't like this. I come to OCC for peer-to-peer networking, not go get lectured at. This is hijacking an open, social event to allow one person dominate and control the discussion. Not only that, but my conversation was interrupted! This wastes my time, because I am deprived of the ability to choose the people I want to converse with. I expect to meet people either because they are interesting or their service is useful to me. I have no respect for a dude who has effectively bought* OCC as a platform to market his services, and I have no respect for an OCC willing to sell itself in this way.
&lt;/p&gt;&lt;p&gt;
Some people are politely paying attention. Others look bored and are wondering when this abuse will be over. And I have nobody to talk to :((
&lt;/p&gt;&lt;p style="font-size:small"&gt;
* "bought" in the moral sense. I have no idea how the dude in question obtained authority to hijack the group.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-8519556193598259253?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/MS_BlCGyUok" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/8519556193598259253/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/open-coffee-club-paris-for-sale.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8519556193598259253?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8519556193598259253?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/open-coffee-club-paris-for-sale.html" title="Open Coffee Club Paris: For Sale" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUMASXczcSp7ImA9WxVUFUs.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-8392876294535172566</id><published>2009-03-20T17:40:00.003+01:00</published><updated>2009-03-20T17:44:08.989+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-20T17:44:08.989+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Scaling Testing</title><content type="html">Check out &lt;a href="http://ejohn.org/blog/javascript-testing-does-not-scale/"&gt;TestSwarm by John Resig&lt;/a&gt; - it's like &lt;a href="http://setiathome.ssl.berkeley.edu/"&gt;SETI@Home&lt;/a&gt; for distributed testing ... isn't that a totally awesome concept? If you're having difficulty scaling your tests, especially if browser and OS combinations are wearing out your head, this is worth a look ...&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-8392876294535172566?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/8dTxdZmZ9Ww" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/8392876294535172566/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/scaling-testing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8392876294535172566?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/8392876294535172566?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/scaling-testing.html" title="Scaling Testing" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkcGSXg6eyp7ImA9WxVUFUs.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-2625483187338228152</id><published>2009-03-20T15:30:00.003+01:00</published><updated>2009-03-20T15:40:28.613+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-20T15:40:28.613+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Updating the security budget</title><content type="html">&lt;p&gt;

You might think in your cosy world of internal corporate web applications you don't need to worry about XSS and CSRF attacks (cross-site-scripting and cross-site request forgery) - after all, these are worries for public-facing web sites, not for us, surely?

&lt;/p&gt;&lt;p&gt;

Wrong!

&lt;/p&gt;&lt;p&gt;

Suppose your disgruntled employee leaves the project, and "in these times of crisis, you know", has nothing to do so gets scripting. Your disgruntled ex-employee, who previously worked on a precious sensitive internal system (aren't they all?), knows exactly which URLs will trigger a money transfer if accessed by persons with the right privileges, assuming they are logged in at the time.

&lt;/p&gt;&lt;p&gt;

Suppose that person is you - you're the manager of Whatsit and Whatnot after all, you have clearance for pretty much everything, and we used to do lunch together, so you'd happily open a link I sent you because it's sure to be interesting, entertaining, funny, informative, edifying ... you know, the kind of links I send to people.

&lt;/p&gt;&lt;p&gt;

But all I need to do is include this bit of code, which will be completely invisible to you:

&lt;/p&gt;&lt;pre&gt;
&amp;lt;form id="maliciousForm" action="http://internal.bank.example.com/transferMoney" style="display:none;"&amp;gt;
  &amp;lt;input type="hidden" name="from" value="myOldBossesAccount"/&amp;gt;
  &amp;lt;input type="hidden" name="to" value="myPersonalAccount"/&amp;gt;
&amp;lt;/form&amp;gt;

&amp;lt;script&amp;gt;document.forms.maliciousForm.submit();&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;p&gt;

If you happen to be logged in to http://internal.bank.example.com at the time (perhaps in another tab or window of your browser), that's all it takes to do the damage. To cover my tracks I'd need to be a lot smarter and more subtle, but the basic attack is trivial. And, more likely than not, your application isn't protected.

&lt;/p&gt;&lt;p&gt;

In fact, you don't even know what scripts are embedded in this page ... do you dare "view source" and check? What malicious clandestine script has executed while you were reading this paragraph?
&lt;script&gt;
  // ha-ha, fooled you, there's nothing here ...
&lt;/script&gt;

&lt;/p&gt;&lt;p&gt;

Time to run to the program manager and get a security budget extension! While you're at it, please don't shoot the messenger: smarter and meaner people than I (yes, they exist) have already thought of this. And even if your disgruntled ex-employee isn't that smart or mean, he might well be willing to sell his knowledge to someone who is.

&lt;/p&gt;&lt;p&gt;

For more information, see Adam Barth, Collin Jackson, and John C. Mitchell, &lt;a href="http://www.adambarth.com/papers/2008/barth-jackson-mitchell-b.pdf"&gt;Robust Defenses for Cross-Site Request Forgery&lt;/a&gt; (pdf). The most reliable defence involves ensuring all potentially harmful requests are made via POST, not GET; and then requiring that any POST request includes a secret token in its body (possibly via a hidden input); the server validates the secret token and allows the request to proceed only if the token is valid. Ruby on Rails provides framework methods for simplifying this (seriously: you call the &lt;code&gt;protect_from_forgery&lt;/code&gt; method).

&lt;/p&gt;&lt;p&gt;

Asking your corporate users to logout when they're not using your precious sensitive application is like asking dogs to stop wagging their tails. It's not going to happen. If security isn't &lt;i&gt;your&lt;/i&gt; problem, then it's a problem.

&lt;/p&gt;&lt;p&gt;

This post was inspired by the "Web application security horror stories" talk at &lt;a href="http://events.carsonified.com/fowa/2009/dublin/content"&gt;FOWA Dublin 2009&lt;/a&gt; by &lt;a href="http://simonwillison.net/"&gt;Simon Willison&lt;/a&gt;

&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-2625483187338228152?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/wFO9mzY7904" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/2625483187338228152/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/updating-security-budget.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2625483187338228152?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2625483187338228152?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/updating-security-budget.html" title="Updating the security budget" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcNRnY_fSp7ImA9WxVUFUk.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-5314100887766728973</id><published>2009-03-20T12:05:00.004+01:00</published><updated>2009-03-20T12:21:37.845+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-20T12:21:37.845+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iconfu" /><title>Unambiguous Icons</title><content type="html">&lt;p&gt;&lt;a href="http://blog.kwiqq.com/"&gt;Lucy Irving&lt;/a&gt;'s &lt;a href="http://blog.kwiqq.com/2009/03/18/ambiguous-icons/"&gt;Ambiguous Icons&lt;/a&gt; post raises an interesting point about icon design: the problem of ambiguity and the fact that, often, words are simply better.
&lt;/p&gt;&lt;p&gt;
This is, of course, bad news for iconfu, but I'll get over it.
&lt;/p&gt;&lt;p&gt;
I agree, I think there will always be ambiguity. What's interesting though is that the pool of unambiguous icons is growing - &lt;a href="http://iconfu.com/tags/list/0.html?search=favorite&amp;browse=feed"&gt;&lt;img class="icon-action" src="http://iconfu.com/library/image/706.png" alt="rss feed"/&gt;&lt;/a&gt;, for example, is pretty universal; other fairly universal concepts are &lt;a href="http://iconfu.com/library/home/10146.png"&gt;&lt;img  class="icon-action" src="http://iconfu.com/library/image/10146.png" alt="star"/&gt;&lt;/a&gt; for &lt;a href="http://iconfu.com/tags/list/0.html?browse=favorite"&gt;"favourite"&lt;/a&gt;, &lt;a href="http://iconfu.com/library/home/10407.html"&gt;&lt;img class="icon-action" src="http://iconfu.com/library/image/10407.png" alt="magnifying glass"/&gt;&lt;/a&gt; for "&lt;a href="http://iconfu.com/tags/list/0.html?browse=search"&gt;search&lt;/a&gt;", and &lt;a href="http://iconfu.com/library/home/26.png" alt="floppy disk"&gt;&lt;img class="icon-action" src="http://iconfu.com/library/image/26.png"/&gt;&lt;/a&gt; for "&lt;a href="http://iconfu.com/tags/list/0.html?browse=save"&gt;save&lt;/a&gt;". 
&lt;/p&gt;&lt;p&gt;
This kind of convergence is inevitable, as the most popular websites prefer the most unsurprising UI elements. At the same time, the convergence will be organic rather than committee-driven, because it's a process of people looking around to see what other people are doing.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-5314100887766728973?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/sBE5mN5RiCY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/5314100887766728973/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/unambiguous-icons.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/5314100887766728973?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/5314100887766728973?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/unambiguous-icons.html" title="Unambiguous Icons" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEIHSHo8fip7ImA9WxVUEkU.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-1138050327602685413</id><published>2009-03-17T10:17:00.004+01:00</published><updated>2009-03-17T10:35:39.476+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-17T10:35:39.476+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="politics" /><title>Jamendo &amp; Magnatune</title><content type="html">&lt;p&gt;
Thanks to &lt;a href="http://blog.desgrange.net/index.php/post/2009/03/13/Jamendo%2C-remeciements-gradu%C3%A9s"&gt;Laurent&lt;/a&gt; I found &lt;a href="http://www.jamendo.com/"&gt;Jamendo&lt;/a&gt;, a distributor of Creative-Commons-licensed music, and from there &lt;a href="http://magnatune.com/"&gt;Magnatune&lt;/a&gt;, with similar goals. Magnatune artists get 50% of proceeds from sales of their work. Here's a Bach cantata from Magnatune:
&lt;/p&gt;&lt;p&gt;
&lt;a href="http://magnatune.com"&gt; &lt;img src="http://he3.magnatune.com/images/magnatune.gif" border="0"&gt;&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;
&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="300" height="160" &gt;
 &lt;param name="allowScriptAccess" value="sameDomain"/&gt;
 &lt;param name="movie" value="http://embed.magnatune.com/img/magnatune_player_embedded.swf?playlist_url=http://embed.magnatune.com/artists/albums/abs-cantatasfour/hifi.xspf&amp;autoload=true&amp;autoplay=&amp;playlist_title=JS%20Bach%20Cantatas%20-%20Volume%20IV%20-%20Early%20Cantatas%20for%20Holy%20Week%20:%20American%20Bach%20Soloists"/&gt;
 &lt;param name="quality" value="high"/&gt;
 &lt;param name="bgcolor" value="#E6E6E6"/&gt;
 &lt;embed src="http://embed.magnatune.com/img/magnatune_player_embedded.swf?playlist_url=http://embed.magnatune.com/artists/albums/abs-cantatasfour/hifi.xspf&amp;autoload=true&amp;autoplay=&amp;playlist_title=JS%20Bach%20Cantatas%20-%20Volume%20IV%20-%20Early%20Cantatas%20for%20Holy%20Week%20:%20American%20Bach%20Soloists" quality="high" bgcolor="#E6E6E6" name="xspf_player" allowscriptaccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" align="center" height="160" width="300"&gt; 
 &lt;/embed&gt;
&lt;/object&gt;
&lt;/p&gt;&lt;p&gt;&lt;FONT FACE="Verdana, Arial, utopia, sans-serif" SIZE="1" COLOR="#000000"&gt;
 &lt;a href="http://magnatune.com/artists/albums/abs-cantatasfour"&gt;&lt;b&gt;JS Bach Cantatas - Volume IV - Early Cantatas for Holy Week&lt;/b&gt;&lt;/a&gt; by &lt;a href="http://magnatune.com/artists/abs"&gt;&lt;b&gt;American Bach Soloists&lt;/b&gt;&lt;/a&gt;
&lt;/font&gt;
&lt;/p&gt;&lt;p&gt;
The quality of the music is good, but there's an annoying voice between each track that tells you the album and artist name, which you knew already. I hope the paid version excludes this. 
&lt;/p&gt;&lt;p&gt;
I'm going to explore these sites some more. It might be time to bid farewell to the iTunes Store, and all those Big Record Labels and their fascist anti-piracy methods with it.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-1138050327602685413?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/HVUxN4qhP2M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/1138050327602685413/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/jamendo-magnatune.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/1138050327602685413?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/1138050327602685413?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/jamendo-magnatune.html" title="Jamendo &amp; Magnatune" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0cNRHYzeCp7ImA9WxVVFkQ.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-2867794771810265004</id><published>2009-03-10T15:02:00.002+01:00</published><updated>2009-03-10T15:24:55.880+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-10T15:24:55.880+01:00</app:edited><title>Ban Censorship Now!</title><content type="html">&lt;p&gt;An Irish ISP, eircom, has agreed to ban any website the IRMA (Irish Recorded Music Association) chooses to block.&lt;/p&gt;

&lt;p&gt;I had thought censorship was one of those nasty deals you get in China and Iran, but now it's thriving in Ireland. Please support &lt;a href="http://blackoutireland.com/"&gt;http://blackoutireland.com/&lt;/a&gt; even if you're not Irish. I hate to fearmonger, but this is coming to an ISP near you, wherever you are, in the near future if it's not stopped now.&lt;/p&gt;

&lt;p&gt;Personally, I'm not interested in illegal music (my musical preferences aren't the kind that go with P2P), but it is not acceptable for a private corporation to decide what sites I may or may not use. Now I just feel all icky and horrible when I enter a music store. All those shiny CDs are whispering "censorship, censorship" at me.&lt;/p&gt;

&lt;p&gt;Go and prosecute the criminals, leave the rest of us alone!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-2867794771810265004?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/SEdymVf_mIQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/2867794771810265004/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/ban-censorship-now.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2867794771810265004?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/2867794771810265004?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/ban-censorship-now.html" title="Ban Censorship Now!" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUMFQnw_fSp7ImA9WxVVEEo.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-679544593008442297</id><published>2009-03-03T11:49:00.000+01:00</published><updated>2009-03-03T11:50:13.245+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-03T11:50:13.245+01:00</app:edited><title>Blogger: break "convert line breaks"</title><content type="html">&lt;p&gt;Blogger's "convert line breaks" setting seems to cause a lot of pain, and what's more, it doesn't even seem to work. I get gratuitous &amp;lt;br/&amp;gt; in my code despite having set this setting to OFF. The issue and some workarounds are discussed on &lt;a href="http://robertmarkbramprogrammer.blogspot.com/2008/06/few-tipswarnings-for-posting-code-for.html"&gt;Rob on Programming&lt;/a&gt;, &lt;a href="http://blogging.nitecruzr.net/2007/05/beware-gratuitous-line-breaks-in-code.html"&gt;The Real Blogger Status&lt;/a&gt;, and &lt;a href="http://mlawire.blogspot.com/2007/01/table-formatting-in-blogger.html"&gt;MLA Wire&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The trouble is, if you've chosen to edit in "Edit Html" mode, it's reasonable to suppose that you know what you're doing, and you want the html code of your post to be exactly what you write. In other words, I can take care of my own &amp;lt;p&amp;gt; and &amp;lt;br&amp;gt; tags.&lt;/p&gt;

&lt;p&gt;Blogger doesn't think so. And here's my revenge - I added this to the "style" section of my template:&lt;/p&gt;

&lt;pre&gt;
  br { display: none; }
  br.forReal { display:inline; }
&lt;/pre&gt;

&lt;p&gt;This way, I never have to think about Blogger's thoughtful, kind, but misguided insertion of line breaks again. And when I want a line break for real, which isn't very often (I'm more of a &amp;lt;p&amp;gt;...&amp;lt;/p&amp;gt; person), I just&lt;/p&gt;

&lt;pre&gt;
  &amp;lt;br class='forReal'/&amp;gt;
&lt;/pre&gt;

&lt;p&gt;So I can make a table thusly*:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;table style="width:auto;" cellpadding="1" cellspacing="1" border="1"&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;foo&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;bar&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;toto&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;titi&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Which looks like&lt;/p&gt;

&lt;table style="width:auto;" cellpadding="1" cellspacing="1" border="1"&gt;
  &lt;tr&gt;
    &lt;td&gt;foo&lt;/td&gt;
    &lt;td&gt;bar&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;toto&lt;/td&gt;
    &lt;td&gt;titi&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Slight problem: it has probably gone and damaged all my old posts. What a pain!&lt;/p&gt;


&lt;small&gt;* I know, "thusly" isn't a word. I don't care.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-679544593008442297?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/B-eNdCMN3tM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/679544593008442297/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/blogger-break-convert-line-breaks_03.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/679544593008442297?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/679544593008442297?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/blogger-break-convert-line-breaks_03.html" title="Blogger: break &quot;convert line breaks&quot;" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DU8HQ3s-eCp7ImA9WxVVEEo.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-5232113318811045157</id><published>2009-03-03T10:09:00.003+01:00</published><updated>2009-03-03T11:57:12.550+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-03T11:57:12.550+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="iconfu" /><title>iconfu news</title><content type="html">&lt;p&gt;Release notes for the latest iconfu:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Added "fill" tool - fills a given set of contiguous transparent pixels with the current colour.&lt;/li&gt;&lt;li&gt;Added "round-corners" action - rounds the corners of your icon. This was inspired by a collection of iphone icons, I wanted to prove iconfu could make iphone icons!&lt;/li&gt;&lt;li&gt;Much-improved "draw border" action - previously it made a mess of curvy, antialiased edges, now it uses a much smarter algorithm, and it's pretty nice&lt;/li&gt;&lt;li&gt;Draw ellipses at any angle (not just 0° and 90°)&lt;/li&gt;&lt;li&gt;Draw ellipse outline (ie, specify a transparent "inner ellipse" area) for drawing rings and "O"s and rss feed icons and anything circular or elliptical&lt;/li&gt;&lt;li&gt;Fixed a nasty defect that prevented conversion to .ico format if the original image was strictly black and white.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;I made this flowery icon to try out all these exciting new features ...&lt;/p&gt;

&lt;p style="white-space: nowrap;"&gt;&lt;img src="/flowers/1.png" alt="flower 1" /&gt; &lt;img src="/flowers/4.png" alt="flower 4" /&gt; &lt;img src="/flowers/5.png" alt="flower 5" /&gt; &lt;img src="/flowers/6.png" alt="flower 6" /&gt; &lt;img src="/flowers/7.png" alt="flower 7" /&gt; &lt;img src="/flowers/8.png" alt="flower 8" /&gt; &lt;img src="/flowers/9.png" alt="flower 9" /&gt; &lt;img src="/flowers/10.png" alt="flower 10" /&gt; &lt;img src="/flowers/3.png" alt="flower 3" /&gt; &lt;img src="/flowers/11.png" alt="flower 11" /&gt; &lt;img src="/flowers/12.png" alt="flower 12" /&gt; &lt;img src="/flowers/14.png" alt="flower 14" /&gt; &lt;img src="/flowers/15.png" alt="flower 15" /&gt; &lt;img src="/flowers/16.png" alt="flower 16" /&gt; &lt;img src="/flowers/2.png" alt="flower 2" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(note the Alexandrian properties of borders, gradients, and repetition. I wasn't able to work in any Deep Interlock and Ambiguity, I'll try that for the next round)&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-5232113318811045157?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/mpnaRVZPqRA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/5232113318811045157/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/03/iconfu-news.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/5232113318811045157?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/5232113318811045157?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/03/iconfu-news.html" title="iconfu news" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0MEQXw8cSp7ImA9WxVWFE8.&quot;"><id>tag:blogger.com,1999:blog-4089129643157405806.post-4881091013594457687</id><published>2009-02-23T22:09:00.007+01:00</published><updated>2009-02-23T22:43:20.279+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-23T22:43:20.279+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nonsense" /><category scheme="http://www.blogger.com/atom/ns#" term="software" /><title>Exceptions In Java [Must Read]</title><content type="html">&lt;p&gt;Exceptions were a big improvement over the old-fashioned C way of returning error codes, but then the debate raged over Checked vs Unchecked Exceptions, vs "Huh? Checked? Whazza?". Java offers all three varieties so you can never hope to port exceptional experience from one project to the next, because there are at least as many correct ways to do things as there are gurus. However, at least now there's a step in the right direction; with Björn Andersson's &lt;a href="http://rymden.nu/exceptions.html"&gt;Java Exception Explanator&lt;/a&gt; a lot more of this makes sense. Check it out. Here's a teaser:&lt;/p&gt;

&lt;p style='margin-left:4em;margin-right:4em;'&gt;&lt;strong&gt;&lt;code&gt;AccessControlException&lt;/code&gt;&lt;/strong&gt; : You have lost control of Microsoft Access. If you cannot regain control or stop the program in some other way, you should cut the power to your computer as fast as possible.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;ps. thanks &lt;a href="http://www.reddit.com/r/programming/comments/7zmf9/list_of_common_java_exceptions_wait_wtf/"&gt;reddit&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;copyright conan dalton 2007-2010 feel free to quote please link back&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4089129643157405806-4881091013594457687?l=www.conandalton.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PublicInterface/~4/55cUvPzt8DI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.conandalton.net/feeds/4881091013594457687/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.conandalton.net/2009/02/exceptions-in-java-must-read.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/4881091013594457687?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4089129643157405806/posts/default/4881091013594457687?v=2" /><link rel="alternate" type="text/html" href="http://www.conandalton.net/2009/02/exceptions-in-java-must-read.html" title="Exceptions In Java [Must Read]" /><author><name>conan</name><uri>http://www.blogger.com/profile/03401726635379568413</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00745436931910790196" /></author><thr:total>0</thr:total></entry></feed>
