<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Mendable.com</title>
 <link href="http://feeds.feedburner.com/mendable" rel="self"/>
 <link href="http://www.mendable.com/"/>
 <updated>2011-02-15T13:13:20-08:00</updated>
 <id>http://www.mendable.com/</id>
 <author>
   <name>Jason Lambert</name>
 </author>

 
 <entry>
   <title>Compiling Power DNS on Snow Leopard</title>
   <link href="http://www.mendable.com/2010/09/11/compiling-power-dns-on-snow-leopard.html"/>
   <updated>2010-09-11T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/09/11/compiling-power-dns-on-snow-leopard</id>
   <content type="html">&lt;p&gt;This is how to install PowerDNS on Mac OSX Snow Leopard 10.6.4.&lt;/p&gt;

&lt;p&gt;1) Install 64-bit Mysql server from the MySQL dmg package available from the MySQL website&lt;/p&gt;

&lt;p&gt;2) Install the boost c++ library by ports (at time of writing this is boost version 1.44)&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;sudo port install boost
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;3) Download the authoritative server tar.gz file from [powerdns.com][], and unpack.&lt;/p&gt;

&lt;p&gt;4) Build and Install.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;CXXFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;-DDARWIN &lt;span class=&quot;nv&quot;&gt;CPPFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;-I/opt/local/include ./configure &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 --with-mysql-includes&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/mysql/include/
make
sudo make install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;5) Install a default config file, examples within the package.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;sudo cp /usr/local/etc/pdns.conf-dist /usr/local/etc/pdns.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;6) Edit /usr/local/etc/pdns.conf to taste. To setup the MySQL backend, you will need to add the following to the file:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;----
&lt;span class=&quot;nv&quot;&gt;launch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;gmysql
gmysql-host&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;127.0.0.1
gmysql-user&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;root
gmysql-dbname&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;power_dns
----
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;7) Create the database and database schema. You can find it &lt;a href=&quot;http://doc.powerdns.com/generic-mypgsql-backends.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;8) Start the server.&lt;/p&gt;

&lt;p&gt;There is an init script file in &quot;pdns/pdns&quot; in the tar.gz package after compiling that you can use to stop/start the server, you must have root privileges (ie, use sudo) to start/stop the server because the daemon listens on ports &amp;lt; 1024.&lt;/p&gt;

&lt;p&gt;You can find server log output in /var/log/system.log.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>New Project Launched - ChatUp.com</title>
   <link href="http://www.mendable.com/2010/06/06/new-project-launched-chatup-com.html"/>
   <updated>2010-06-06T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/06/06/new-project-launched-chatup-com</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.chatup.com/&quot;&gt;&lt;img src=&quot;/images/posts/chatup-logo.gif&quot; alt=&quot;chatup logo&quot; title=&quot;chatup logo&quot; width=&quot;248&quot; height=&quot;84&quot; style=&quot;float:left; margin-right: 20px;&quot; /&gt;&lt;/a&gt;I have launched a new Ruby on Rails website, &lt;a href=&quot;http://www.chatup.com/&quot;&gt;ChatUp.com&lt;/a&gt;. This is a personal project that i've been working on in my spare time with a little help from my girlfriend, and it's great to finally have it out there.&lt;/p&gt;

&lt;p&gt;I've got some really cool stuff integrated, including Facebook authentication using the new OAuth2 API and HTML5 GeoLocation. Doing GeoLocation &lt;em&gt;well&lt;/em&gt; and having it work for any user of the site turned out to be a bit tricky, i might post more on that later. Back end searching is done using the latest Sphinx search daemon and ThinkingSphinx plugin.&lt;/p&gt;

&lt;p&gt;There are still 101 things I want to improve, i'm working on getting a new design for the blog sorted right now, but as an initial version 1 it does all the things you would expect of any dating site.&lt;/p&gt;

&lt;p&gt;I'm going to be writing about my efforts to build out the site further, and probably more importantly how I actually am getting traffic to the website (let's face it, that's one of the hardest things to do, programming is easy).&lt;/p&gt;

&lt;p&gt;If you want to follow the project along, please check out the &lt;a href=&quot;http://www.chatup.com/blog&quot;&gt;ChatUp Blog&lt;/a&gt; and grab the RSS feed.&lt;/p&gt;

&lt;p&gt;Please &lt;a href=&quot;http://www.chatup.com/&quot;&gt;check it out&lt;/a&gt;, Feedback welcome!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thinking Sphinx Performance - Split your re-indexing into seperate tasks</title>
   <link href="http://www.mendable.com/2010/06/03/thinking-sphinx-performance-index-faster-separately.html"/>
   <updated>2010-06-03T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/06/03/thinking-sphinx-performance-index-faster-separately</id>
   <content type="html">&lt;p&gt;If you have multiple indexes, you need to consider if they all need to be re-indexed at the same time.&lt;/p&gt;

&lt;p&gt;For example, you might have a &quot;users&quot; index that changes frequently that you want to re-index from scratch or merge delta changes, and a &quot;spare car parts&quot; index that may only change once or twice a day.&lt;/p&gt;

&lt;p&gt;The accepted way to perform a re-index your data is of course to run &quot;rake ts:index&quot; which will re-create ALL of your indexes, but that assumes all indexes are equal and all need re-indexing at the same time - usually that is not true. When you have to re-index a &lt;em&gt;huge&lt;/em&gt; index when all you really want is to update the smaller one... it's inefficient.&lt;/p&gt;

&lt;p&gt;So, what does rake ts:index actually do?&lt;/p&gt;

&lt;p&gt;The thinking sphinx index task works out what config file to use based on your rails environment and Rails.root directory, re-generates the config file, and then calls the sphinx indexer program with a link to the config file.&lt;/p&gt;

&lt;p&gt;The indexer program has a whole range of options which you might like to get familiar with:&lt;/p&gt;

&lt;pre&gt;$ indexer
Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoff

Usage: indexer [OPTIONS] [indexname1 [indexname2 [...]]]

Options are:
--config &lt;file&gt;     read configuration from specified file
            (default is sphinx.conf)
