<feed xmlns="http://www.w3.org/2005/Atom">
  <title>ghickman</title>
  <link href="http://ghickman.co.uk/" />
  <link href="http://ghickman.co.uk/atom.xml" rel="self" />
  <updated>2013-01-05T23:26:17+00:00</updated>
  <id>tag:ghickman.co.uk,2007-07-03:1</id>
  <author>
    <name>George Hickman</name>
  </author>
  <entry>
    <title>Expanding your RAID-5 Array</title>
    <link href="http://ghickman.co.uk//2013/01/06/expanding-your-raid-5-array.html" />
    <updated>2013-01-06T00:00:00+00:00</updated>
    <id>tag:ghickman.co.uk,2013-01-06:/2013/01/06/expanding-your-raid-5-array.html</id>
    <content type="html">
      &lt;p&gt;Every so often the time comes around again where I run out of space on my fileserver. Thankfully I'm using RAID-5 so expanding the array is easy enough and the wonderful &lt;code&gt;mdadm&lt;/code&gt; utility means I can have software RAID so the expansion won't take eons.&lt;/p&gt;
      
      &lt;p&gt;Expanding an array with &lt;code&gt;mdadm&lt;/code&gt; is fairly straightforward:&lt;/p&gt;
      
      &lt;ul&gt;
      &lt;li&gt;Add the new drive to the array&lt;/li&gt;
      &lt;li&gt;Expand the array&lt;/li&gt;
      &lt;li&gt;Expand the file system&lt;/li&gt;
      &lt;/ul&gt;
      
      
      &lt;p&gt;However there are some gotchas along the way that can make the process painful.&lt;/p&gt;
      &lt;h2&gt;Preparation&lt;/h2&gt;
      
      &lt;p&gt;Before I start working on any file system I prefer to know that nothing else is trying to access it so I turn off file sharing services as the first order of business.&lt;/p&gt;
      
      &lt;p&gt;Then unmount the volume and stop the array:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo umount /mnt/media&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo mdadm --stop /dev/md0&lt;/code&gt;&lt;/p&gt;
      
      &lt;h2&gt;Install the New Drive&lt;/h2&gt;
      
      &lt;p&gt;This has always been the most annoying part I've found with expansions. Quite frequently the drive labels will move around. This is no doubt motherboard related and isn't an issue once you're aware of it! But before then it can be confusing and potentially hazardous.&lt;/p&gt;
      
      &lt;h2&gt;Add the New Drive to the Array&lt;/h2&gt;
      
      &lt;p&gt;Now that the drive is physically in place and you know the label you can get on with the fun stuff and add the drive to your array.&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo mdadm --add /dev/md0 /dev/sdf&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Replace &lt;code&gt;/dev/md0&lt;/code&gt; with your array's volume label &lt;code&gt;/dev/sdf&lt;/code&gt; with your drive label.&lt;/p&gt;
      
      &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Some people prefer to partition drives before adding them to the array. Personally I've never had any issues with unpartitioned devices.&lt;/p&gt;
      
      &lt;h2&gt;Expand the Array&lt;/h2&gt;
      
      &lt;p&gt;Now tell the array to use the new drive:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo mdadm --grow --raid-devices=4 /dev/md0&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This part can take anywhere from hours to days, or more, depending on the speed of your machine and the size of disk you're adding to the array.&lt;/p&gt;
      
      &lt;h2&gt;Expand the File System&lt;/h2&gt;
      
      &lt;p&gt;Finally expand your filesystem to fill the new array:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo resize2fs /dev/md0&lt;/code&gt;&lt;/p&gt;
      
      &lt;h2&gt;Finishing Touches&lt;/h2&gt;
      
      &lt;p&gt;The last few bits are reversing what you did before working on the array:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo mount /dev/md0 /mnt/media&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo mdadm --start /dev/md0&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Don't forget to re-enable any services, such as samba or AFP, that you disabled.&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>How to Install Raspbmc when raspbmc.com is Down</title>
    <link href="http://ghickman.co.uk//2012/08/09/install-raspbmc-when-raspbmc-site-down.html" />
    <updated>2012-08-09T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2012-08-09:/2012/08/09/install-raspbmc-when-raspbmc-site-down.html</id>
    <content type="html">
      &lt;p&gt;&lt;code&gt;raspbmc.com&lt;/code&gt; down for you? Never fear, the internet has your back.&lt;/p&gt;
      &lt;h2&gt;Install Script&lt;/h2&gt;
      
      &lt;p&gt;Copy and paste the python code (starts with &lt;code&gt;#!/usr/bin/python&lt;/code&gt;) from &lt;a href=&quot;http://webcache.googleusercontent.com/search?q=cache:http://svn.stmlabs.com/vn/raspbmc/testing/installers/python/install.py&quot;&gt;here&lt;/a&gt; into a file and save it as &lt;code&gt;install.py&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;Set permissions on it: &lt;code&gt;chmod +x install.py&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;When you've downloaded the binary (below) run it with &lt;code&gt;sudo ./install.py&lt;/code&gt;&lt;/p&gt;
      
      &lt;h2&gt;Pre-Download the Install Binary&lt;/h2&gt;
      
      &lt;p&gt;The install script will use &lt;code&gt;installer.img.gz&lt;/code&gt; if it finds it in the same directory so grab that off the University of Arizona mirror:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;curl -O http://mirrors.arizona.edu/raspbmc/downloads/bin/ramdistribution/installer.img.gz&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Now run the install script and you're away!&lt;/p&gt;
      
      &lt;h2&gt;A Big Thank You&lt;/h2&gt;
      
      &lt;p&gt;To &lt;a href=&quot;https://twitter.com/SamNazarko&quot;&gt;Sam Nazarko&lt;/a&gt; for all his hard working actually making Raspbmc! Also to the various people providing mirror services for the install binary.&lt;/p&gt;
      
      &lt;h2&gt;Problems?&lt;/h2&gt;
      
      &lt;p&gt;It's more than likely that the information above will be out of date pretty soon after I post this entry but don't let that deter you. You can always browse raspbmc.com using Google's Cache by placing any URL from the site after &lt;code&gt;http://webcache.googleusercontent.com/search?q=cache:&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;You should get automatically routed to a download mirror by going to:&lt;/p&gt;
      
      &lt;p&gt;&lt;a href=&quot;http://mirrors.arizona.edu/raspbmc/downloads/bin/ramdistribution/installer.img.gz&quot;&gt;http://webcache.googleusercontent.com/search?q=cache:http://download.raspbmc.com/&lt;/a&gt;&lt;/p&gt;
      
      &lt;p&gt;Then find the install image, it's path should look like&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;/downloads/bin/ramdistribution/installer.img.gz&lt;/code&gt;&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>How we use GitHub Flow at Incuna</title>
    <link href="http://ghickman.co.uk//2012/07/29/how-we-use-github-flow-at-incuna.html" />
    <updated>2012-07-29T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2012-07-29:/2012/07/29/how-we-use-github-flow-at-incuna.html</id>
    <content type="html">
      &lt;p&gt;Our team at Incuna has been growing rapidly of late and like most businesses at this stage of growth we've had to come up with some development flows to cope with the influx of new &lt;a href=&quot;http://twitter.com/incuna/incunanauts&quot;&gt;Incunanauts&lt;/a&gt;. Currently we have three (technical) teams: Design, Front End and Back End with work flowing through them in roughly that order. (Technically we have an Ops team, but really that's just me part time).&lt;/p&gt;
      
      &lt;p&gt;We currently use GitHub to host our code, track issues and do pull requests with &lt;a href=&quot;&quot;&gt;hub&lt;/a&gt; for extra features like attaching code to an issue to make a pull request.&lt;/p&gt;
      &lt;h2&gt;Branching&lt;/h2&gt;
      
      &lt;p&gt;When do we branch?&lt;/p&gt;
      
      &lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/3F0H2q0P41091O162b3N/Image%202012.07.21%2000:17:22.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Anything other than a trivial change goes on a branch so it can be pull requested (more on this later). Following GitHub Flow we try to keep a project's master branch production ready which branching allows us to do easily. However, sometimes we have a large, long running, feature to implement which requires it's own master feature branch. This is a bit more involved as you have to make sure you pull request onto the right branch but otherwise works well.&lt;/p&gt;
      
      &lt;p&gt;The most common problem I've seen with this style of branching (as with all programming) is &quot;What do I call my branches&quot;. We try to name our branches directly around the piece of work, even if it isn't immediately obvious to every developer, that's what &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/git-log.html&quot;&gt;git log&lt;/a&gt; is for.&lt;/p&gt;
      
      &lt;h2&gt;Pull Requests&lt;/h2&gt;
      
      &lt;p&gt;As an extension of our branching we try to use pull requests as our main area of code review. When we first started using this as a formal method it worked quite well but more recently we've started to see the benefit of using the pull request as a forum of conversation around a bug/feature. We're still slowly moving Designers and Account Managers onto this flow and it seems to work well once they get into it.&lt;/p&gt;
      
      &lt;h2&gt;Code Review&lt;/h2&gt;
      
      &lt;p&gt;While pull requests are great it's been important for us to avoid hard rules for this sort of work flow. Even if the code has been done on a branch it's quite feasible for someone to have migrations that break the database or a block of code that everyone else needs ASAP to carry on. In this situation we bring in the Master Code Reviewers [read: the nearest developer who is ideally not on your project, thus fresh set of eyes].&lt;/p&gt;
      
      &lt;p&gt;The most important part of this for us is to have more than one set of eyes look at new code, ideally someone who isn't familiar with it. This way we're more likely to avoid obvious bugs and create maintainable code.&lt;/p&gt;
      
      &lt;h2&gt;Testing&lt;/h2&gt;
      
      &lt;p&gt;Always a sticky subject, but we're slowly getting better at it. &lt;a href=&quot;http://github.com/meshy&quot;&gt;Charlie&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://github.com/mjtamlyn&quot;&gt;Marc&lt;/a&gt; have made great headway in setting up our large internal libraries with proper test suites and a general purge of all fixture based unit tests in favour of factories using the very awesome &lt;a href=&quot;https://github.com/dnerdy/factory_boy&quot;&gt;Factory Boy&lt;/a&gt;. I'm hoping &lt;a href=&quot;http://travis-ci.org&quot;&gt;Travis CI&lt;/a&gt; will bring out pro/private accounts soon as their testing suite would suit our pull request flow perfectly and we're already moving our open source projects to them.&lt;/p&gt;
      
      &lt;h2&gt;What Can We Do Better?&lt;/h2&gt;
      
      &lt;h3&gt;Deployments.&lt;/h3&gt;
      
      &lt;p&gt;Our current situation is sharded across three different service but unfortunately this is due to the nature of our business as customers have differing needs. Currently I do the majority of the deployments. However, it &lt;em&gt;can&lt;/em&gt; be easier. Eventually I want any technical person to be both capable and willing to deploy an existing site.&lt;/p&gt;
      
      &lt;h3&gt; Testing Culture&lt;/h3&gt;
      
      &lt;p&gt;I think this is something that will come over time and is really a social problem, especially as we begin to firm up the ways in which we actually test projects, it should become second nature.&lt;/p&gt;
      
      &lt;p&gt;The Front End team has been talking about setting up testing for our Javascript projects for a while along with Selenium which I'd really like to see in action.&lt;/p&gt;
      
      &lt;h2&gt;Conclusion&lt;/h2&gt;
      
      &lt;p&gt;Our workflow is centred around being social and avoiding project specialists (i.e. only one person knows about a project). I think the current situation is very good and we're improving upon it all the time, but it can always be better. Hopefully time and &lt;a href=&quot;http://henryblyth.tumblr.com/&quot;&gt;new&lt;/a&gt; Incunanauts will show we're on the right track!&lt;/p&gt;
      
      &lt;h2&gt;TL;DR&lt;/h2&gt;
      
      &lt;p&gt;Be social, use good tools and don't have rules just best practices.&lt;/p&gt;
      
      &lt;p&gt;Incuna is &lt;a href=&quot;http://incuna.com/jobs&quot;&gt;hiring&lt;/a&gt;!&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Setup Single Sign On in Django using Google OAuth2</title>
    <link href="http://ghickman.co.uk//2012/07/22/google-oauth2-sso-with-django.html" />
    <updated>2012-07-22T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2012-07-22:/2012/07/22/google-oauth2-sso-with-django.html</id>
    <content type="html">
      &lt;p&gt;We recently had our second Incuna Hack Day where &lt;a href=&quot;http://www.github.com/meshy&quot;&gt;Charlie&lt;/a&gt; and I made the decision to start breaking up the main internal site, our venerable Dashboard. It was well on its way to becoming a monolithic beast and the only thing that had stopped me breaking it up before was an easy way to add Single Sign On to the many apps it would become.&lt;/p&gt;
      
      &lt;p&gt;Enter &lt;a href=&quot;http://django-social-auth.readthedocs.org/en/latest/index.html&quot;&gt;Django Social Auth&lt;/a&gt;. A cover-all-the-bases authentication app that provides backends for pretty much every service you can think of.&lt;/p&gt;
      
      &lt;p&gt;This write-up is based on my experience setting up a few internal apps so it's fairly opinionated towards that goal, but hopefully it's still adaptable to other situations!&lt;/p&gt;
      &lt;h2&gt;Setup your App in Google's API Console&lt;/h2&gt;
      
      &lt;p&gt;In Google's &lt;a href=&quot;https://code.google.com/apis/console&quot;&gt;API Console&lt;/a&gt; create a new project.&lt;/p&gt;
      
      &lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/1i353P2Q162K3G440o0R/Screen%20Shot%202012-07-15%20at%2021.11.02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;You don't need to turn on any extra services, so go directly to &lt;code&gt;API Access&lt;/code&gt; and hit the giant blue button to get started.&lt;/p&gt;
      
      &lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/323j183V3n0j0s1H1A2p/Screen%20Shot%202012-07-15%20at%2021.12.26.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Enter your Product name and the URL to a logo if you have one. These are the details users will see when they authenticate via Google. Click &lt;code&gt;Next&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;Now set up the credentials for your application (this is per environment due to the redirect URI). The example below is for development, but only the hostname needs to change between environments.&lt;/p&gt;
      
      &lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/3f2M0e0r0z3D120X1f2z/Screen%20Shot%202012-07-15%20at%2021.16.47.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Click &lt;code&gt;more options&lt;/code&gt; to set the callback path. The default Social Auth URL for this is &lt;code&gt;/complete/google-oauth2/&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;&lt;img src=&quot;http://f.cl.ly/items/3q2P0j173i2Q000r3i24/Screen%20Shot%202012-07-15%20at%2021.21.40.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
      
      &lt;p&gt;Click &lt;code&gt;Create client id&lt;/code&gt; and grab your &lt;code&gt;Client ID&lt;/code&gt;/&lt;code&gt;Client secret&lt;/code&gt; combo for the next step.&lt;/p&gt;
      
      &lt;h2&gt;Setup Django Social Auth&lt;/h2&gt;
      
      &lt;p&gt;Add &lt;code&gt;social_auth&lt;/code&gt; to your &lt;code&gt;INSTALLED_APPS&lt;/code&gt; and the other settings below:&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;        &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;              &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;n&quot;&gt;AUTHENTICATION_BACKENDS&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&gt;&lt;span class=line id=LC2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;s&quot;&gt;&amp;#39;social_auth.backends.google.GoogleOAuth2Backend&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;s&quot;&gt;&amp;#39;django.contrib.auth.backends.ModelBackend&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&lt;span class=&quot;n&quot;&gt;LOGIN_REDIRECT_URL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&lt;span class=&quot;n&quot;&gt;GOOGLE_OAUTH2_CLIENT_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;GOOGLE_OAUTH2_CLIENT_ID&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;span class=&quot;n&quot;&gt;GOOGLE_OAUTH2_CLIENT_SECRET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;GOOGLE_OAUTH2_CLIENT_SECRET&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&lt;span class=&quot;n&quot;&gt;GOOGLE_WHITE_LISTED_DOMAINS&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;s&quot;&gt;&amp;#39;incuna.com&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&lt;span class=&quot;n&quot;&gt;SOCIAL_AUTH_USER_MODEL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;auth.User&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;br/&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;          &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/3118490/e6a46d3e07848bf92e2b167aba12c4ce0f2ccf89/settings.py&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3118490#file_settings.py&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;settings.py&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3118490&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;&lt;/div&gt;
      
      
      &lt;p&gt;Here I whitelist our Google Apps domain to only allow authentication by users from work email addresses and tell Social Auth to use the &lt;code&gt;auth.User&lt;/code&gt; model when creating new users which it will do by default (I believe you can turn this off with another setting). This lets met forget about registration completely which is perfect for internal applications.&lt;/p&gt;
      
      &lt;p&gt;Make sure you've set &lt;code&gt;GOOGLE_OAUTH2_CLIENT_ID&lt;/code&gt; and &lt;code&gt;GOOGLE_OAUTH2_CLIENT_SECRET&lt;/code&gt; in your environment when you do &lt;code&gt;runserver&lt;/code&gt; or you'll get the crappy settings error message &lt;code&gt;Unknown command: 'runserver'&lt;/code&gt;. You can avoid this using &lt;code&gt;.get()&lt;/code&gt; instead of square braces notation when getting the Google credentials however the error may be more archaic. I'm currently favouring square braces notation and getting used to fixing my environment!&lt;/p&gt;
      
      &lt;h2&gt;Create Some Basic Views&lt;/h2&gt;
      
      &lt;div class=&quot;gist&quot;&gt;        &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;              &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.core.urlresolvers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.http&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponseRedirect&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.views.generic.base&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;View&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;social_auth.backends.exceptions&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthFailed&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;social_auth.views&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthComplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&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;args&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;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;backend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;backend&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;backend&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;args&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;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthFailed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Your Google Apps domain isn&amp;#39;t authorized for this app&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponseRedirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;login&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC18&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC19&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC20&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoginError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC21&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&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;args&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;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC22&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC23&gt;&lt;br/&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;          &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/3118490/4623c5610a4e2d015127fca361335f418bcf0a02/views.py&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3118490#file_views.py&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;views.py&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3118490&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;&lt;/div&gt;
      
      
      &lt;p&gt;Social Auth requires you add a view for when login fails. So far this hasn't been an issue for me so I've done the pure basics here with &lt;code&gt;LoginError&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;The second view was to cope with the whitelisting of domains which, pleasingly, raises an &lt;code&gt;AuthFailed&lt;/code&gt; exception when you try to authenticate with a domain not in the whitelist.&lt;/p&gt;
      
      &lt;p&gt;Now all we need is to plumb this in with some URLs:&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;        &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;              &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.conf.urls&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.contrib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;.views&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthComplete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LoginError&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autodiscover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&lt;span class=&quot;n&quot;&gt;urlpatterns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patterns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c&quot;&gt;# some other urls&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r&amp;#39;^admin/&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r&amp;#39;^complete/(?P&amp;lt;backend&amp;gt;[^/]+)/$&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthComplete&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r&amp;#39;^login-error/$&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LoginError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;as_view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;social_auth.urls&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;          &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/3118490/37866c8da165c09f90604987072e63cf5454f25d/urls.py&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3118490#file_urls.py&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;urls.py&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3118490&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;&lt;/div&gt;
      
      
      &lt;h2&gt;Profit&lt;/h2&gt;
      
      &lt;p&gt;I usually put &lt;code&gt;login_required&lt;/code&gt; on the whole site with a little piece of middleware (like &lt;a href=&quot;http://djangosnippets.org/snippets/1179/&quot;&gt;this&lt;/a&gt; or &lt;a href=&quot;http://djangosnippets.org/snippets/1220/&quot;&gt;this&lt;/a&gt;) but otherwise that's it!&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Generating unique slugs with Django</title>
    <link href="http://ghickman.co.uk//2012/07/15/generating-unique-slugs-with-django.html" />
    <updated>2012-07-15T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2012-07-15:/2012/07/15/generating-unique-slugs-with-django.html</id>
    <content type="html">
      &lt;p&gt;This is something I've come across a couple of times over the last few months and each time ended up acking through various projects so putting this up here to save myself the pain next time!&lt;/p&gt;
      
      &lt;p&gt;There are two versions to this method - model specific and a more generic one intended for a &lt;code&gt;utils&lt;/code&gt; module if you're going to use it on more than one model.&lt;/p&gt;
      
      &lt;p&gt;Neither of these methods is built to scale, but since I've never worked at scale this hasn't been an issue. However you've been warned!&lt;/p&gt;
      &lt;p&gt;The functions make the slug unique by appending a count to the end and checking the length is still valid for the slug field.&lt;/p&gt;
      
      &lt;h2&gt;Model Specific&lt;/h2&gt;
      
      &lt;div class=&quot;gist&quot;&gt;        &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;              &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.template.defaultfilters&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&lt;span class=&quot;nd&quot;&gt;@classmethod&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generate_slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;count&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&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_get_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&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;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_get_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&amp;#39;{0}-{1}&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c&quot;&gt;# make sure the slug is not too long&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;slug&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;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&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&gt;&lt;span class=line id=LC17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&amp;#39;{0}-{1}&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC18&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&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&gt;&lt;span class=line id=LC19&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC20&gt;&lt;br/&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;          &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/3116929/6e4f79a58709faf5223ebc57e1dc1587f68d05b1/specific.py&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3116929#file_specific.py&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;specific.py&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3116929&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;&lt;/div&gt;
      
      
      &lt;p&gt;&lt;em&gt;example usage&lt;/em&gt;: &lt;code&gt;MyModel.objects.create(name='foo', slug=MyModel.generate_slug('foo'))&lt;/code&gt;&lt;/p&gt;
      
      &lt;h2&gt;Generic&lt;/h2&gt;
      
      &lt;div class=&quot;gist&quot;&gt;        &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;              &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;django.template.defaultfilters&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generate_slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;count&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&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__class__&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_get_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&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;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&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;kwargs&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;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_get_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&amp;#39;{0}-{1}&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c&quot;&gt;# make sure the slug is not too long&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_meta&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;slug&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;n&quot;&gt;max_length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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&gt;&lt;span class=line id=LC18&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;u&amp;#39;{0}-{1}&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC19&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&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&gt;&lt;span class=line id=LC20&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slug&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;          &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/3116929/fa8e9d6d0ee6e83e165ecc2ff7bee1ec177fa1ff/generic.py&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3116929#file_generic.py&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;generic.py&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/3116929&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;&lt;/div&gt;
      
      
      &lt;p&gt;&lt;em&gt;example usage&lt;/em&gt;: &lt;code&gt;AnotherModel.objects.create(name='bar', slug=generate_slug(AnotherModel, 'foo'))&lt;/code&gt;&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Extending OS X Lion's Maxfiles Limit for Neo4J</title>
    <link href="http://ghickman.co.uk//2012/02/25/osx-max-files-limit-neo4j.html" />
    <updated>2012-02-25T00:00:00+00:00</updated>
    <id>tag:ghickman.co.uk,2012-02-25:/2012/02/25/osx-max-files-limit-neo4j.html</id>
    <content type="html">
      &lt;p&gt;After upgrading to Neo4j 1.6 today I got this warning when starting the server:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;Detected a limit of 512 for maximum open files.&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;A limit of 40000 is suggested instead and a quick look on Google suggests the use of &lt;code&gt;launchctl limit&lt;/code&gt; or &lt;code&gt;ulimit -n&lt;/code&gt;. However the results I found were split between how Linux deals with this issue (&lt;code&gt;ulimit -n&lt;/code&gt;) and pre Lion fixes that involve using &lt;code&gt;unlimited&lt;/code&gt; as the hard limit (which hasn't worked since Leopard).&lt;/p&gt;
      &lt;p&gt;Setting a higher limit on lion is fairly simple. Edit &lt;code&gt;launchd.conf&lt;/code&gt; like so (it might not exist):&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo vim /etc/launchd.conf&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Then add this line to it:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;limit maxfiles 1000000 1000000&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;This tells Lion to set both the soft and hard limit (in that order) to &lt;code&gt;1000000&lt;/code&gt;. I picked such a high value to avoid any issues of the same nature in the future.&lt;/p&gt;
      
      &lt;p&gt;Make sure you restart afterwards for the changes to take effect.&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Setup Gitalist with Gitolite on Nginx</title>
    <link href="http://ghickman.co.uk//2011/07/24/gitolite-gitalist-nginx.html" />
    <updated>2011-07-24T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2011-07-24:/2011/07/24/gitolite-gitalist-nginx.html</id>
    <content type="html">
      &lt;p&gt;I recently gave &lt;a href=&quot;https://github.com/&quot;&gt;Github's&lt;/a&gt; paid service a go when my vimrc ended up needing some passwords in it. While I'm a big fan of Github and what it's done for the Git community as a whole I just can't justify paying the £5 a month so I can use my vimrc at home, work and a few servers. Of course the downside is the loss of being able to quickly view code on the web, but as fate would have it Twitter came to my rescue within a couple of days via the sagely &lt;a href=&quot;http://developwithstyle.com/&quot;&gt;Joel Moss&lt;/a&gt;.&lt;/p&gt;
      
      &lt;!-- https://twitter.com/joelmoss/status/89637329731461121 --&gt;
      
      
      &lt;!-- https://twitter.com/joelmoss/status/89637329731461121 --&gt;
      
      
      &lt;p&gt; &lt;style type='text/css'&gt;.bbpBox89637329731461121 {background:url(http://a1.twimg.com/images/themes/theme5/bg.gif) #352726;padding:20px;} p.bbpTweet{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} p.bbpTweet span.metadata{display:block;width:100%;clear:both;margin-top:8px;padding-top:12px;height:40px;border-top:1px solid #fff;border-top:1px solid #e6e6e6} p.bbpTweet span.metadata span.author{line-height:19px} p.bbpTweet span.metadata span.author img{float:left;margin:0 7px 0 0px;width:38px;height:38px} p.bbpTweet a:hover{text-decoration:underline}p.bbpTweet span.timestamp{font-size:12px;display:block}&lt;/style&gt; &lt;div class='bbpBox89637329731461121'&gt;&lt;p class='bbpTweet'&gt;Gitalist - a modern git web viewer &lt;a href=&quot;http://j.mp/pJEQtN&quot; rel=&quot;nofollow&quot;&gt;http://j.mp/pJEQtN&lt;/a&gt;&lt;span class='timestamp'&gt;&lt;a title='Sat Jul 09 10:09:39 +0000 2011' href='https://twitter.com/joelmoss/status/89637329731461121'&gt;less than a minute ago&lt;/a&gt; via &lt;a href=&quot;http://reederapp.com&quot; rel=&quot;nofollow&quot;&gt;Reeder&lt;/a&gt; &lt;a href='http://twitter.com/intent/favorite?tweet_id=89637329731461121'&gt;&lt;img src='http://si0.twimg.com/images/dev/cms/intents/icons/favorite.png' /&gt; Favorite&lt;/a&gt; &lt;a href='http://twitter.com/intent/retweet?tweet_id=89637329731461121'&gt;&lt;img src='http://si0.twimg.com/images/dev/cms/intents/icons/retweet.png' /&gt; Retweet&lt;/a&gt; &lt;a href='http://twitter.com/intent/tweet?in_reply_to=89637329731461121'&gt;&lt;img src='http://si0.twimg.com/images/dev/cms/intents/icons/reply.png' /&gt; Reply&lt;/a&gt;&lt;/span&gt;&lt;span class='metadata'&gt;&lt;span class='author'&gt;&lt;a href='http://twitter.com/joelmoss'&gt;&lt;img src='http://a2.twimg.com/profile_images/1208340303/pocoyo_avatar_normal.png' /&gt;&lt;/a&gt;&lt;strong&gt;&lt;a href='http://twitter.com/joelmoss'&gt;Joel Moss&lt;/a&gt;&lt;/strong&gt;&lt;br/&gt;joelmoss&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt; &lt;!-- end of tweet --&gt;&lt;/p&gt;
      
      &lt;p&gt;Diving into &lt;a href=&quot;http://www.gitalist.com/&quot;&gt;Gitalist&lt;/a&gt; there were a couple of surprises, least of all it's written in Perl. &lt;em&gt;Perl?! That's a dead language right? (Unless you're slashdot)&lt;/em&gt;. However playing around with the demo (guys, please up whatever server you're running that on, it's dire) was great, not to mention it looks really slick.&lt;/p&gt;
      &lt;p&gt;Gitalist also presented an opportunity to coax my workplace from Mercurial/Bitbucket (Github's corporate pricing has so far been the major reason not to use Git) onto Git, but to do so some sort of access control would be needed, thus &lt;a href=&quot;https://github.com/sitaramc/gitolite&quot;&gt;Gitolite&lt;/a&gt;.&lt;/p&gt;
      
      &lt;p&gt;I've tested these instructions on Ubuntu Server 10.04 so they should work reasonably well on other Ubuntu versions and child distros.&lt;/p&gt;
      
      &lt;h2&gt;Gitolite&lt;/h2&gt;
      
      &lt;p&gt;Gitolite is an access control system for Git repositories, a natural successor to &lt;a href=&quot;http://scie.nti.st/2007/11/14/hosting-git-repositories-the-easy-and-secure-way&quot;&gt;Gitosis&lt;/a&gt;, providing fine grained control on a per branch basis. I won't bother going into much detail as there's so much to it and &lt;a href=&quot;http://sitaramc.blogspot.com/&quot;&gt;Sitraramc&lt;/a&gt; provides a far more comprehensive description on the Github &lt;a href=&quot;https://github.com/sitaramc/gitolite/wiki/&quot;&gt;page&lt;/a&gt;.&lt;/p&gt;
      
      &lt;p&gt;I followed the &lt;a href=&quot;http://sitaramc.github.com/gitolite/doc/1-INSTALL.html#_root_method&quot;&gt;root install instructions&lt;/a&gt; with a couple of caveats:&lt;/p&gt;
      
      &lt;p&gt;I specify the folder locations when running &lt;code&gt;src/gl-system-install&lt;/code&gt; as it didn't seem to use the default one's listed for me:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;src/gl-system-install /usr/local/bin /usr/local/share/gitolite/conf /usr/local/share/gitolite/hooks&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;When adding the git user, rather than just doing a plain &lt;code&gt;useradd git&lt;/code&gt; I set some options:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo adduser --system --shell /bin/bash --gecos 'git version control' --group --disabled-password --home /home/git git&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;and then run the &lt;code&gt;su - git&lt;/code&gt; command with &lt;code&gt;sudo&lt;/code&gt; so you can enter your own password.&lt;/p&gt;
      
      &lt;p&gt;Check you can push your projects to the server and you're away!&lt;/p&gt;
      
      &lt;h2&gt;Gitalist&lt;/h2&gt;
      
      &lt;h3&gt;Installation (CPAN)&lt;/h3&gt;
      
      &lt;p&gt;After some fruitless attempts to install from source and &lt;a href=&quot;http://search.cpan.org/dist/Gitalist/lib/Gitalist.pm#BOOTSTRAPPING&quot;&gt;bootstrap&lt;/a&gt; I turned to the IRC channel where a Big Damn Hero pointed me at CPAN as the &quot;Way to Go&quot;.&lt;/p&gt;
      
      &lt;p&gt;First of all CPAN needs a little love. By default it asks you what to do when it finds a dependency it doesn't have.&lt;/p&gt;
      
      &lt;!-- http://twitter.com/ghickman/statuses/89982230209904641 --&gt;
      
      
      &lt;!-- http://twitter.com/ghickman/statuses/89982230209904641 --&gt;
      
      
      &lt;p&gt; &lt;style type='text/css'&gt;.bbpBox89982230209904641 {background:url(http://a1.twimg.com/images/themes/theme2/bg.gif) #C6E2EE;padding:20px;} p.bbpTweet{background:#fff;padding:10px 12px 10px 12px;margin:0;min-height:48px;color:#000;font-size:18px !important;line-height:22px;-moz-border-radius:5px;-webkit-border-radius:5px} p.bbpTweet span.metadata{display:block;width:100%;clear:both;margin-top:8px;padding-top:12px;height:40px;border-top:1px solid #fff;border-top:1px solid #e6e6e6} p.bbpTweet span.metadata span.author{line-height:19px} p.bbpTweet span.metadata span.author img{float:left;margin:0 7px 0 0px;width:38px;height:38px} p.bbpTweet a:hover{text-decoration:underline}p.bbpTweet span.timestamp{font-size:12px;display:block}&lt;/style&gt; &lt;div class='bbpBox89982230209904641'&gt;&lt;p class='bbpTweet'&gt;&quot;Module X is required, shall I install it?&quot; Well… yea…&lt;span class='timestamp'&gt;&lt;a title='Sun Jul 10 09:00:10 +0000 2011' href='http://twitter.com/ghickman/statuses/89982230209904641'&gt;less than a minute ago&lt;/a&gt; via &lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;/a&gt; &lt;a href='http://twitter.com/intent/favorite?tweet_id=89982230209904641'&gt;&lt;img src='http://si0.twimg.com/images/dev/cms/intents/icons/favorite.png' /&gt; Favorite&lt;/a&gt; &lt;a href='http://twitter.com/intent/retweet?tweet_id=89982230209904641'&gt;&lt;img src='http://si0.twimg.com/images/dev/cms/intents/icons/retweet.png' /&gt; Retweet&lt;/a&gt; &lt;a href='http://twitter.com/intent/tweet?in_reply_to=89982230209904641'&gt;&lt;img src='http://si0.twimg.com/images/dev/cms/intents/icons/reply.png' /&gt; Reply&lt;/a&gt;&lt;/span&gt;&lt;span class='metadata'&gt;&lt;span class='author'&gt;&lt;a href='http://twitter.com/ghickman'&gt;&lt;img src='http://a0.twimg.com/profile_images/1258522839/gravatar_normal.jpeg' /&gt;&lt;/a&gt;&lt;strong&gt;&lt;a href='http://twitter.com/ghickman'&gt;George Hickman&lt;/a&gt;&lt;/strong&gt;&lt;br/&gt;ghickman&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt; &lt;!-- end of tweet --&gt;&lt;/p&gt;
      
      &lt;p&gt;Thankfully it's easy enough to configure CPAN to follow the default options with the &lt;code&gt;prerequisites_policy&lt;/code&gt; option. Open the CPAN console by running &lt;code&gt;cpan&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If CPAN hasn't been configured before you'll be asked if you want it to &quot;configure as much as possible automatically&quot;, choose yes then follow the instructions below. However if you do want to go through them manually you'll be asked for a &lt;a href=&quot;http://www.cpan.org/SITES.html&quot;&gt;local CPAN mirror&lt;/a&gt; after the proxies section.&lt;/p&gt;
      
      &lt;p&gt;To configure type the following into the CPAN console:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;o conf prerequisites_policy follow&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;then&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;o conf commit&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;This sets the &lt;code&gt;prerequisites_policy&lt;/code&gt; to &lt;code&gt;follow&lt;/code&gt; the default option for each dependency. Thanks to Mithaldu on #gitalist for helping me out and saving hours of tedium.&lt;/p&gt;
      
      &lt;p&gt;Finally it's time for some installations! First up is &lt;a href=&quot;http://yaml.org&quot;&gt;YAML&lt;/a&gt;, which isn't required, but every install complains that it's not there because all the package descriptors are written in it. Installing packages from CPAN is as easy as:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;install YAML&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; CPAN might update itself at this point, which can take a significant amount of time depending on the power of your machine.&lt;/p&gt;
      
      &lt;p&gt;When that's done, it's time for Gitalist:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;install Gitalist&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Unfortunately some questions still come up, so it's not a completely unattended installation and did take quite a while for me (at least an hour). Default answers seem fine though.&lt;/p&gt;
      
      &lt;p&gt;Test the install by running &lt;code&gt;sudo gitalist_server.pl&lt;/code&gt; and having a look at &lt;code&gt;http://&amp;lt;server&amp;gt;:3000/&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;If you get an error about the location of the config then try the methods suggested &lt;a href=&quot;http://search.cpan.org/dist/Gitalist/lib/Gitalist.pm#FOR_CPAN_INSTALLS&quot;&gt;here&lt;/a&gt;. I found none of these worked for me so I grabbed the source from &lt;a href=&quot;https://github.com/broquaint/Gitalist&quot;&gt;Github&lt;/a&gt; and copied &lt;code&gt;gitalist.conf&lt;/code&gt; to &lt;code&gt;/usr/local/share/perl/5.10.x/Gitalist/&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;Later on we'll setup Gitalist with FastCGI, at which point you'll need Perl's &lt;code&gt;FCGI::ProcManager&lt;/code&gt; installed as it's the default &quot;Process Manager&quot; for the Gitalist FastCGI script:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;install FCGI::ProcManager&lt;/code&gt;&lt;/p&gt;
      
      &lt;h3&gt;Combining with Gitolite&lt;/h3&gt;
      
      &lt;p&gt;Combining Gitolite and Gitalist is as &quot;simple&quot; as pointing Gitalist at Gitolite's repository directory. Gitolite is running under the &lt;code&gt;git&lt;/code&gt; user and stores the repositories under &lt;code&gt;/home/git/repositories/&lt;/code&gt; which won't be accessible to you under another user. The easiest way around this is to run the &lt;code&gt;gitalist_server.pl&lt;/code&gt; command as the git user like so:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo -u git gitalist_server.pl --repo_dir /home/git/repositories/&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Of course you don't want to be stuck with a command running in the terminal all the time, or having to suffix it with &lt;code&gt;&amp;amp;&lt;/code&gt; just to have it run in the background so we'll setup &lt;a href=&quot;http://supervisord.org/&quot;&gt;Supervisor&lt;/a&gt; to handle all of that for us.&lt;/p&gt;
      
      &lt;h4&gt;Supervisor&lt;/h4&gt;
      
      &lt;p&gt;Supervisor looks after a process and can be configured to perform useful duties like autorestarting and running your process under a different user, both of which we're going to take advantage of. Thankfully supervisor can be installed with ease, like so:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo aptitude install supervisor&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Next you'll need a config file for Gitalist:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo vim /etc/supervisor/conf.d/gitalist.conf&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;Paste in the following - setting the path to your gitalist_server.pl to the appropriate place if it's not in the default location.&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                              &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;[program:gitalist]&lt;/span&gt;&lt;span class=line id=LC2&gt;command=/usr/local/bin/gitalist_fastcgi.pl --listen /var/run/gitalist/gitalist.sock --nproc 2 --pidfile /var/run/gitalist/gitalist.pid&lt;/span&gt;&lt;span class=line id=LC3&gt;user=git&lt;/span&gt;&lt;span class=line id=LC4&gt;autostart=true&lt;/span&gt;&lt;span class=line id=LC5&gt;autorestart=true&lt;/span&gt;&lt;span class=line id=LC6&gt;redirect_stderr=true&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/1084154/a600ba4b8b76c4e238513debfe72227d94434442/supervisor&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1084154#file_supervisor&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;supervisor&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1084154&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                    &lt;/div&gt;
      
      
      &lt;p&gt;I've put the socket and pid files in &lt;code&gt;/var/run/&lt;/code&gt; since Gitalist is installed via CPAN into and &lt;a href=&quot;#gitalist-install-dir&quot;&gt;doesn't really&lt;/a&gt; have an install directory as such so that's the next logical place. However you'll need to create the gitalist directory there and &lt;code&gt;chown&lt;/code&gt; it to your &lt;code&gt;git&lt;/code&gt; user so it can be written to by the FastCGI script (which is now running under the &lt;code&gt;git&lt;/code&gt; user). The &lt;code&gt;--nproc&lt;/code&gt; switch tells the script how many processes to run, like Nginx's workers directive. To see all the options run &lt;code&gt;/usr/local/bin/gitalist_fastcgi.pl --help&lt;/code&gt; in your terminal.&lt;/p&gt;
      
      &lt;p&gt;Open up Supervisor's nifty console with &lt;code&gt;sudo supervisorctl&lt;/code&gt; and tell it to &lt;code&gt;update&lt;/code&gt; so that it uses your Gitalist config (you'll need to do this after any updates to a configuration file). &lt;code&gt;status&lt;/code&gt; will show you a list programs you've setup which you can &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;restart&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; (for program output, with &lt;code&gt;-f&lt;/code&gt; for continuous output). The gitatlist server should now be running under Supervisor, check with the &lt;code&gt;tail gitalist&lt;/code&gt; to make sure there are no errors in the output.&lt;/p&gt;
      
      &lt;h4&gt;Gitalist Config&lt;/h4&gt;
      
      &lt;p&gt;Since we're using FastCGI to pass requests from Nginx through to Gitalist we'll use the Gitalist config file (you can't pass Gitalist configuration values to the FastCGI script). Open it up in your favourite editor:&lt;/p&gt;
      
      &lt;p&gt;&lt;code&gt;sudo vim /usr/local/share/perl/5.10.1/Gitalist/gitalist.conf&lt;/code&gt;&lt;/p&gt;
      
      &lt;p&gt;and set the &lt;code&gt;repo_dir&lt;/code&gt; option to &lt;code&gt;/home/git/repositories/&lt;/code&gt;:&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;name Gitalist&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;lt;Model::CollectionOfRepos&amp;gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#git /path/to/git&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# Configure this to where your repositories are.&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repo_dir /home/git/repositories/&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;lt;/Model::CollectionOfRepos&amp;gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;sitename &amp;quot;Gitalist&amp;quot;&lt;/span&gt;&lt;span class=line id=LC10&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;lt;paging&amp;gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;log = 20&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;summary = 17&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;lt;/paging&amp;gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;# Support gitweb patches action.&lt;/span&gt;&lt;span class=line id=LC17&gt;&amp;lt;patches&amp;gt;&lt;/span&gt;&lt;span class=line id=LC18&gt;&amp;nbsp;&amp;nbsp;max = 16&lt;/span&gt;&lt;span class=line id=LC19&gt;&amp;lt;/patches&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/1084154/bf2c8661deb4fe844d6bdacb3b71b70e09bb379e/gitalist.conf&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1084154#file_gitalist.conf&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;gitalist.conf&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1084154&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                            &lt;/div&gt;
      
      
      &lt;h4&gt;Nginx&lt;/h4&gt;
      
      &lt;p&gt;Create yourself a virtual host in nginx's sites-available directory and add the following, changing the server name to something suitable:&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;server {&lt;/span&gt;&lt;span class=line id=LC2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;server_name www.example.com;&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rewrite ^/(.*) http://git.example.com/$1 permanent;&lt;/span&gt;&lt;span class=line id=LC4&gt;}   &lt;/span&gt;&lt;span class=line id=LC5&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;server {&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;server_name example.com;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;access_log /var/log/gitalist/access.log combined;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;error_log /var/log/gitalist/error.log;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;location / {&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;include /etc/nginx/fastcgi_params;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fastcgi_pass unix:/var/run/gitalist/gitalist.sock;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;span class=line id=LC16&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/1084154/72d9a9c9a9df9ea5f99e77601ca6e1048a1ab4d5/vhost&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1084154#file_vhost&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;vhost&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1084154&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;            &lt;/div&gt;
      
      
      &lt;p&gt;I've setup the logs under &lt;code&gt;/var/log/gitalist/&lt;/code&gt; for the same reason as the socket and the pid files, again you'll have to create that directory but make it writable by &lt;code&gt;www-data&lt;/code&gt; so Nginx has access to it.&lt;/p&gt;
      
      &lt;p&gt;Link the virtual host into sites-enabled and test with &lt;code&gt;sudo nginx -t&lt;/code&gt; to check there are no errors, then reload nginx &lt;code&gt;sudo /etc/init.d/nginx reload&lt;/code&gt; (or use upstart) and your Gitalist should now be accessible on your domain!&lt;/p&gt;
      
      &lt;h2&gt;Notes&lt;/h2&gt;
      
      &lt;h4&gt;FastCGI vs. Reverse Proxying&lt;/h4&gt;
      
      &lt;p&gt;While getting FastCGI setup I toyed with Nginx as a reverse proxy to the one or more instances of the Catalyst development server, but had issues with hiding the port number and it felt a bit wrong to use a development server in production.&lt;/p&gt;
      
      &lt;h4 id=&quot;gitalist-install-dir&quot;&gt;Gitalist Install Directory&lt;/h4&gt;
      
      
      &lt;p&gt;Having installed Gitalist via CPAN it lives under &lt;code&gt;/usr/local/share/perl/5.10.1/Gitalist/&lt;/code&gt; which seems a bad place to store a socket file, a pid file or any logs which is why I chose to put them all under &lt;code&gt;/var/&lt;/code&gt;.&lt;/p&gt;
      
      &lt;h2&gt;Extra Reading&lt;/h2&gt;
      
      &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;http://wiki.catalystframework.org/wiki/adventcalendararticles/2008/02-catalyst_and_nginx&quot;&gt;Catalyst and Nginx (Catalyst Docs)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://search.cpan.org/~bobtfish/Catalyst-Runtime-5.80032/lib/Catalyst/Engine/FastCGI.pm#nginx&quot;&gt;Gitalist, FastCGI and Nginx (Catalyst Docs on CPAN)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://search.cpan.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Cookbook.pod#Standalone_server_mode&quot;&gt;Catalyst Standalone Server (Gitalist Docs on CPAN)&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    </content>
  </entry>
  <entry>
    <title>Adding Django Inline Forms with Javascript</title>
    <link href="http://ghickman.co.uk//2011/07/10/adding-django-inline-forms-with-javascript.html" />
    <updated>2011-07-10T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2011-07-10:/2011/07/10/adding-django-inline-forms-with-javascript.html</id>
    <content type="html">
      &lt;p&gt;Using Django formsets on a new section for a project at work I came across something I haven't considered before: adding new inline forms to a formset without reloading the page. Javascript was the obvious choice. Two pages required the functionality: one with six formsets, the other with one, which meant the solution needed to take into account formset prefixes. I found various solutions around the Internet, but all were outdated (lots of table based layouts!) or not generic enough (didn't deal with multiple formsets).&lt;/p&gt;
      &lt;p&gt;The idea behind the script is pretty simple: duplicate an existing form then update the form counter.&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add_inline_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prefix&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&gt;&lt;span class=line id=LC2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;#id_&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-TOTAL_FORMS&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&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&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;last_form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&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;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;:last&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;new_form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;last_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;last_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;RegExp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-\\\\\\\\d-&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;g&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&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&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nx&quot;&gt;new_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;input[type=&amp;quot;text&amp;quot;], textarea&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&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&gt;&lt;span class=line id=LC8&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;val&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&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nx&quot;&gt;new_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;insertAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;last_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;slideDown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c1&quot;&gt;// Update the total form count&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;#id_&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-TOTAL_FORMS&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&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&gt;&lt;span class=line id=LC14&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c1&quot;&gt;// re-initialise triggers&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC18&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC19&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC20&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/(?:inline\\-form) ([\\\\w\\-]*) (?:add|existing)/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC21&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.add-inline&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&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&gt;&lt;span class=line id=LC22&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.body&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;.inline-form&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC23&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;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;p&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC24&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&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&gt;&lt;span class=line id=LC25&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add_inline_form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;p&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&gt;&lt;span class=line id=LC26&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC27&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC28&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/1020463/8358e3b4a4d9e5916a857686332cf9d36078b2b6/add_inline.js&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1020463#file_add_inline.js&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;add_inline.js&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1020463&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                    &lt;/div&gt;
      
      
      &lt;p&gt;Which is setup to work on html that looks like this:&lt;/p&gt;
      
      &lt;p&gt;&lt;em&gt;Note: I'm using &lt;a href=&quot;https://github.com/pydanny/django-uni-form&quot;&gt;Django UniForm&lt;/a&gt; to output the form in &lt;code&gt;&amp;lt;div&amp;gt;'s&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                              &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{{ prefix_formset.management_form }}&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{{ prefix_formset.non_form_errors }}&lt;/span&gt;&lt;span class=line id=LC4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{% for form in prefix_formset.forms %}&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;inline-form prefix&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{{ form|as_uni_form }}&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{% endfor %}&lt;/span&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;new-inline&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;button&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;add-inline&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Add another form&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&lt;br/&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/1020463/a5269200d0d18ceb076ee970af8ab8eea0cf2ee5/forms.html&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1020463#file_forms.html&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;forms.html&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/1020463&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;            &lt;/div&gt;
      
      
      &lt;h3&gt;So How Does it Work?&lt;/h3&gt;
      
      &lt;p&gt;&lt;em&gt;Skip to &lt;a href=&quot;#gotchas&quot;&gt;Gotchas&lt;/a&gt; if you already understand my javascript&lt;/em&gt;&lt;/p&gt;
      
      &lt;p&gt;I start by looping my form class &lt;code&gt;add-inline&lt;/code&gt; (you can call it anything you like) and then running the regular expression from line 20 to find the form prefix, which is another class on the form. It expects the classes applied to the form in the order &lt;code&gt;add-inline &amp;lt;formset prefix&amp;gt; add/existing&lt;/code&gt;. The add/existing bit on the end isn't necessary but gives you an example of where to put any other classes that might exist on your form. If you don't want to use it, just remember to remove it from the regex! Inside the &lt;code&gt;add_inline_form&lt;/code&gt; function I'm grabbing the count from the hidden div and the last form with jQuery's &lt;code&gt;:last&lt;/code&gt; selector.&lt;/p&gt;
      
      &lt;p&gt;When new_form is set I'm using jQuery's &lt;a href=&quot;http://api.jquery.com/clone/&quot;&gt;clone&lt;/a&gt; method to take a copy of the last form and grab the raw html. The false passed into clone tells it to ignore any triggers and binds. The regex sets the correct count in the element ids. The next line clears the contents of every element in the new form since clone will pull this in with the elements. The new form is hidden then added after the last form with a nice little bit of &lt;a href=&quot;http://api.jquery.com/slideDown/&quot;&gt;slideDown&lt;/a&gt; candy for some UI goodness.&lt;/p&gt;
      
      &lt;p&gt;Finally increment the form count and return false so the form isn't submitted.&lt;/p&gt;
      
      &lt;h2 id=&quot;gotchas&quot;&gt;Gotchas&lt;/h2&gt;
      
      
      &lt;p&gt;So now you've got your nice little bit of javascript (if I don't say so myself) all setup to grab the last form in each formset, duplicate it and add it below the last form. However there are some caveats to this...&lt;/p&gt;
      
      &lt;p&gt;The script grabs the last form in the formset &lt;em&gt;every&lt;/em&gt; time so say you want the first form to differ from the rest (as I did) and implement this in the templates then you'll get the non-standard first form duplicated each time. The easiest way around this is to check the count and add an if to look for the first form.&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Nose Tests - no such option</title>
    <link href="http://ghickman.co.uk//2011/04/30/nosetests-no-such-option.html" />
    <updated>2011-04-30T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2011-04-30:/2011/04/30/nosetests-no-such-option.html</id>
    <content type="html">
      &lt;p&gt;Some time ago now I added proper command line options to &lt;a href=&quot;http://github.com/ghickman/tvrenamr&quot;&gt;Tv Renamr&lt;/a&gt;, followed shortly by a test suite with Python's &lt;a href=&quot;http://somethingaboutorange.com/mrl/projects/nose/1.0.0/&quot;&gt;Nose&lt;/a&gt;. Along the way I ran into a bug that has frustrated me for a long long time, until today when I finally found a work around - hooray, go me!&lt;/p&gt;
      
      &lt;p&gt;The bug is hardly a game stopper as it only affects the UI candy on my tests. Simply put, I couldn't use options with nose. Every time I did, an error was thrown saying no such option existed for nose while displaying the usage string for tvr:&lt;/p&gt;
      
      &lt;div&gt;
        &lt;img src=&quot;http://ghickman.s3.amazonaws.com/posts/2011-04-30-nosetest-no-such-option/screenshot.png&quot; width=&quot;700&quot;&gt;
      &lt;/div&gt;
      &lt;p&gt;This initially prompted me to split the front end script's options into a &lt;a href=&quot;https://github.com/ghickman/tvrenamr/commit/b77e16d97f7712de38625381e194d43e090a3fde&quot;&gt;separate&lt;/a&gt; file which didn't solve the issue, but did wonders for cleaning up the codebase.&lt;/p&gt;
      
      &lt;p&gt;This seems to have affected at least &lt;a href=&quot;http://ionelmc.wordpress.com/2008/04/24/setuptools-nosetests-oddness/&quot;&gt;one&lt;/a&gt; other person, whose post finally gave me the lightbulb today. &lt;a href=&quot;http://ionelmc.wordpress.com/&quot;&gt;Ionel&lt;/a&gt; mentions in his post &quot;Luckily, setuptools has aliases for commands and instead of&quot; and a snippet of a config file. It's only taken me a couple of years (I've tried to fix this at least 3 times now and always drawn blanks sadly) to realise that he was using a config file. A quick google for the appropriate section in the &lt;a href=&quot;http://somethingaboutorange.com/mrl/projects/nose/1.0.0/man.html#configuration&quot;&gt;nose docs&lt;/a&gt; turned up enough information to construct a useful rc file:&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;[nosetests]&lt;/span&gt;&lt;span class=line id=LC2&gt;with-spec=1&lt;/span&gt;&lt;span class=line id=LC3&gt;spec-color=1&lt;/span&gt;&lt;span class=line id=LC4&gt;with-growl=1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/949702/00816eda5cdb9c9f348915e30a95b2b3f28145a8/.noserc&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/949702#file_.noserc&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;.noserc&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/949702&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;            &lt;/div&gt;
      
      
      &lt;p&gt;And so I finally have my lovely coloured output, with &lt;a href=&quot;https://bitbucket.org/crankycoder/nosegrowl&quot;&gt;Growl&lt;/a&gt; integration, back. This is shaping up to be quite the productive weekend.&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Using Passenger with RVM and Sinatra</title>
    <link href="http://ghickman.co.uk//2011/04/04/passenger-with-rvm-and-sinatra.html" />
    <updated>2011-04-04T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2011-04-04:/2011/04/04/passenger-with-rvm-and-sinatra.html</id>
    <content type="html">
      &lt;p&gt;After making the move to &lt;a href=&quot;http://linode.com&quot;&gt;Linode&lt;/a&gt; (finally!) I had some issues with getting the contact pages on this site and &lt;a href=&quot;http://Penderry.com&quot;&gt;Penderry&lt;/a&gt; up and running. RVM was throwing an error about the sinatra gem missing. A quick scan of the error message and it was obvious that Passenger wasn't using my gemsets.&lt;/p&gt;
      
      &lt;p&gt;A bit of googling turned up this little snippet which, when placed in &lt;code&gt;app/config/&lt;/code&gt;, will tell RVM to use the gemset associated with the folder.&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;MY_RUBY_HOME&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;MY_RUBY_HOME&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;rvm&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;rvm_path&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&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;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;no&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;MY_RUBY_HOME&amp;#39;&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&gt;&lt;span class=line id=LC4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;rvm_lib_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rvm_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;lib&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unshift&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rvm_lib_path&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;rvm&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;no&quot;&gt;RVM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_from_path!&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;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&gt;&lt;span class=line id=LC8&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LoadError&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c1&quot;&gt;# RVM is unavailable at this point.&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;RVM ruby lib is currently unavailable.&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/900934/2f78a2c0e9e8f2f61531278b50166a9a1616b753/config/setup_load_paths.rb&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/900934#file_config/setup_load_paths.rb&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;config/setup_load_paths.rb&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/900934&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;            &lt;/div&gt;
    </content>
  </entry>
  <entry>
    <title>Ecohandle Shopping Bag</title>
    <link href="http://ghickman.co.uk//2011/01/08/ecohandle-shopping-bag.html" />
    <updated>2011-01-08T00:00:00+00:00</updated>
    <id>tag:ghickman.co.uk,2011-01-08:/2011/01/08/ecohandle-shopping-bag.html</id>
    <content type="html">
      &lt;div class=&quot;right photo&quot;&gt;
          &lt;img src=&quot;https://s3-eu-west-1.amazonaws.com/ghickman/ecohandle.jpg&quot; width=&quot;300&quot; title=&quot;Ecohandle&quot; alt=&quot;Ecohandle Shopping Bag&quot;&gt;
      &lt;/div&gt;
      
      
      &lt;p&gt;This year's Christmas Haul brought me an interesting little gem: The Ecohandle Shopping Bag. I got round to giving it a bit of a go today when I did a veg shop and thought doing a review on it would be fun.&lt;/p&gt;
      
      &lt;p&gt;So, first things first - what is it?&lt;/p&gt;
      
      &lt;p&gt;It's a shopping bag, duh. The bonus here though is that the bag part compacts down into the handle for when you're going to the shop. Nice and neat. If you feel like a real glutton for punishment on your forearms (I'll get to that properly in a minute) you can add extra bags. There are two slots with retractable clips that you can put the bags into, assuming you can carry them of course. I managed to get at least 5 kg into the Ecohandle bag alone without pushing it's limits! Getting it home was the bigger issue issue as I had to keep swapping hands when my grip muscles died.&lt;/p&gt;
      &lt;h2&gt;The Good&lt;/h2&gt;
      
      &lt;p&gt;You're saving bags...thus, Puppies.&lt;/p&gt;
      
      &lt;p&gt;The bag is really quite strong. I was worried that packing it full might have put too much strain on it, but it held up surprisingly well.&lt;/p&gt;
      
      &lt;h2&gt;The Bad&lt;/h2&gt;
      
      &lt;p&gt;The embossed name. When holding it in my left hand I found the edge of the embossed text rubbed against my finger tips in such a small way that it left them raw within a couple of minutes of use. It's certainly not a deal breaker, but smoother letters would be appreciated.&lt;/p&gt;
      
      &lt;h2&gt;The Fence&lt;/h2&gt;
      
      &lt;p&gt;It's a handle. Whereas you would normally have your bags cutting a nice line across your fingers - pulling directly down on your arm, you've got to actually grip the Ecohandle. I ended up swapping hands every few minutes and cursing my decision to put 5Kg+ of shopping in it. Good workout though (thus why it's on The Fence&amp;copy;).&lt;/p&gt;
      
      &lt;h2&gt;TL;DR&lt;/h2&gt;
      
      &lt;p&gt;It's a reusable shopping bag that packs down into it's own handle. You can attach other shopping bags and it'll give you a great workout on your grip muscles.&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Creating a Contact Page for Jekyll with Sinatra</title>
    <link href="http://ghickman.co.uk//2010/09/26/creating-a-contact-page-for-jekyll-with-sinatra.html" />
    <updated>2010-09-26T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2010-09-26:/2010/09/26/creating-a-contact-page-for-jekyll-with-sinatra.html</id>
    <content type="html">
      &lt;div class=&quot;right photo&quot;&gt;
          &lt;img src=&quot;https://s3-eu-west-1.amazonaws.com/ghickman/jekyll.jpg&quot; width=&quot;300&quot; height=&quot;169&quot; title=&quot;Jekyll&quot; alt=&quot;James Nesbitt in Jekyll&quot;&gt;
          &lt;p class=&quot;photo&quot;&gt;
              &lt;a href=&quot;http://thetvdb.com/?tab=artistbanners&amp;amp;id=513&quot;&gt;Freneticvirus&lt;/a&gt;
              &lt;img class=&quot;cc&quot; src=&quot;/images/cc.png&quot; width=&quot;16&quot; height=&quot;16&quot; title=&quot;Creative Commons Icon&quot; alt=&quot;CC&quot;&gt;
          &lt;/p&gt;
      &lt;/div&gt;
      
      
      &lt;p&gt;Jekyll is a fantastic static site generator with a great little community of modifications around it and I've used it for my own &lt;a href=&quot;http://ghickman.co.uk&quot;&gt;blog&lt;/a&gt; and &lt;a href=&quot;http://penderry.com&quot;&gt;Penderry.com&lt;/a&gt;. However my biggest problem with it is the lack of a way to deal with a contact form. Of course, this really isn't Jekyll's fault as it's only built to create HTML pages.&lt;/p&gt;
      
      &lt;p&gt;Enter Sinatra stage left.&lt;/p&gt;
      
      &lt;p&gt;&lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt; is a rad little web framework, well a micro framework really - in fact it's so small the Hello World app is 5 lines long! It's also perfect for creating a contact form.&lt;/p&gt;
      
      &lt;p&gt;To combine the two I needed both of them to display the same layout since I didn't want to have to maintain two. The contact page needed the same layout as the portfolio page, so no sidebar. The easiest way to do this is to plug your Sinatra application into Jekyll's layout mocking up any Jekyll specific objects/variables you need to (like page). I did give using a header and footer includes a go but it broke validation, pah.&lt;/p&gt;
      &lt;p&gt;My test app is hosted on &lt;a href=&quot;http://github.com/ghickman/jekyll_contact&quot;&gt;Github&lt;/a&gt; for your viewing pleasure but I'll go through the important parts here too.&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                                              &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;nn&quot;&gt;!!!&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;span class=&quot;nt&quot;&gt;%html&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%head&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%title&lt;/span&gt; Jekyll&amp;#39;s Contact Form&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&amp;quot;http-equiv&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Content-type&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;text/html; charset=utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:rel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;shortcut icon&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/favicon.ico&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;image/x-icon&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;stylesheet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;text/css&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/stylesheets/master.css&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:media&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;screen&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%body&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%header&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%h1&lt;/span&gt; Jekyll&amp;#39;s Contact From brought to you by Sinatra&lt;/span&gt;&lt;span class=line id=LC13&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%nav&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%ul&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%li&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;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;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Home&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; Blog&lt;/span&gt;&lt;span class=line id=LC18&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%li&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC19&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;http://localhost:4567/contact&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Contact&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; Contact&lt;/span&gt;&lt;span class=line id=LC20&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC21&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%section&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC22&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC23&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%footer&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC24&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%div&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC25&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%section&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#jekyll&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC26&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Powered by &lt;/span&gt;&lt;span class=line id=LC27&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;http://github.com/richguk/jekyll&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Jekyll&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; Jekyll&lt;/span&gt;&lt;span class=line id=LC28&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%section&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#from&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC29&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A&lt;/span&gt;&lt;span class=line id=LC30&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;http://ghickman.co.uk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;GHickman Blog&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; GHickman&lt;/span&gt;&lt;span class=line id=LC31&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;project&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/463598/c7007e119fa8315e07d4be17f4839afe30edc240/default.haml&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598#file_default.haml&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;default.haml&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                    &lt;/div&gt;
      
      
      &lt;p&gt;Nothing special here, just a bog standard Jekyll layout (well almost, this one is in HAML as I use &lt;a href=&quot;http://github.com/richguk/jekyll&quot;&gt;RickGuk's Jekyll fork&lt;/a&gt;) with a HAML interpreter bolted on.&lt;/p&gt;
      
      &lt;p&gt;The contact page itself is an HTML(5) form that displays some extra bits if we find errors. The test app is done using some HTML 5 specific elements like the email input box but there's no big leaps from HTML 4.&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;nf&quot;&gt;#contact&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;post&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%fieldset&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nc&quot;&gt;.input&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; Name&lt;/span&gt;&lt;span class=line id=LC6&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;text&amp;quot;&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;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;error&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;}&lt;/span&gt;&lt;span class=line id=LC7&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nc&quot;&gt;.error&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC11&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nc&quot;&gt;.input&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; Email Address&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;email&amp;quot;&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;s2&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;error&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;}&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nc&quot;&gt;.error&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC17&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC18&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nc&quot;&gt;.input&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC19&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; Message&lt;/span&gt;&lt;span class=line id=LC20&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%textarea&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;message&amp;quot;&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;s2&quot;&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;error&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;}&lt;/span&gt;&lt;span class=line id=LC21&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC22&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nc&quot;&gt;.error&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC23&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC24&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC25&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nf&quot;&gt;#submit&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.input&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC26&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;nt&quot;&gt;%input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;submit&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Send&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/463598/72248e3fb77fccb92e2e8c4d16e6ddad78e597db/contact.haml&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598#file_contact.haml&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;contact.haml&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                            &lt;/div&gt;
      
      
      &lt;p&gt;The actual Sinatra application is nice and simple given that we're plugging it into a different layout.&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                      &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;sinatra&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pony&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;haml&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:haml&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;ss&quot;&gt;:format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:html5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:public&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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&gt;&lt;span class=line id=LC8&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:views&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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&gt;&lt;span class=line id=LC9&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&lt;span class=&quot;c1&quot;&gt;# Create the page class and give it a title of Contact for the layout&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Page&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC12&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC13&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Contact&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC14&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC15&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC16&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC17&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;contact&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC18&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c1&quot;&gt;# create the variables that the layout will expect&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC19&gt;&amp;nbsp;&amp;nbsp;&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;no&quot;&gt;Page&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&gt;&lt;span class=line id=LC20&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;haml&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:contact&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC21&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC22&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;c1&quot;&gt;# render the contact page using jekyll&amp;#39;s layout and with our mock jekyll vars&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC23&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;haml&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:contact&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&amp;#39;_layouts/default&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:locals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC24&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC25&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC26&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/contact&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC27&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;vi&quot;&gt;@errors&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&gt;&lt;span class=line id=LC28&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;contact&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC29&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC30&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC31&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/contact&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC32&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;vi&quot;&gt;@errors&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&gt;&lt;span class=line id=LC33&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&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;s1&quot;&gt;&amp;#39;No Anon allowed here.&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&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;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC34&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&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;s1&quot;&gt;&amp;#39;Sinatra needs an email to send your message from!&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;:email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&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;:email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC35&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:message&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;s1&quot;&gt;&amp;#39;No message?! Sounds like heavy breathing on the phone to me.&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;:message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&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;:message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC36&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=line id=LC37&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@errors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty?&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC38&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;no&quot;&gt;Pony&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;george@ghickman.co.uk&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;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;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:subject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Contact Message&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:body&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;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;params&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:message&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;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC39&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;redirect&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://localhost:4000/index.html&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC40&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC41&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;n&quot;&gt;contact&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC42&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC43&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/463598/13a675bab89cd0789d535360f1d57e62a2e1ac18/_contact.rb&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598#file__contact.rb&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;_contact.rb&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                                            &lt;/div&gt;
      
      
      &lt;p&gt;I've started off by setting the views path to Jekyll's source directory so Sinatra knows where to find the contact page and since you can specify a subdirectory the site layout can easily be found later.&lt;/p&gt;
      
      &lt;p&gt;The &lt;code&gt;Page&lt;/code&gt; class is there to emulate the page class that Jekyll uses. Here I've created a title method as my site (what this was originally created for) checks to see what the title of the page is before rendering the sidebar. You can use this method to mock up any of the Jekyll specific objects you wanted, i.e. &lt;code&gt;site&lt;/code&gt;.&lt;/p&gt;
      
      &lt;p&gt;The &lt;code&gt;contact&lt;/code&gt; method is where the &lt;em&gt;magic&lt;/em&gt; really happens. Here we're rending the contact page with Jekyll's layout and passing it our mocked up variables so that Sinatra doesn't freak out when the layout asks for them.&lt;/p&gt;
      
      &lt;p&gt;The script is finished off by the get and post methods that both call contact when they want to render a page (making my code nice and DRY). Voila! Jekyll has a contact page!&lt;/p&gt;
      
      &lt;p&gt;The last thing to note in the script is the redirect on a successful submission. Since your Sinatra is running on a different port to Jekyll (likely the default 4567) you'll want to redirect back to your Jekyll setup during development. In production this can be changed to &lt;code&gt;redirect '/index.html'&lt;/code&gt;.&lt;/p&gt;
      
      &lt;h3&gt;Setting it up in a Production Environment&lt;/h3&gt;
      
      &lt;p&gt;Setting this all up in production requires a bit more than Jekyll since you're running a ruby application in the background now. Luckily this is where &lt;a href=&quot;http://www.modrails.com/&quot;&gt;Phusion Passenger&lt;/a&gt; comes in. You'll need a rack file in your Jekyll root that looks like this:&lt;/p&gt;
      
      &lt;div class=&quot;gist&quot;&gt;                                              &lt;div class=&quot;gist-file&quot;&gt;          &lt;div class=&quot;gist-data gist-syntax&quot;&gt;                                                  &lt;div class=&quot;gist-highlight&quot;&gt;&lt;pre&gt;&lt;span class=line id=LC1&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;source/_contact&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC2&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC3&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC4&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:production&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC5&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC6&gt;&lt;span class=&quot;no&quot;&gt;FileUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir_p&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;log&amp;#39;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&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;exists?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;log&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC7&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;log/sinatra.log&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC8&gt;&lt;span class=&quot;vg&quot;&gt;$stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC9&gt;&lt;span class=&quot;vg&quot;&gt;$stderr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=line id=LC10&gt;&lt;br/&gt;&lt;/span&gt;&lt;span class=line id=LC11&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Sinatra&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Application&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;                      &lt;/div&gt;          &lt;div class=&quot;gist-meta&quot;&gt;            &lt;a href=&quot;https://gist.github.com/raw/463598/5a6806d949bf55474729991f1a8918e657667c5d/config.ru&quot; style=&quot;float:right;&quot;&gt;view raw&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598#file_config.ru&quot; style=&quot;float:right;margin-right:10px;color:#666&quot;&gt;config.ru&lt;/a&gt;            &lt;a href=&quot;https://gist.github.com/463598&quot;&gt;This Gist&lt;/a&gt; brought to you by &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;.          &lt;/div&gt;        &lt;/div&gt;                                    &lt;/div&gt;
      
      
      &lt;p&gt;Don't forget to update the redirect path back from Sinatra to Jekyll, then you're good to go!&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Mumbai</title>
    <link href="http://ghickman.co.uk//2010/09/18/mumbai.html" />
    <updated>2010-09-18T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2010-09-18:/2010/09/18/mumbai.html</id>
    <content type="html">
      &lt;p&gt;Coming into Mumbai's domestic airport we got to see a fair number of shanty town looking dwellings, contrasting what I'd read about the metropolitan downtown area. We booked a prepay taxi and headed outside to the taxi rank where, to my surprise and child like joy, they had incredibly stereotypical Indian taxis that look like they are from the 50's. They are called Black and Yellows (for their paint job...), have bench seats, usually no wing mirrors and are dented to hell. We took a ride in one of the mini van type ones to our hotel in Downtown. Alas, this was an hour and a half away... Sweaty!&lt;/p&gt;
      &lt;h2&gt;MEAT and Other Delectables&lt;/h2&gt;
      
      &lt;p&gt;As previously mentioned Gujerat is predominately a vegetarian province and we'd miss meat, along with cheese and eggs at the school. Thus, as in Rajkot, we promptly pigged out on the heaviest meat/cheese/egg dishes we could find. Mumbai is very much like Bangkok in some ways, there are lots of market stalls down the main Bazaar road in Colaba (the district we were staying in), street vendors are everywhere and my favourite - juice bars. Freshly squeezed juice practically on tap. Nom nom nom. On our last day we picked up a selection of spices to take home from a local supermarket. Damn it's cheap to buy spices in India. We bought about 4 or 5 kilos split between a variety of spices and the bill was barely £5. Win! Garam Masala seems to be the thing to get, it's a mix of a selection of spices that you can just chuck in with some meat and you've got a full curry.&lt;/p&gt;
      
      &lt;h2&gt;Hotel Bentleys&lt;/h2&gt;
      
      &lt;p&gt;I couldn't talk about our time in Mumbai without mentioning our awesome hotel. Hidden away down a side street in central Colaba, Hotel Bentleys is a few minutes away from the Gateway to India and completely secluded from the hubbub of the main road. It even had an old school lift. So. Much. Fun. We were the first people to use our room since it had been refurbished which meant it was possibly the cleanest room we'd stayed in all trip. The only downside was the pretty solid 'mattresses' we had to sleep on, but there was free breakfast so who can complain?!&lt;/p&gt;
      
      &lt;h2&gt;Bon Voyage&lt;/h2&gt;
      
      &lt;p&gt;Aaaaaaaaand home time! An interesting journey to the airport... Our 'booked' taxi involved the hotel front-gate-man getting us a taxi on the day. The driver turned out to be pretty drunk with reaction speeds to match which wasn't so bad until he clipped a guy knocking his phone out of his hand. Rather than stop he just gave the guy an angry look, shouted and carried on driving. He was a very angry man. So very very angry. Once again the airport was rammed with armed guards, even a mounted sentry post on the way in! Then it was home time on our nine and a half hour flight home.&lt;/p&gt;
      
      &lt;p&gt;BYE INDIA!!!&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Back to School</title>
    <link href="http://ghickman.co.uk//2010/09/17/back-to-school.html" />
    <updated>2010-09-17T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2010-09-17:/2010/09/17/back-to-school.html</id>
    <content type="html">
      &lt;p&gt;One of our main aims in India was to help out at a school we had vague ties to. The school had been variously described to us as an orphanage (and is indeed for children who have not had the best start in life, but also for others) and a hostel. We had assumed, before arrival, that it was a small school with 200 girls attending where we could help with teaching English. It actually turns out the 'school' is more of a community. Based on 5000 acres of land it is a charity run organisation with a large school, hostel for the children, various (large scale) cooking facilities, a water treatment plant, enough farm land to be self sufficient for 9 months of the year, a college/university, an old peoples home, a blind school, a general farm and more. Our initial figure of 200 girls is about right, however no-one thought to mention the other 2000 male students living here! Almost all staff live on-site and their are a good number of administrators and other personnel for things like building, farming, cooking, etc.&lt;/p&gt;
      &lt;p&gt;This post is going to differ a bit from my previous India ones in that I'm going to pick on various parts of our stay and talk about them. Two weeks here has left me with far too much to talk about!&lt;/p&gt;
      
      &lt;h2&gt;Meal Times&lt;/h2&gt;
      
      &lt;p&gt;Being guests we ate in a different kitchen to either the elderly/blind or the main school body and mostly ate by ourselves - sometimes being joined. We were served by the same kitchen as the elderly/blind school just in a different room and I don't think either of us have been so voraciously offered food in our lives. At first I felt a bit beseeched having to defend my platter from being filled every time I looked away but slowly learnt the game of covering my food while pushing the cook and his serving away. It's a hard life being a guest in Gujerat! Water had to be filtered to make it drinkable, for us at least, and most people drink far more butter milk than water anyway. I gave butter milk a go, it was not a great experience. Poppy was a little sick in her mouth when she tried it. She did not try it again. I gave curd a go which was like plain/greek yoghurt when mixed up. I had some sort of brown powder added to it (possibly cinnamon) that added a sweet edge. Unfortunately this was probably the source of my day of bad bowels (rusty water much?!). After expressing a like for potato, a few days in, the cook jumped at the opportunity and every meal time onward had some sort of potato (aloo in Hindi) in one of the dishes - yes, even breakfast.&lt;/p&gt;
      
      &lt;p&gt;It would be prudent to note at this point that every meal consists of 3+ dishes essentially, called a Gujerati Thali - it's like a set meal. Your main plate is a platter with edges and on it you have 2 or 3 bowls and a cup. All metal of course. You are served with a variety of dishes. We got a lot of lentil based dishes that I loved and generally there was theme to the meal. Dal (a kind of broth made from lentils) was served with almost every meal and I loved it at first but went off it after having it for two meals a day for a week. We discovered that chapatis and rotis are basically the same thing - having an english speaking chaperone was great as I asked about every dish we got served and learnt the rest of the dish names that I hadn't worked out. My favourite was by far the mash potato with chopped potato bits in it (me likey aloo) and butter. Fresh butter is the best thing. Ever. They make it daily (from what I could tell) and use unthinkable amounts of it in everything. I was in heaven. It's not salted and is almost like whipped cream. Pancakes would have gone very, &lt;em&gt;very&lt;/em&gt; well with the butter. Nom nom nom.&lt;/p&gt;
      
      &lt;h2&gt;[Farm] Animals&lt;/h2&gt;
      
      &lt;p&gt;Like everywhere else animals roamed freely at the school. The main difference is that the cows are farmed. Gujerat is both a dry and vegetarian state in honour of it being Ghandi's birth place. There are of course exceptions to this, mostly meat being available (chicken and mutton) primarily for tourists. So we were a little surprised to see cows being farmed when we arrived. It was later explained to use that while cows are a sacred animal they can be farmed for their produce. The cows at the school are the biggest healthiest cows I've ever seen (all adult cows were a match, if not bigger, than prime bulls I've seen in the UK...). On average they produce 70 litres of milk per day over two sittings (explains why dairy products feature so heavily in the diet there!) and the herd is roughly 200 strong. Any cow that can grow horns has got an epic set of people stabbers on their head and as with all the cows we'd seen - they go where they please. We had one cow in the field outside our room for a few days who would randomly wander through a flower bed to get there before stuffing his face from dawn til dusk.&lt;/p&gt;
      
      &lt;p&gt;A lot of equipment used to farm is mechanical but it blends seamlessly in with the Ox drawn carts and ploughs. Having never seen oxen before we first thought they were just humungous cows with even better horns (these look like your stereotypical devil/fully grown hellboy horns). Got a little schooling on that....get it schooling, at a school... #terriblejoke&lt;/p&gt;
      
      &lt;p&gt;Dogs randomly potter around the place but are some of the skinniest we'd seen. It turned out that residents were told not to feed the dogs in an attempt to keep them away but the elderly, doing as they pleased (some things never change), seemed to break this almost constantly - giving them a permanent pooch presence.&lt;/p&gt;
      
      &lt;h2&gt;Teaching Techniques&lt;/h2&gt;
      
      &lt;p&gt;I am no teacher. This is clearly evident if you have ever met me. I am happy to wander off on random tangents of thought and end up with cotton mouth 5 minutes into any public speaking (there is never any water around). So I do not, by any means, presume to pass judgement on the teaching techniques of the school. However I found them quite interesting. Theory and textbooks rule. Everywhere I went textbooks are being used by staff and students alike and whenever I tried to lend my expertise (only at the college/university - software engineering doesn't have much application for 3-16 year olds) the question that constantly popped up is: What book should I consult about this? This is not my way of doing things. I am a very practical person - something my academic career can attest to and books are by no means my preferred method of learning. In my opinion they are for stories, which has probably never helped me with textbooks! So I found this culture of text books hard to understand. Of course I don't think it's wrong, just very alien! I certainly know of a number of people who would flourish in the environment.&lt;/p&gt;
      
      &lt;h2&gt;Leaving&lt;/h2&gt;
      
      &lt;p&gt;We were fortunate to be driven up to Rajkot when it came time to leave. Which was no doubt for the best, it probably would have taken us the whole day if we'd tried to do it ourselves. We said goodbye to everyone, which was no quick thing and grabbed pictures of everything we could think of (still managed to forget the room of course) and headed off for the night in Rajkot before jetting over to Mumbai.&lt;/p&gt;
      
      &lt;p&gt;To anyone reading this from the Institute - thank you so very much for a wonderful two weeks. I hope the lab is still working!&lt;/p&gt;
    </content>
  </entry>
  <entry>
    <title>Diu - Home of Sand, Sea and Forts</title>
    <link href="http://ghickman.co.uk//2010/09/16/diu.html" />
    <updated>2010-09-16T00:00:00+01:00</updated>
    <id>tag:ghickman.co.uk,2010-09-16:/2010/09/16/diu.html</id>
    <content type="html">
      &lt;p&gt;Diu is a little island off the south coast of Gujarat that was under Portuguese control until some point (I'm vague on any actual sort of date or time frame....I'm no history buff). The general architecture is a weird mix of Indian construction with the loud colours that you see in a lot of Portuguese culture, made even more obvious when you see the grey pure concrete buildings being constructed next to the ADHD coloured buildings. Connected to the mainland by a bridge the whole island is pretty tiny at 14km in length. Apparently it's a big holiday destination in the high season but this is &lt;em&gt;MONSOON&lt;/em&gt; so it randomly rained like rain is going out of fashion and everything was a fraction of the price (our hotel was 500 rupees a night instead of 1500).&lt;/p&gt;
      &lt;h2&gt;Highway to HELL&lt;/h2&gt;
      
      &lt;p&gt;Allow me, if you will, to take you on a literary journey. Close your eyes and imagine the worst smell you can think of, throw in a heavy over tone of body odour, if this makes you gag/throw up in your mouth a little then you're on the right track. Now infuse that very smell into a cold, ever so slightly, damp mattress and put a blanket over the top. The blanket is dry but has the same smell and is covered in bits of general muck that stick to you the minute you touch it along with it's fluff. Now take a 10 hour night bus on that very mattress and blanket and try very hard not to think or talk about your situation. It will make you sick.&lt;/p&gt;
      
      &lt;p&gt;This was our bus journey from Ahmedabad to Diu. We covered ourselves in our sleeping bag liners. It was terrible. I'm still trying to repress the memory.&lt;/p&gt;
      
      &lt;h2&gt;La Dolce Vita Music Garden&lt;/h2&gt;
      
      &lt;p&gt;The first night in Diu we went for something budget-as-hell that the book said was cheap but okish. We were craving a shower/bleach after the bus so didn't look too closely when showed the room and ended up in Jay Shankar. While perusing the balcony [read: bored] I noticed a little restaurant over the road call La Dolce Vita Music Garden. It looked nice enough as being the lazy person I am I made sure we ate their first rather than trying to find somewhere else. Best decision of the trip.&lt;/p&gt;
      
      &lt;p&gt;La Dolce Vita is a collection of tables under a thatched reed roof attached to the owners' house. They have a fairly large selection of dishes on the menu that they cook in their own kitchen and were always happy to see us - probably because we were their only customers 99% of the time. They even helped us to learn a lot of the dish names, which became invaluable in other restaurants as up until that point I'd mostly picked dishes based on either randomly pointing at one or whichever had the coolest name. This had mixed results... I found a dish there, that was much like the first one I had in Delhi, called Aloo Gobi which means Potato Cauliflower. It didn't have much sauce but tasted great and mixed with one of their mammoth portions of rice formed more of a feast than a single meal. Nom nom nom!&lt;/p&gt;
      
      &lt;p&gt;My favourite part of La Dolce Vita is how the dishes always vary from day to day. This can be seen more explicitly in the lassis (like a milkshake but with yoghurt) and milkshakes that were practically a different drink every time we had one and just adds to the homely vibe of the place.&lt;/p&gt;
      
      &lt;h2&gt;Fort Boyard and Fort Bill&lt;/h2&gt;
      
      &lt;p&gt;In various places around Diu I've seen pictures of the sea fort in the main port bay. I promptly named it Fort Bouyard in my head and would strongly recommend the Diu authorities follow suit. You can't visit the actual fort so the only way to see it is to take a fishing boat around the outside and since the weather took a turn for the worse it got sacked off. Of course there are totally tigers in there for people who don't make it out of the cage fast enough, this I am sure of.&lt;/p&gt;
      
      &lt;p&gt;We did go and see the main fort regardless of the rain. It's one bad ass fort! Built into the bedrock of the peninsula, surrounded on three sides by sea and a double moat on the final side it seems pretty impenetrable. Somehow the Portuguese were ousted by the Indian army though. Fail. The two moats are backed by walls with with three bastions on the outer wall and four on the inner, each bastion packed to bursting with cannons...how the Portuguese lost is beyond me. L for love! The fort is still in use as the local prison and for some government offices since these existed back when it was built so it does make sense, but it does mean some parts are off limits which is a shame.&lt;/p&gt;
      
      &lt;p&gt;The first spectacle as you enter the fort proper is St George's Bastion which, apart from being named the best, overlooks the landing pier ready to bombard any marauding pirates. We saw another random bastion after this, St Luzia I think, which was more of the same, an armoury which seemed to have some rather more modern (post WWI) artillery pieces and a chapel before we got historied out (ADHD much?) and left.&lt;/p&gt;
      
      &lt;p&gt;We saw some restorative work had been done to walls here and there and some workmen were fixing up a wall but it's nothing like you'd see in England at say an English Heritage or National Trust site. The new brick work seems far less long lasting than the 500 year old stuff they are removing, which is a shame. There's a general feel of disrepair about the place which isn't helped by the large patches (old buildings that have since fallen down possibly) of overgrowth. Had English Heritage got their hands on it we could have at least had an overpriced coffee at the end.&lt;/p&gt;
      
      &lt;p&gt;Overall the fort can be summed up as RAD&lt;sup&gt;Sick&lt;/sup&gt; especially if you're into history but I'd forgotten most of the broken english translation of it's history by the first bastion. The slippery steep slope (stairs anyone?) up to each bastion was enough to pique my Fear of Heights into rearing it's ugly head. Flip flops were a bad choice.&lt;/p&gt;
      
      &lt;p&gt;I couldn't help but think that had the place been done up it would have been amazing for paintballing or airsofting on an epic scale. Pirates attack the fort anyone?!&lt;/p&gt;
      
      &lt;h2&gt;Reservoir Dogs&lt;/h2&gt;
      
      &lt;p&gt;Towards the end of our Diu tour we were, once again, visiting our favourite restaurant when the second group of people we'd ever seen there appeared. Six shifty looking indian fellas came in and perused the menu before sitting down. I didn't pay them much attention after the initial shock at seeing someone other than the owners in &lt;em&gt;my&lt;/em&gt; restaurant. After we'd finished yet another scrumptious gut busting meal I popped out my iPhone to look up a route from the restaurant to the local fort when one of the shifty gentlemen appeared at my shoulder giving me a pretty good fright. This put me on edge a bit until I later found out they had all been watching us the whole time and seemed especially interested in our wallets when it came time to pay up. Worse still the wife had stayed inside and when one of them approached us to ask for, what we thought, was a photo of the group the husband had told Poppy to sit down almost the moment she stood up. I found most of this out as we were walking away and immediately felt uneasy, promptly topped off by one of the guys coming out of the restaurant to watch us walk down the road. He was still there when we went round the corner a few hundred metres away. With paranoia rising we walked back to the hotel at almost running pace and promptly hid in the room for the next few hours, leaving the fort for another day.&lt;/p&gt;
      
      &lt;p&gt;Looking back on the experience the group were probably not muggers/the mafia and simply really leery guys which would explain the wife staying inside and the husband barely talking to us after they arrived (he was too busy keeping an eye on them). The worst part of the whole thing is we'd both become very comfortable in Diu, with Poppy venturing out unaccompanied occasionally and me using various tech in public but we were a little on edge afterwards and it took us a couple of days to get comfortable again.&lt;/p&gt;
      
      &lt;h2&gt;Cheese It!&lt;/h2&gt;
      
      &lt;p&gt;A very early start (5.30am) saw us on the 7am (sorry 7.30am...) bus to Veraval which needed to be jump started and whose horn got stuck on after mass overuse so the driver had to disconnect it. Sitting down the front of the bus meant we got to ignore almost all the usual stares (the door was in the middle) - a nice change. Once in Veraval we went looking for the bus we'd been assured we could get to Visavadar, which turned out to actually be a bus to Junagh and then get a connection from there, an extra 96km. It's only 120km from Diu to Visavadar.&lt;/p&gt;
      
      &lt;p&gt;A hilariously roundabout negotiation for a rickshaw got us to the train station for 10 rupees saving us the trip in the pouring rain. We just about managed to purchase a ticket to Visavadar on a train that was leaving 3 hours later and headed for our platform. The bridge was really high and floored with tiles that were slick with rain, so so utterly dim cool with a giant bag and flip flops on. Even after being up close to 9 or 10 hours I still loved being on the train. Over half the stops had no visible buildings but people would be waiting around, sometimes to sell you things when you got off for a break or because it was a 'station'. At one stop there were monkeys outside, so being the ultimate tourist I leap from the train, camera in hand, and tried to get as close as possible to get a good picture. These monkeys were enjoying the food they were being given but apparently the white man getting closer than 3 feet is a faux pas....I got hissed and had teeth bared at me. It was rad. I could have totally taken that monkey....&lt;/p&gt;
    </content>
  </entry>
</feed>