--all           reindex all configured indexes
--quiet         be quiet, only print errors
--noprogress        do not display progress
            (automatically on if output is not to a tty)
--rotate        send SIGHUP to searchd when indexing is over
            to rotate updated indexes automatically
--buildstops &lt;output.txt&gt; &lt;N&gt;
            build top N stopwords and write them to given file
--buildfreqs        store words frequencies to output.txt
            (used with --buildstops only)
--merge &lt;dst-index&gt; &lt;src-index&gt;
            merge 'src-index' into 'dst-index'
            'dst-index' will receive merge result
            'src-index' will not be modified
--merge-dst-range &lt;attr&gt; &lt;min&gt; &lt;max&gt;
            filter 'dst-index' on merge, keep only those documents
            where 'attr' is between 'min' and 'max' (inclusive)
--merge-killlists           merge src and dst killlists instead of applying src killlist to dst
Examples:
indexer --quiet myidx1  reindex 'myidx1' defined in 'sphinx.conf'
indexer --all       reindex all indexes defined in 'sphinx.conf'&lt;/pre&gt;


&lt;p&gt;We are interested in indexing only specific indexes at specific times, following from the example above, the &quot;spare car parts&quot; index, instead of running rake ts:in from cron to re-index everything every hour (for example), you can split those indexes out to separate tasks like this:&lt;/p&gt;

&lt;pre&gt;indexer --config /var/www/your-website.com/current/config/production_slave.sphinx.conf spare_car_parts_core --rotate
indexer --config /var/www/your-website.com/current/config/production_slave.sphinx.conf users_core --rotate&lt;/pre&gt;


&lt;p&gt;Put those into cron with your desired time schedule, and you will have a happier database server. Important to note is that you must include the _core part, as this is how the ThinkingSphinx gem names the index in the sphinx configuration.&lt;/p&gt;

&lt;p&gt;When you deploy remember to run &quot;rake ts:config&quot; with the correct Rails environment to generate your config.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thinking Sphinx Performance - How to Index from Slave MySQL Database</title>
   <link href="http://www.mendable.com/2010/05/31/thinking-sphinx-performance-index-from-slave-mysql-database.html"/>
   <updated>2010-05-31T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/05/31/thinking-sphinx-performance-index-from-slave-mysql-database</id>
   <content type="html">&lt;p&gt;For one of the sites I work with, we are running a load balanced web server setup with separate MySQL database servers in master-slave configuration on the back end. Each of the web servers run their own Sphinx searchd daemon (to reduce latency of client connection/queries) using a non-distributed sphinx index.&lt;/p&gt;

&lt;p&gt;While looking at our Munin graphs I was concerned to see the amount of bandwidth and disk IO on the master MySQL database server caused by periodic re-indexing, and that load increases in line with the number of front-end web servers currently in use.&lt;/p&gt;

&lt;p&gt;So that got me thinking... these are huge read-only queries, a small time lag is acceptable, they &lt;em&gt;should&lt;/em&gt; be happening on the Slave MySQL database.&lt;/p&gt;

&lt;p&gt;ThinkingSphinx does not have any official documentation for how to configure this, so here is the secret to setup the Sphinx indexer to use your slave MySQL database...&lt;/p&gt;

&lt;p&gt;&lt;b&gt;1/. Create a Read Only MySQL User&lt;/b&gt;
On your Master MySQL server create a read-only MySQL user if you do not have one already. It will be replicated automatically onto the slave servers. This is just good practice, you do NOT want any changes accidentally made on your slave databases or you run the risk of breaking MySQL replication.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;2/. Create new production_slave environment&lt;/b&gt;
We will use a separate Rails environment to hold our slave database and sphinx configuration, but you need to get that environment working. To do this in your rails project, copy config/environments/production.rb to config/environments/production_slave.rb.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;3/. Configure database.yml&lt;/b&gt;
In your database yml, create a new entry for your production_slave environment, pointing to your slave MySQL database, and use your read-only MySQL user.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;4/. Edit your config/sphinx.yml file&lt;/b&gt;
Take a copy of your production section and duplicate it under production_slave. It is important that you use the same port number and settings of the production environment.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;5/. Commit your changes and deploy live&lt;/b&gt;
Push our your code to the servers, so your servers now have access to your new production_slave environment. Edit your yml configs on the servers if your deploy process does not mange this for you.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;6/. Setup Sphinx Indexer for new Environment&lt;/b&gt;
The sphinx indexer should now use the RAILS_ENV=production_slave. As this is the first time you should now run &quot;RAILS_ENV=production_slave rake ts:in&quot; which will automatically generate a new config/production_slave.sphinx.conf file for you that searchd and indexer can use, and generate your first set of indexes in db/sphinx/production_slave/.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;7/. Restart Sphinx&lt;/b&gt;
Stop your production sphinx instance, and restart sphinx with the production_slave environment. It needs to read the same config file as your indexer in case of future schema changes etc.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;8/. Update RAILS_ENV for sphinx elsewhere&lt;/b&gt;
This will largely be dependent on your setup, but you need to change your cron-jobs, init.d scripts, deploy scripts, process monitoring etc to use the production_slave environment for your sphinx daemon and sphinx indexing tasks.&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;The reason this works it because of step #4, where we use the same host &amp;amp; port for our sphinx server for both the production and production_slave environments. Although your app continues to run as production, your sphinx server runs as production slave on the port expected in the production environment so you are now querying the sphinx daemon that is indexed from the slave MySQL database.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>uninitialized constant ThinkingSphinx::Deltas::Job</title>
   <link href="http://www.mendable.com/2010/04/18/uninitialized-constant-thinkingsphinxdeltasjob.html"/>
   <updated>2010-04-18T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/04/18/uninitialized-constant-thinkingsphinxdeltasjob</id>
   <content type="html">&lt;p&gt;If you are getting this error during a sphinx index, it is likely because you have a copy of the gem 'thinking-sphinx' installed, but you also have an older version of the gem from the old github repository also installed (eg, freelancing-god-thinking-sphinx).&lt;/p&gt;

&lt;p&gt;The solution is to remove the old github gem version.&lt;/p&gt;

&lt;p&gt;Also this should be a reminder that github will stop hosting gems in October 2010, so you need to allocate time to switching all of your gem dependencies be running gems from github to their respective rubygems/gemcutter versions.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>FFMpeg SWF File Conversion</title>
   <link href="http://www.mendable.com/2010/04/18/ffmpeg-swf-file-conversion.html"/>
   <updated>2010-04-18T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/04/18/ffmpeg-swf-file-conversion</id>
   <content type="html">&lt;p&gt;FFMpeg has multiple problems and bugs with writing out to SWF files, I run into a few of these at my day-job and wrote a patch for one of the problems and submitted it back to FFMpeg. It was a nice change to go back and do some C programming for a while.&lt;/p&gt;

&lt;p&gt;Anyway, list of ffmpeg swf audio problems as follows:
1) Converting to SWF was hard coding the number of audio frames to 6000 in the generated SWF file, whereas the SWF Format specification document from adobe says this must match the number of frames in the file. It was also hard-coding an arbitrary file size into the SWF header as well, rather than the correct file size of the generated file. These are the problems I fixed.&lt;/p&gt;

&lt;p&gt;2) FFMpeg SWF encoder writes too many frames to a file. Yeah, really. It writes all of your audio, then a few minutes of empty sound as well. Haven't got a fix for it yet, need to step through an FFMpeg run in GDB to figure out why it's doing it. You can open a SWF in a &lt;a href=&quot;http://www.suavetech.com/0xed/0xed.html&quot;&gt;binary editor&lt;/a&gt; and manually fudge the number of frames in the SWF Header if you have a scrobbler that is dependent upon the number of frames to determine play duration / progress.. or do something a little more automated.&lt;/p&gt;

&lt;p&gt;3) The SWF encoder in FFMpeg is writing out audio only streams using version 4 of the SWF file format, where as the file format specification is now up to version 10. Not sure why it's writing out in such an old version (maximum compatibility?). Could probably use some documentation.&lt;/p&gt;

&lt;p&gt;This was the patch I submitted for problem #1.&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100415/c02bf648/attachment.obj&quot;&gt;http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100415/c02bf648/attachment.obj&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2010-April/086938.html&quot;&gt;On the mailing list:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Problem Description:
When converting any Audio to SWF, the File Size is always hard-coded
as 104857600, and Frame Count is always hard coded to 6000. The
incorrect frame count can cause problems when ffmpeg generated swfs
are used inside a flash application and the _totalframes method is
used.&lt;/p&gt;

&lt;p&gt;Example command line:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;ffmpeg -i 157346.mp3 -ar 44100 -ab 96k -ac 1 -y 157346.swf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;When inspecting the generated swf using the swfdump tool
(swftools.org), the following is shown:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;o&quot;&gt;====&lt;/span&gt; Error: Real Filesize &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1495887&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; doesn&lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;t match header Filesize
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;104857600&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;====&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        File version: 4
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        File size: 104857600
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Frame rate: 10.000000
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Frame count: 6000
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Movie width: 320.00
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Movie height: 200.00
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;02d&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         6 SOUNDSTREAMHEAD2
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       317 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:00:00,000&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       318 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 2 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:00:00,100&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
.........
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       318 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 4595 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:07:39,382&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       317 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 4596 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:07:39,482&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;000&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 END
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;As you can see, the last frame is 4596, and the file size specified in
the header does not match the real file size (swfdump gives a warning
about this).&lt;/p&gt;

&lt;p&gt;File size should indicate 1495887 bytes:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ls -al 157346.swf
-rw-r--r-- 1 username &lt;span class=&quot;k&quot;&gt;default &lt;/span&gt;1495887 Apr 14 11:25 157346.swf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Problem Solution:
Correctly set the File Size in the SWF header section to the real
number of bytes written, and correctly set the number of frames
included in the SWF.&lt;/p&gt;

&lt;p&gt;Details of the SWF file format header information can be confirmed on
page 25 of the SWF File Format Specification document from Adobe,
available here: http://www.adobe.com/devnet/swf/&lt;/p&gt;

&lt;p&gt;After my patch is applied, using ffmpeg with the same command line
options as above and then inspecting the generated swf with swfdump
shows:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        File version: 4
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        File size: 1495887
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Frame rate: 10.000000
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Frame count: 4596
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Movie width: 320.00
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;HEADER&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;        Movie height: 200.00
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;02d&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         6 SOUNDSTREAMHEAD2
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       317 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:00:00,000&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       318 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 2 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:00:00,100&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
.........
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       318 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 4595 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:07:39,382&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;013&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;       317 SOUNDSTREAMBLOCK
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;001&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 SHOWFRAME 4596 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;00:07:39,482&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;000&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;         0 END
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Note that the Frame Count is correct, and the file size is correctly
reflects the total number of bytes in the file:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ls -al 157346.swf
-rw-r--r-- 1 username &lt;span class=&quot;k&quot;&gt;default &lt;/span&gt;1495887 Apr 15 06:58 157346.swf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>Programmer Philosophy</title>
   <link href="http://www.mendable.com/2010/04/09/programmer-philosophy.html"/>
   <updated>2010-04-09T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/04/09/programmer-philosophy</id>
   <content type="html">&lt;p&gt;I write code for a living. Even when I am writing code by myself, there are actually three people working with that code.&lt;/p&gt;

&lt;p&gt;First, there is me. I am a clever and talented programmer. I know to keep my code clean and easy to read. I try to do things the right way and I know that if old code is wrong that I am better off fixing it now then trying to code around it.&lt;/p&gt;

&lt;p&gt;Second, there is past me. This guy is a fracking moron. He pisses me off on a daily basis as I am having to constant re-write his code. He is generally clueless and causes me more headaches than anyone else.&lt;/p&gt;

&lt;p&gt;Finally there is the future me. This guy is smarter than I am, has seen more than I have and has done more. My goal, in addition to making sure my code works, is to make sure that my intentions are clear for him so that I don’t piss him off too badly.&lt;/p&gt;

&lt;p&gt;When I claim to be a moron, it is a matter of perspective. Compared to my 8 year old self, I am brilliant. Compared to myself in 10 years; not so much. Therefore, it is safe to say that anything I wrote in the past was written by someone dumber than I am.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I came across those words of wisdom &lt;a href=&quot;http://www.cimgf.com/2009/03/26/dont-blindly-trust-debb/&quot;&gt;here&lt;/a&gt; - very eloquently expressed, but really focuses in on the fact that as programmers we are always improving.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Polymorphic Single Table Inheritance (STI)</title>
   <link href="http://www.mendable.com/2010/03/30/polymorphic-single-table-inheritance-sti.html"/>
   <updated>2010-03-30T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2010/03/30/polymorphic-single-table-inheritance-sti</id>
   <content type="html">&lt;p&gt;Migration:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;  &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addresses&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;references&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addressable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:polymorphic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamps&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Address Models:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addressable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:polymorphic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InvoiceAddress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DeliveryAddress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;User Model:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dependent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:destroy&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_one&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:invoice_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addressable&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_one&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:delivery_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addressable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Order Model:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Order&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:dependent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:destroy&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_one&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:invoice_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addressable&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_one&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:delivery_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:addressable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Get Funky:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;irb&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=&amp;gt; &amp;lt;User id: nil ...&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_invoice_address&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=&amp;gt; #&amp;lt;InvoiceAddress id: nil, addressable_id: nil, addressable_type: &amp;quot;User&amp;quot;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;created_at: nil, updated_at: nil, type: &amp;quot;InvoiceAddress&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_delivery_address&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=&amp;gt; &amp;lt;DeliveryAddress id: nil, addressable_id: nil, addressable_type: &amp;quot;User&amp;quot;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;created_at: nil, updated_at: nil, type: &amp;quot;DeliveryAddress&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Order&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=&amp;gt; #&amp;lt;Order id: nil ...&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_invoice_address&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=&amp;gt; #&amp;lt;InvoiceAddress id: nil, addressable_id: nil, addressable_type: &amp;quot;Order&amp;quot;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;created_at: nil, updated_at: nil, type: &amp;quot;InvoiceAddress&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Sweet :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Quick and easy static pages in Rails</title>
   <link href="http://www.mendable.com/2010/02/10/quick-and-easy-static-pages-in-rails.html"/>
   <updated>2010-02-10T00:00:00-08:00</updated>
   <id>http://www.mendable.com/2010/02/10/quick-and-easy-static-pages-in-rails</id>
   <content type="html">&lt;p&gt;Sometimes you have a Rails app, the core functionality is not a CMS, and you need to add some static pages to your app that don't get changed often, eg, an about us page, privacy policy, etc.&lt;/p&gt;

&lt;p&gt;This post shows you a quick and easy way to do that in about 60 seconds, without using a database model or having to write any sort of CMS.&lt;/p&gt;

&lt;p&gt;1) First off, add some routes for your static pages. Here I want an FAQ page, About page, Privacy page, and Terms and Conditions pages.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with_options&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;static_pages&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;show&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;static_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;static_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;faq&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;faq&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;faq&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;static_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;about&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;about&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;about&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;static_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;privacy&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;privacy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;privacy&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;static_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terms_and_conditions&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;terms_and_conditions&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;terms_and_conditions&amp;#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;2) Add a functional test so we know it works now, and we can check we don't retrospectively break it later. Create a new file in test/functionals/static_pages_controller_test.rb:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/../test_helper&amp;#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticPagesControllerTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;should_route&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/privacy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;show&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;privacy&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;should_route&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/terms_and_conditions&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;show&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;terms_and_conditions&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;should_route&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/faq&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;show&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;faq&amp;#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;should_route&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/about&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;show&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;about&amp;#39;&lt;/span&gt;

  &lt;span class=&quot;sx&quot;&gt;%w(privacy about terms_and_conditions faq)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;static_page_template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Accessing the &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;static_page_template&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; page&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;static_page_template&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;should_respond_with&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:success&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;should_render_template&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;static_page_template&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is fairly simple but covers everything we need it to. It just checks your routing is setup and the pages render from the static template files correctly.&lt;/p&gt;

&lt;p&gt;3) Create your controller, app/controllers/static_pages_controller.rb:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StaticPagesController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;show&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;static_pages/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Again, really simple. Use a RESTful 'show' method to select a template to render, then render it.&lt;/p&gt;

&lt;p&gt;4) from a shell, make a directory for your pages to live in, and create the empty files:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkdir app/views/static_pages
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;touch app/views/static_pages/about.html.erb
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;touch app/views/static_pages/faq.html.erb
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;touch app/views/static_pages/privacy.html.erb
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;touch app/views/static_pages/terms_and_conditions.html.erb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;5) Check it works:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ruby test/functional/static_pages_controller_test.rb 
Loaded suite test/functional/static_pages_controller_test
Started
............
Finished in 0.156958 seconds.

12 tests, 24 assertions, 0 failures, 0 errors
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Done! Now put the content in your pages, test, check in and deploy.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails 3 Beta is out - check out Rails Upgrade plugin</title>
   <link href="http://www.mendable.com/2010/02/07/rails-3-beta-is-out-check-out-rails-upgrade-plugin.html"/>
   <updated>2010-02-07T00:00:00-08:00</updated>
   <id>http://www.mendable.com/2010/02/07/rails-3-beta-is-out-check-out-rails-upgrade-plugin</id>
   <content type="html">&lt;p&gt;In case you haven't heard, &lt;a href=&quot;http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release&quot;&gt;Rails 3 is now in Beta&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just a quick post to say, if you haven't already, check out the &lt;a href=&quot;http://omgbloglol.com/post/364624593/rails-upgrade-is-now-an-official-plugin&quot;&gt;Rails upgrade plugin&lt;/a&gt;, this will quickly show you what bits of your code need to be updated to work with Rails 3.&lt;/p&gt;

&lt;p&gt;Also, check out the full &lt;a href=&quot;http://guides.rails.info/3_0_release_notes.html&quot;&gt;release notes&lt;/a&gt;, lots of juicy stuff in there.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sometimes the best way to create is to remove</title>
   <link href="http://www.mendable.com/2010/02/06/sometimes-the-best-way-to-create-is-to-remove.html"/>
   <updated>2010-02-06T00:00:00-08:00</updated>
   <id>http://www.mendable.com/2010/02/06/sometimes-the-best-way-to-create-is-to-remove</id>
   <content type="html">&lt;p&gt;Over the life cycle of a project many features may be developed, sometimes just to account for one variation or tiny use case, get used once, and are then not used again for the next 5 years (if ever).&lt;/p&gt;

&lt;p&gt;One of my personal pet peeves is overly complicated software with too many redundant, old, unused features. This sort of redundant complexity increases the learning curve for new developers coming into the software project and creates extra work in maintaining the software,&lt;/p&gt;

&lt;p&gt;I often think the best way to create and maintain software, is to periodically remove all the old crap not being used any more. Some people do not like the idea of losing a feature in their application, as in &quot;OMG, you can't take that away, I was planning to use that one day&quot;, and maybe they were. But often, you have to look at what they say they are going to do, and compare that with what they actually do.&lt;/p&gt;

&lt;p&gt;I am sure this is some sort of psychological effect where the fear of losing a feature has more of an emotional impact on the end user / client than the prospect of faster software development and the addition of new features, as well as cheaper maintenance.&lt;/p&gt;

&lt;p&gt;If the feature works, can't it just stay?&lt;/p&gt;

&lt;p&gt;Hypothetically yes, but sometimes the part the end user sees is that the old features only continue to work because when adding new features we are able to test we have not broken the old features, and in some cases that means a ton of work when a big structural change is occurring.&lt;/p&gt;

&lt;p&gt;Also consider the development of a new software project, or a big addition to an existing project. The number of proposed features grows exponentially with the number of people involved. In reality, only 20% of the features will make 80% of the software, but you may end up coding 80% of the features to make up 90% of the functionality, just because people don't get agile, or the business structure around you does not allow for it to happen so easily (extensive budgeting approvals, waterfall methodology), or of the HiPPO effect (Highest paid person's opinion).&lt;/p&gt;

&lt;p&gt;This post has been a bit of a rant, but the points are these:
* Don't develop crap you don't need
* Remove old crap you don't use any more&lt;/p&gt;

&lt;p&gt;Do points 1 &amp;amp; 2 and you will get:
* Faster software development
* Software that is easier to maintain
* Easier to bring in new developers to a project
* Happier developers
* Reduced costs all round&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Decrypt/Reverse MD5 / SHA1 Password Hashes</title>
   <link href="http://www.mendable.com/2010/01/15/decryptreverse-md5-sha1-password-hashes.html"/>
   <updated>2010-01-15T00:00:00-08:00</updated>
   <id>http://www.mendable.com/2010/01/15/decryptreverse-md5-sha1-password-hashes</id>
   <content type="html">&lt;p&gt;There is a nice little tool over on &lt;a href=&quot;http://tmto.org&quot;&gt;tmto.org&lt;/a&gt; that allows you to decrypt (or should I say, reverse) MD5 or SHA1 hashes. Essentially, someone has forward hash'ed all a-z letters, put them in a database, then matches your hash against what is in the DB to find what the original string was. This is somewhat limited, it only currently does a-z by the looks of things, but a very nice idea. Should also re-enforce the benefits of double-salting your passwords with a per-size and per-user based salt as well.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Installing AutoTest</title>
   <link href="http://www.mendable.com/2009/08/06/installing-autotest.html"/>
   <updated>2009-08-06T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/08/06/installing-autotest</id>
   <content type="html">&lt;p&gt;I think autotest is one of the best things about developing in Rails. If you don't know, autotest runs in the background watching all of your application files. When you edit any of them, it automatically runs the sections of your test suite that apply to the modified file, and can then give you feedback as to if your tests are passing or failing. This means more time developing, less time switching windows to run rake test!&lt;/p&gt;

&lt;p&gt;I thought I would post a note about how to correctly install autotest, as some of the other documentation is out of date.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;sudo gem uninstall ZenTest
sudo gem install ZenTest
sudo gem install autotest-rails
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Something that is missing in a lot of other online documentation is the fact that you have to install the autotest-rails gem as well, if you don't do this, you will get an error any time you try to run autotest:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;Autotest style autotest/rails doesn&lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;t seem to exist. Aborting.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Another note, if you want to get desktop notifications working, &lt;a href=&quot;http://ph7spot.com/articles/getting_started_with_autotest&quot;&gt;this page&lt;/a&gt; has details of how to achieve that using Mac OSX, KDE, Gnome, etc.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wireframing your Rails Apps</title>
   <link href="http://www.mendable.com/2009/07/25/wireframing-rails-apps.html"/>
   <updated>2009-07-25T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/07/25/wireframing-rails-apps</id>
   <content type="html">&lt;p&gt;A really useful way to mockup your applications before coding is to use wire framing software to create the screens and layout of your  application. By doing this, you can ensure everyone working on the project can help to decide upon what the first version should functionally look like, and everyone will know what the end goal should approximately look like.&lt;/p&gt;

&lt;p&gt;With this sort of discussion, you really need a tool that will just let you focus on the functional aspect, and avoid too much discussion about colors, branding, etc, all of which can come later.&lt;/p&gt;

&lt;p&gt;A really useful tool I have been using is &lt;a href=&quot;http://www.balsamiq.com/products/mockups&quot; target=&quot;_new&quot;&gt;Balsamiq Mockups&lt;/a&gt;, it allows you to quickly create screens for your app and includes all the standard page controls you would expect. Here is an example of what you can produce:&lt;/p&gt;

&lt;p&gt;There is a nice video demo on the site as well.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Is your conversion rate good?</title>
   <link href="http://www.mendable.com/2009/07/11/is-your-conversion-rate-good.html"/>
   <updated>2009-07-11T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/07/11/is-your-conversion-rate-good</id>
   <content type="html">&lt;p&gt;Something I have been asked a few times by online retailers is, &quot;&lt;em&gt;how does my conversion rate compare to others in my industry?&lt;/em&gt;&quot;. Speaking to one online retailer a few weeks ago, they specifically mentioned having access to lots of data from Google analytics, but they have no idea if they are doing better or worse than their competitors or others in their industry.&lt;/p&gt;

&lt;p&gt;If you work with E-Commerce, check out the &lt;a href=&quot;http://index.fireclick.com/&quot;&gt;Fireclick Index&lt;/a&gt; which publishes a list of conversion rates for different types of e-commerce websites each month, and that can offer some sort of guide as to average conversion rates, and how you are performing.&lt;/p&gt;

&lt;p&gt;You should of course be aiming to out perform the average, as this makes your advertising cheaper (lower customer acquisition costs), can result in a higher absolute number of customers, which can result in a higher absolute number of repeat-sales.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Google Analytics and Rails in 60 Seconds</title>
   <link href="http://www.mendable.com/2009/07/08/google-analytics-and-rails-in-60-seconds.html"/>
   <updated>2009-07-08T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/07/08/google-analytics-and-rails-in-60-seconds</id>
   <content type="html">&lt;p&gt;This quick post will show you how to install Google Analytics into your Rails powered website in less than 60 seconds.&lt;/p&gt;

&lt;p&gt;Installing Google Analytics into your Ruby on Rails website is very easy. First of all, ensure you are signed up for &lt;a href=&quot;http://www.google.com/analytics&quot;&gt;Google Analytics&lt;/a&gt; if you are not already.&lt;/p&gt;

&lt;p&gt;Once you have your Analytics account setup and you are logged in, you should be able to see the website for which you are tracking statistics, and the tracking ID (will be in the format of &quot;UA-nnnnnn-n&quot;. You will need this now.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkdir app/views/common
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Add this code to &lt;b&gt;app/views/common/_google_analytics.html.erb&lt;/b&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;  var _gaq = _gaq || [];&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  _gaq.push([&amp;#39;_setAccount&amp;#39;, &amp;#39;UA-XXXXX-X&amp;#39;]);&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  _gaq.push([&amp;#39;_trackPageview&amp;#39;]);&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;  (function() {&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    var ga = document.createElement(&amp;#39;script&amp;#39;); ga.type = &amp;#39;text/javascript&amp;#39;; ga.async = true;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    ga.src = (&amp;#39;https:&amp;#39; == document.location.protocol ? &amp;#39;https://ssl&amp;#39; : &amp;#39;http://www&amp;#39;) + &amp;#39;.google-analytics.com/ga.js&amp;#39;;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    var s = document.getElementsByTagName(&amp;#39;script&amp;#39;)[0]; s.parentNode.insertBefore(ga, s);&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;  })();&lt;/span&gt;

&lt;span class=&quot;x&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;(the latest code can be obtained from &lt;a href=&quot;http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;You need to replace the &quot;UA-XXXXX-X&quot; in that code with your own tracking ID. Save and close.&lt;/p&gt;

&lt;p&gt;Rails allows you to easily keep your website design easy to manage, by allowing you to use standardized site layout templates for your entire website (application.html.erb) or for specific controllers or even actions. These files are stored in the &lt;b&gt;app/views/layouts/&lt;/b&gt; directory. One at a time, open each of the files in this directory, and add the following to the end of the file, just before the closing &quot;&amp;lt;&gt;/body&gt;&quot; HTML tag:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;common/google_analytics&amp;#39;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;All done!&lt;/p&gt;

&lt;p&gt;If you want an alternative method of inserting your Google Analytics code into your application, there are &lt;a href=&quot;http://www.juixe.com/techknow/index.php/2007/02/04/rails-google-analytics-plugin/&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;http://www.google.com/search?q=google+analytics+rails&quot;&gt;few&lt;/a&gt; existing plugins that will do the work (what work?) for you. Personally, for such a trivial task, why bother with a plugin? Using plugins all of the time is not the right approach, I would even consider it an anti-pattern of sorts. It creates a whole new set of maintainability problems (what if rails changes the way it works, and those plugins no longer work after upgrade? What if the Google Analytics code needs to be updated, but the plugin is no longer being maintained, but you had no idea that was the case? In every case, the decision to use plugins or not can only be decided after weighing up the pro's and con's of each choice. My general rule (some exceptions obviously) is, if I can do it in 5 minutes or less, a plugin is probably not a good idea.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Correct Format Plugin Released</title>
   <link href="http://www.mendable.com/2009/07/04/rails-correct-format-plugin.html"/>
   <updated>2009-07-04T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/07/04/rails-correct-format-plugin</id>
   <content type="html">&lt;p&gt;I have released a new Plugin for Rails, called &lt;strong&gt;Correct-Format&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Github URL: &lt;a href=&quot;http://github.com/mendable/correct-format&quot;&gt;github.com/mendable/correct-format&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This plugin allows you to automatically correct simple user input mistakes and format user-input without raising an ActiveRecord Error and without inserting inconsistently formatted data into your database. Using this plugin will enhance the usability and user-friendlyness of your application and increase your data integrity.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;You can automatically:&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make a field uppercase&lt;/li&gt;
&lt;li&gt;Make a field lowercase&lt;/li&gt;
&lt;li&gt;Capitalize the first letter of the first word (and lower case everything else)&lt;/li&gt;
&lt;li&gt;Capitalize the first letter of all words (and lower case everything else)&lt;/li&gt;
&lt;li&gt;Replace comma with period and downcase email addresses&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Installation&lt;/h2&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;tcsh&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git submodule add git://github.com/mendable/correct-format.git vendor/plugins/correct-format
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit -am &lt;span class=&quot;s2&quot;&gt;&amp;quot;add correct-format plugin&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ensure that you have this in your config/deploy.rb:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:git_enable_submodules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;so that the submodules are pulled down when you deploy your application.&lt;/p&gt;

&lt;h2&gt;Example Usage&lt;/h2&gt;




&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Make usernames consistently lower case&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;correct_format_downcase&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:username&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Replace comma&amp;#39;s with periods in email address, and make email address all lower case&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;correct_format_email&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Capitalize first letter of first word, and downcase the rest&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;correct_format_capitalize&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:username&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Capitalize all first letters of ALL WORDS in the string&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;correct_format_capitalize_each&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:address_line_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:address_line_2&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# UK Postcodes are upper case&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;correct_format_upcase&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:postcode&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# apply a function to EVERY string field in a record&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;correct_format_capitalize&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;column_for_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Feedback and patches welcome.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Howto Display a GitHub Changelog in your application</title>
   <link href="http://www.mendable.com/2009/06/27/howto-display-a-github-changelog-in-your-application.html"/>
   <updated>2009-06-27T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/06/27/howto-display-a-github-changelog-in-your-application</id>
   <content type="html">&lt;p&gt;In this post I will show you a simple way to display a list of your GitHub changes inside your application.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/github_changes_screenshot.png&quot; alt=&quot;github_changes_screenshot&quot; title=&quot;github_changes_screenshot&quot; width=&quot;522&quot; height=&quot;271&quot; style=&quot;display:block;clear:both;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This can be useful for so many reasons, not least helping to create a better relationship between your users and your developers. This obviously would not be applicable in all circumstances, but in many cases, having a Changelog inside your application (especially where the end users already work closely with the application developers) can enable them to see what work has been done, and what new features are available to them. This is also fantastically useful for allowing Project managers to keep track of development changes.&lt;/p&gt;

&lt;p&gt;The code below will pull out the last 20 GitHub commit comments from your GitHub project, and display them in a table, and with a bit of CSS styling will look something like the screenshot above, or better!&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;th&amp;gt;When&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;th&amp;gt;Description&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent_website_changes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`git log -20 --abbrev-commit --pretty=format:&amp;quot;%H %cr - %s&amp;quot;`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;   
&lt;span class=&quot;n&quot;&gt;recent_website_changes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/\n/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ln&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;     
    &lt;span class=&quot;n&quot;&gt;commit_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ln&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/ /&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;     
    &lt;span class=&quot;n&quot;&gt;without_commit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ln&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commit_code&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     
    &lt;span class=&quot;n&quot;&gt;commit_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;without_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/ - /&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;     
    &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;without_commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commit_time&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; - &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commit_time&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;link_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;view&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;https://github.com/your-github-username/your-project-name/commit/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commit_code&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;    &amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;x&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Another advantage of displaying your commit log publicly to other non-developers is that it can incentivize your developers to think carefully about writing better commit messages, knowing they will have to be read by others.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Set your Rails Environment Globally</title>
   <link href="http://www.mendable.com/2009/06/20/set-your-rails-environment-globally.html"/>
   <updated>2009-06-20T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/06/20/set-your-rails-environment-globally</id>
   <content type="html">&lt;p&gt;In much of the rails documentation it is suggested that when you want to run a task in a specific environment, you should set the RAILS_ENV environment variable on the command line where you are running the task.&lt;/p&gt;

&lt;p&gt;For example, assume you want to run &lt;b&gt;rake db:migrate&lt;/b&gt; on the production system (should be done automatically by Capistrano, but anyway..), because it is the production system, you would have to declare your rails environment in the command line, so you would actually have to run &lt;b&gt;RAILS_ENV=production rake db:migrate&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Well, this becomes tedious sometimes, and open to human error as well. Luckily there is a way around this.&lt;/p&gt;

&lt;p&gt;The solution is simple.&lt;/p&gt;

&lt;p&gt;Add it to your &lt;b&gt;/etc/environment&lt;/b&gt; file:&lt;/p&gt;

&lt;pre&gt;RAILS_ENV=production&lt;/pre&gt;


&lt;p&gt;You may have to log out and log in again of your shell for it to take effect. Put this on your production server, and any command that runs on that production server will automatically default to the production environment. This includes cron jobs, and other users logging into the same system.&lt;/p&gt;

&lt;p&gt;Handy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to protect a folder by IP address in Nginx</title>
   <link href="http://www.mendable.com/2009/06/20/how-to-protect-a-folder-by-ip-address-in-nginx.html"/>
   <updated>2009-06-20T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/06/20/how-to-protect-a-folder-by-ip-address-in-nginx</id>
   <content type="html">&lt;p&gt;To protect a folder by IP address in nginx is fairly simple, see the example below that demonstrates only allowing access to the /protected folder for people in the 192.168.0.* network.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;nginx&quot;&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;....&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/protected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;allow&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;192&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.168.0.0/24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;deny&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>Nudge Book and User-Website Interactions</title>
   <link href="http://www.mendable.com/2009/06/18/nudge-book-and-user-website-interactions.html"/>
   <updated>2009-06-18T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/06/18/nudge-book-and-user-website-interactions</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/images/posts/nudge_book_cover.jpg&quot; alt=&quot;nudge_book_cover&quot; title=&quot;nudge_book_cover&quot; width=&quot;150&quot; height=&quot;200&quot; style=&quot;float:left; margin-right: 20px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have been reading the book &lt;a href=&quot;http://www.amazon.co.uk/Nudge-Improving-Decisions-Health-Happiness/dp/0141040017/&quot;&gt;Nudge: Improving Decisions About Health, Wealth and Happiness&lt;/a&gt; recently.&lt;/p&gt;

&lt;p&gt;The book talks about how &quot;choice architects&quot; can make small changes to the way choices are presented (in every day life) and have a huge impact on the choices that people make.&lt;/p&gt;

&lt;p&gt;What I found particularly interesting is how many of the idea's in the book can be taken and applied to the Internet and websites we build, helping guide users to the best choices and also increase conversion rates for the Website, creating a better experience for the user, increasing user retention rates, user satisfaction, and ultimately profitability for the business.&lt;/p&gt;

&lt;p&gt;Highly recommended.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>5 Simple rules for managing your Email Inbox</title>
   <link href="http://www.mendable.com/2009/06/12/5-simple-rules-for-managing-your-email-inbox.html"/>
   <updated>2009-06-12T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/06/12/5-simple-rules-for-managing-your-email-inbox</id>
   <content type="html">&lt;p&gt;&lt;img style=&quot;clear:both&quot; title=&quot;email-stress&quot; src=&quot;/images/posts/email-stress.jpg&quot; alt=&quot;email-stress&quot; width=&quot;548&quot; height=&quot;354&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A few years ago, one of the most time consuming but un-productive parts of my day was checking and managing email Inbox. Back then, I used to have one big list of all my emails (the Inbox), with things I did not need to see ever again continuously taking up screen space and brain time.&lt;/p&gt;

&lt;p&gt;Then It dawned on me... there must be a better way to handle this.&lt;/p&gt;

&lt;p&gt;There was.&lt;/p&gt;

&lt;p&gt;All emails can be categorised in 5 ways, and depending on what category any particular email falls into, depends on what action to take. This simple set of rules increased my productivity so much, that at the end of a days work, I almost always have a completely empty Inbox!&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Things I need to reply to -&lt;/strong&gt;Fairly simple. If I need to reply to it, then I reply to it straight away. The trick with this rule is, never let something sit there for a few hours (or even days) before replying to it. (otherwise, you end up with a big Inbox full of emails you intended to reply to, but...)&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Things I have replied to - &lt;/strong&gt;After replying to an email, unless there is more work for me to do, get rid of it. File it away. Archive it. If it is delt with, then it must disappear. Solution for this? The &quot;Archive&quot; button in Gmail. Generally, if it was important enough for me to reply to it, it is probably worth saving around out of sight. Another tip here: If someone emails you asking for something, you email them back (eg, requesting more info, etc), Archive the email right now. The ball is in their court, don't let your own brain spend time looking at things where you are waiting on other people.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Things I need to do - &lt;/strong&gt;eg, someone has requested I do something etc. This is the ONLY thing that is allowed to stay in my Inbox.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Things I care about, but don't need to action  - &lt;/strong&gt;Say for example, receipts for purchases etc, in this case, it can be Archived straight away.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Things I do not care about&lt;/strong&gt; - DELETE. But, before I do, I need to know, will I get this again next week? Having to click delete every week is still time consuming. My strategy here is to try and always close accounts of services that I do not use any more, un-subscribe from mailing lists I am no longer interested in. Where this is not possible, setup email filters to automatically delete those emails.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Following these simple rules, I have managed to significantly reduce the amount of time I spend each day handling my email. The number of emails I end up looking at each day is probably down by 80% compared to several years ago. The process of checking mail is fast, efficient and hassle free. Just the way I like it. Now time for a cup of Tea!&lt;/p&gt;

&lt;p&gt;How do you maximise your email productivity?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mass Find/replace for Rails Tests</title>
   <link href="http://www.mendable.com/2009/05/26/mass-findreplace-for-rails-tests.html"/>
   <updated>2009-05-26T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/05/26/mass-findreplace-for-rails-tests</id>
   <content type="html">&lt;p&gt;After upgrading an old project to Rails 2.3.2,my tests were failing to run, bombing out with an error like:&lt;/p&gt;

&lt;pre&gt;./test/unit/my_model.rb:4: undefined method `fixtures' for MyModelTest:Class (NoMethodError)&lt;/pre&gt;


&lt;p&gt;This was because in Rails 2.3.2, tests have to derive from ActiveSupport::TestCase, and not the old Test::Unit::TestCase.&lt;/p&gt;

&lt;p&gt;A quick find and replace soon has us up and running again:
&lt;code&gt;perl -pi -w -e 's/Test::Unit::TestCase/ActiveSupport::TestCase/g;' test/unit/*.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Effectively, this one-liner searches through all the files in the test/unit directory, and replaces all instances of &quot;Test::Unit::TestCase&quot; with &quot;ActiveSupport::TestCase&quot;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Git Submodules and Capistrano</title>
   <link href="http://www.mendable.com/2009/04/22/git-submodules-and-capistrano.html"/>
   <updated>2009-04-22T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/04/22/git-submodules-and-capistrano</id>
   <content type="html">&lt;p&gt;Small point of reference, if you use git submodules in your rails application, then remember to add:&lt;/p&gt;

&lt;blockquote&gt;set :git_enable_submodules, true&lt;/blockquote&gt;


&lt;p&gt;to your deploy recipe. This is not very well documented as a lot of documentation on the web for capistrano was written before &lt;a href=&quot;http://dev.rubyonrails.org/changeset/8755&quot;&gt;this feature was included&lt;/a&gt;, and before git was widely used.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Where are your users from? - (By SQL Email Domain)</title>
   <link href="http://www.mendable.com/2009/04/19/sql-trick-where-are-your-users-from.html"/>
   <updated>2009-04-19T00:00:00-07:00</updated>
   <id>http://www.mendable.com/2009/04/19/sql-trick-where-are-your-users-from</id>
   <content type="html">&lt;p&gt;Ever wondered who your users use as their email provider? Who are the biggest email providers of the users on your website? Luckily SQL has the answer in 1 easy step using the &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_substring-index&quot;&gt;SUBSTRING_INDEX&lt;/a&gt; string function.&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;&lt;span class=&quot;n&quot;&gt;mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;n&quot;&gt;SUBSTRING_INDEX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;@&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Domain&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBSTRING_INDEX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;@&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;LIMIT&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;-------+------------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Domain&lt;/span&gt;           &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;-------+------------------+&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hotmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;999&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yahoo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uk&lt;/span&gt;      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;888&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;777&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btinternet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;666&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yahoo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;555&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hotmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uk&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;444&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;333&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ntlworld&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;222&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tiscali&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uk&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;111&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eircom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;net&lt;/span&gt;       &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;-------+------------------+&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

</content>
 </entry>
 
 
</feed>
