<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dr Nic &#187; Announcement</title>
	<atom:link href="http://drnicwilliams.com/category/announcement/feed/" rel="self" type="application/rss+xml" />
	<link>http://drnicwilliams.com</link>
	<description>Ruby makes Rails, Javascript makes Ajax, Dr Nic makes Magic</description>
	<lastBuildDate>Tue, 03 Aug 2010 23:44:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Coming to America</title>
		<link>http://drnicwilliams.com/2010/08/04/coming-to-america/</link>
		<comments>http://drnicwilliams.com/2010/08/04/coming-to-america/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 23:44:48 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Engine Yard]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=782</guid>
		<description><![CDATA[Have you ever looked at your biological watch and thought, &#8220;it looks like it&#8217;s time to change the world?&#8221; My biological time piece has a full set of inscriptions: go to university, chase girls, get a post-graduate qualification, catch a girl, get a professional job, marry the girl, change into contracting, change into consulting (and [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever looked at your biological watch and thought, &#8220;it looks like it&#8217;s time to change the world?&#8221;</p>
<p>My biological time piece has a full set of inscriptions: go to university, chase girls, get a post-graduate qualification, catch a girl, get a professional job, marry the girl, change into contracting, change into consulting (and ponder what the difference is), work overseas (and marvel at the differences), make a baby, change into training, move back to Australia, buy a home, start a consultancy (Mocra), make another baby, grow the consultancy, and &#8230;</p>
<p>Really, I&#8217;m not sure what comes next in the script of normal life. Retire in 30 years? Create more little open source projects? Just keep growing the consultancy? Until what?</p>
<p>A few weeks ago, John Dillon, the CEO of Engine Yard, drew some pictures on a whiteboard for me and asked, &#8220;Do you want to help change the world?&#8221; Sure, a classic Steve Jobs one-liner from the history books of Apple. I said, &#8220;Yes&#8221;.</p>
<p>On the 1st of September I will start work at <a href="http://maps.google.com/maps?q=500+3rd+Street,+San+Francisco">500 3rd Street, San Francisco</a> as <a href="http://www.engineyard.com/">Engine Yard<br />
</a>&#8217;s VP, Technology. Job description: <em>help web application developers win</em>. </p>
<p><a href="http://maps.google.com/maps?f=d&amp;source=s_d&amp;saddr=46+Douglas+St,+Milton+QLD+4064,+Australia&amp;daddr=500+3rd+Street,+San+Francisco&amp;hl=en&amp;geocode=&amp;mra=ls&amp;sll=37.780991,-122.39559&amp;sspn=0.009497,0.01929&amp;g=500+3rd+Street,+San+Francisco&amp;ie=UTF8&amp;z=3"><img src="http://img.skitch.com/20100803-ethi1qtq3e5ictbwx2b919nefp.png" alt="22000km to work" style="float: right"/></a></p>
<h2 id="the_daily_commute">The daily commute</h2>
<p>Google Maps suggests my daily commute to work will be 22,300km. Some of that will be heavy morning traffic, so at say 30km/hr, that is almost 750 hours. Each way.</p>
<p>So instead, my family will pack its bags and move overseas again. Though for the first time, we&#8217;re coming to America!</p>
<h2 id="how_to_move_your_family_to_america">How to move your family to America</h2>
<p>It hasn&#8217;t been all smooth sailing on the home front since I broached the idea with my wife. Personally, have you ever turned to your wife and said, &#8220;Honey, I think we are going to move to America!&#8221;</p>
<p>Try it at home for a laugh. Perhaps your wife will say something witty or clever like mine. Something like, &#8220;No.&#8221;</p>
<p>&#8220;No, baby, really. I have something important to do for a few years. It&#8217;s in America. San Francisco. Apparently it&#8217;s lovely!&#8221;</p>
<p>&#8220;Is the weather nice?&#8221; she might ask looking for any reason to want to leave beautiful, sunny Brisbane.</p>
<p>&#8220;No. I think it&#8217;s kind of cold there. And foggy. There was even a taxi with &#8216;Fog City Taxi&#8217; on its side. But there are wonderful schools and the people are fabulous and are from all over the world!&#8221;</p>
<p>&#8220;So our young kids won&#8217;t get an American accent?&#8221; she might ask pleadingly.</p>
<p>&#8220;Well, they won&#8217;t get all of the accents, no.&#8221;</p>
<p>&#8220;&#8230;&#8221;</p>
<p>&#8220;I love you!&#8221;</p>
<p>And so eventually your wife will say yes.</p>
<h2 id="how_do_we_get_to_win_as_web_developers">How do we get to win as web developers?</h2>
<p>Choose to use Rails. Improve Rails. Improve the ecosystem above/below/around Rails. Improve our daily lives. Expand the sweet spot of Rails to solve problems. </p>
<p>In the future, can we look back at the work we did, the fun we had, the problems we solved, the time we spent working, and feel that it was worth the effort? Will we remember when we first discovered Ruby and Rails and remember the joy?</p>
<p>This is a world-changing set of issues to care about. I&#8217;ve always cared about them before now, but never had resources or reach to work on them beyond my own little projects or cunningly worded, suggestive emails/tweets/chat with other open source developers.</p>
<p>Though from now onwards I will get to work with one of the greatest concentrations of Rails talent and one of the largest <a href="http://www.engineyard.com/open-source">open source programs</a> in the our community. I&#8217;m more than just a little bit excited. Imagine working with full-time contributors to Rails, JRuby and Rubinius as well as the dozens of developers, devops and more.</p>
<p>As Engine Yard continues to grow and win then its capacity to fund and resource more contributions will grow. And then we all win faster.</p>
<p>Can you imagine what else should be funded, promoted or prioritised? I have a dozen solid ideas but I would love suggestions.</p>
<h2 id="mocra">Mocra</h2>
<p>I will miss my guys at Mocra, a wonderful Rails consultancy with clients around the world whilst based out of Brisbane, Australia. I founded and ran Mocra for the last two wonderful years. It will be slightly annoying &#8211; I won&#8217;t get to take any credit for all the success the Mocra team will have in the years to come. </p>
<p>Definitely, if you need an awesome Rails team for your project, contact <a href="http://mocra.com/">Mocra</a>. If you need a personal introduction, let me know. I know some people there.</p>
<h2 id="san_francisco">San Francisco</h2>
<p>I am very excited to move to SF and to hang out on a regular basis all the people I have only been able to see at conferences.</p>
<p>I&#8217;d also love suggestions of where a family of four (including a 4yo and 2yo; oh, plus another one due in February) could live. I&#8217;ve briefly seen parts of SF and many of the surrounding towns in the bay area. Thanks to Randall, Tammer and Marcy for their turns as tour guides during my visit a few weeks ago.</p>
]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2010/08/04/coming-to-america/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Customized Google Forms</title>
		<link>http://drnicwilliams.com/2010/02/25/customized-google-forms/</link>
		<comments>http://drnicwilliams.com/2010/02/25/customized-google-forms/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 11:30:24 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=688</guid>
		<description><![CDATA[Google Forms are a great, free way to collect information from anyone, stored directly into a Google Spreadsheet, and then have Google notify you each time a form is submitted (optionally). The downside is that you can only use one of their pre-packaged themes. You can&#8217;t have your company logo and corporate &#8220;look&#8221;. Pooey to [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2009/03/30/closing-in-on-the-dream-one-click-to-deploy-rails-apps/' rel='bookmark' title='Permanent Link: Closing in on The Dream: &#8220;one-click-to-deploy Rails apps&#8221;'>Closing in on The Dream: &#8220;one-click-to-deploy Rails apps&#8221;</a> <small> Got a simple app you want to build? Allocate...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://img.skitch.com/20100225-rm11rdpj6qib6ukbwdi87ewd76.preview.jpg" alt="Google Form Customized" style="float: right; width: 200px"/></p>
<p>Google Forms are a great, free way to collect information from anyone, stored directly into a Google Spreadsheet, and then have Google notify you each time a form is submitted (optionally). The downside is that you can only use one of their pre-packaged themes. You can&#8217;t have your company logo and corporate &#8220;look&#8221;.</p>
<p>Pooey to Google, we say. So we wrote <a href="http://github.com/mocra/custom_google_forms">custom_google_forms</a>.</p>
<p>Want to truly customized Google Forms? Fork this repository, customize the CSS, DOM and images, and deploy to Heroku. You can then host/customize any number of Google Forms.</p>
<p>For example, here is an original <a href="http://spreadsheets.google.com/a/mocra.com/viewform?formkey=dFo0LXQyYmlEV2dXcVJ6WjRweW9vRnc6MA">bare Google Form</a> and here is a <a href="http://forms.mocra.com/railsdev">fully customized version</a>, including form validation and thank you page.</p>
<p>It&#8217;s fully a dynamic, thin layer on top of Google Forms. If you change your Google Form, your custom form application automatically changes.</p>
<h2 id="how_to_use_google_forms">How to use Google Forms?</h2>
<p>Perhaps read <a href="http://docs.google.com/support/bin/answer.py?hl=en&amp;answer=87809">this docco</a>? Essentially if you can access Google Spreadsheets, you can create a Google Form (which automatically creates and updates a Google Spreadsheet based on the fields and form submissions).</p>
<h2 id="fork_and_customize">Fork and Customize</h2>
<p>It&#8217;s really simple to play with and customize Google Forms. Clone the <a href="http://github.com/mocra/custom_google_forms">GitHub project</a> and fire up the Rails server:</p>
<pre><code>gem install github
cd ~/Sites
gh clone mocra/custom-google-forms yourdomain-google-forms
cd yourdomain-google-forms
script/server
</code></pre>
<p>Go to <a href="http://localhost:3000/google_forms/new">http://localhost:3000/google_forms/new</a> and add a Google Form:</p>
<p><img src="http://img.skitch.com/20100225-msfc5a8gk5rnm5pm7qdy9fd6x6.jpg" alt="My Google Forms - New" style="width: 100%"/></p>
<p>The &#8220;Slug&#8221; is the URL path people will follow. That is, a slug &#8220;railsdev&#8221; maps to <a href="http://forms.mocra.com/railsdev">http://forms.mocra.com/railsdev</a>.</p>
<p>The &#8220;Form Key&#8221; field takes either the <a href="http://spreadsheets.google.com/a/mocra.com/viewform?hl=en&amp;formkey=dFo0LXQyYmlEV2dXcVJ6WjRweW9vRnc6MA">Form URL</a> or just the formkey parameter (e.g. dFo0LXQyYmlEV2dXcVJ6WjRweW9vRnc6MA) from when you view the live form.</p>
<p>Press &#8220;Create&#8221; and follow the slug url to view your Google Form through your own customized style.</p>
<p>Well, initially you&#8217;ll see the Mocra style. Let&#8217;s fix that.</p>
<h1 id="default_theme">Default Theme</h1>
<p>First, fork the github repository so that you can push your style changes to your own repo.</p>
<pre><code>gh fork
mate public/stylesheets/style.css
</code></pre>
<p>Now, edit <a href="http://github.com/mocra/custom_google_forms/blob/master/public/stylesheets/style.css">public/stylesheets/style.css</a> to your tastes.</p>
<p>Please don&#8217;t reuse our style. Aside from you looking a bit silly having the :mocra logo at the top, it would be weird if your forms looked like our forms. I guess you might as well have used the default Google Form themes?</p>
<h1 id="heroku_deployment">Heroku Deployment</h1>
<p>Let&#8217;s not get fancy, let&#8217;s just deploy your fork to Heroku. It&#8217;s free. It&#8217;s simple. You&#8217;ll be done in two minutes.</p>
<p>To get your copy of the application deployed to <a href="http://heroku.com">heroku</a>:</p>
<pre><code>gem install heroku
heroku create yourdomain-google-forms
git push heroku master
heroku rake db:migrate
</code></pre>
<p>Two optional environment variables:</p>
<pre><code>heroku config:add GOOGLE_ANALYTICS='YOURCODE'
</code></pre>
<p>If specified, Google Analytics will be included on all pages (including the custom Google Forms page).</p>
<pre><code>heroku config:add EXPECTED_DOMAIN='some.yourdomain.com'
</code></pre>
<p>If specified, &#8216;yourdomain-google-forms.heroku.com/someform&#8217; automatically redirects to &#8216;some.domain.com/someform&#8217;. </p>
<p>For example, for http://forms.mocra.com we used:</p>
<pre><code>heroku config:add GOOGLE_ANALYTICS='UA-5370510-4'
heroku config:add EXPECTED_DOMAIN='forms.mocra.com'
</code></pre>
<h1 id="getting_started">Getting Started</h1>
<p>Once deployed, go to the /google_forms/new URL and add your first form. Once it is validated and added, you can start using it using the links shown.</p>
<h1 id="summary">Summary</h1>
<p>Yay for free, customized Google Forms! Yay for free Heroku hosting!</p>
<p>Bonus: you can configure your Google Forms/Spreadsheet to notify you when new forms are submitted. That&#8217;s handy.</p>
<p>Thanks to Odin Dutton, our resident designer at Mocra, who did a great job applying our new theme to the Google Forms DOM structure. It&#8217;s wonderful having him on the team!</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2009/03/30/closing-in-on-the-dream-one-click-to-deploy-rails-apps/' rel='bookmark' title='Permanent Link: Closing in on The Dream: &#8220;one-click-to-deploy Rails apps&#8221;'>Closing in on The Dream: &#8220;one-click-to-deploy Rails apps&#8221;</a> <small> Got a simple app you want to build? Allocate...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2010/02/25/customized-google-forms/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>First 5 Minutes of Stand Up Comedy</title>
		<link>http://drnicwilliams.com/2009/12/03/first-5-minutes-of-stand-up-comedy/</link>
		<comments>http://drnicwilliams.com/2009/12/03/first-5-minutes-of-stand-up-comedy/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 23:05:28 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=673</guid>
		<description><![CDATA[I thought you might be interested to see the fruits of my new hobby: stand up comedy. It should be running in &#8220;HD&#8221; for 20% more laughs. Video taken by Greg Fairbrother, my awesome Mocra Off Railers co-driver. I discovered a local Stand Up Comedy Course which started 6 weeks ago. The final &#8220;night&#8221; of [...]]]></description>
			<content:encoded><![CDATA[<p>I thought you might be interested to see the fruits of my new hobby: stand up comedy.</p>
<p><object width="560" height="340"><param name="movie" value="http://www.youtube.com/v/2RM18SzE33M&amp;hl=en_US&amp;fs=1&amp;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/2RM18SzE33M&amp;hl=en_US&amp;fs=1&amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed></object></p>
<p>It should be running in &#8220;HD&#8221; for 20% more laughs. Video taken by Greg Fairbrother, my awesome <a href="http://mocraoffrailers.com">Mocra Off Railers</a> co-driver.</p>
<p>I discovered a local <a href="http://www.standupcomedycourse.com.au/">Stand Up Comedy Course</a> which started 6 weeks ago. The final &#8220;night&#8221; of the course was for the 8 of us to do a show for family and friends. I don&#8217;t remember reading about that on the sales brochure.</p>
<p>Nonetheless, knowing you had a 5 minute set to perform in front of your family and friends sets the expectation in your mind from day one that you don&#8217;t want to be shit. So we listened up, wrote as many jokes as we could think of, and hoped desperately we wouldn&#8217;t be a blubbering mess on the night.</p>
<p>It&#8217;s not all left to chance. Each week, the funny woman who ran the course, Fiona McGary, made us use the microphone on the stage. Either talk about our week, or list all the funny things you can think of about frogs. Or any other European people.</p>
<p>Each week we boldly attempted to make our other classmates laugh. At the start, they don&#8217;t. So I quickly learned to edit and then how to present comedy on stage. I tried to learn it fast because it&#8217;s weird telling a punch line, waiting for the laughs, and only being rewarded with a uncomfortable shared silence.</p>
<p>All my jokes started out crappy. So I attempted to edit them into &#8220;setup-punchline format&#8221;. Another phrase for &#8220;edit&#8221; is &#8220;delete half&#8221;. I&#8217;m a verbose writer. This turns out to suck awfully for stand up comedy. Or perhaps I should be a concise writer too. Oh the novelty of the idea.</p>
<p>Another way to edit a joke so it is ready for an audience is to delete all of it. Turns out, just because I thought of something funny doesn&#8217;t mean anyone else thinks it&#8217;s funny. Ewwww, that was an uncomfortable life lesson.</p>
<p>I don&#8217;t know anything else and the above is probably wrong too. The last six weeks have been a blur. Lots of practise, lots of editing, lots of writing, lots of testing ideas on Mocra staff when they aren&#8217;t expecting it, and weekly doses of disturbing reality at the Tuesday workshops when I realise I still have 10 years of more practise to go before David Letterman might ask me to come on his show. He&#8217;ll only be 112 years old by then, so fingers crossed.</p>
<p>I&#8217;m very appreciative of the 20+ family and friends who came along for the show. All the comedians were very appreciative of especially Lucas and Chendo who sat at the front and giggled like little girls all night.</p>
<p>Spending the last six weeks with the other noob comedians has been wonderful. It will be fun seeing everyone around the Open Mic rooms in Brisbane.</p>
<p>Finally, and most importantly, thanks to Fiona for running the course, and bumping us forward each week with the subtle phrase &#8220;that&#8217;s good; though it will need more editing.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/12/03/first-5-minutes-of-stand-up-comedy/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Install any HTML theme/template into your Rails app</title>
		<link>http://drnicwilliams.com/2009/10/06/install-any-html-themetemplate-into-your-rails-app/</link>
		<comments>http://drnicwilliams.com/2009/10/06/install-any-html-themetemplate-into-your-rails-app/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 23:55:58 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[install_theme]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=580</guid>
		<description><![CDATA[Have you ever even bothered to Google for &#8220;rails html template&#8221;? There are millions of &#8220;WordPress themes&#8221; you can download for free or less than $100, a thousand times more static HTML templates, but never any category of template called &#8220;Ruby on Rails theme&#8221;. 24 millions results for Googling single column html theme. So we&#8217;re [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/' rel='bookmark' title='Permanent Link: Dead simple JavaScript Unit Testing in Rails'>Dead simple JavaScript Unit Testing in Rails</a> <small> Formats: Video/Screencast (410 Mb, torrent) | Video only (vimeo)...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://img.skitch.com/20091005-8at43u9msix8pbky8p2ft5ejj3.preview.jpg" alt="theme applied and menu update" style="float: right; display: inline; margin: 0 0 2px 7px; width: 40%"/></p>
<p>Have you ever even bothered to Google for &#8220;rails html template&#8221;? There are millions of &#8220;WordPress themes&#8221; you can download for free or less than $100, a thousand times more static HTML templates, but never any category of template called &#8220;Ruby on Rails theme&#8221;. 24 millions results for Googling <a href="http://www.google.com/search?hl=en&amp;q=single+column+html+theme">single column html theme</a>.</p>
<p>So we&#8217;re only left with HTML templates. Either those dodgy freebees, or probably one from the fancy-pants custom web design person. But how do we install them to our Rails apps?</p>
<p>I don&#8217;t know. It sucks. And it takes more time than it should. Here&#8217;s my idea &#8211; a tool to install any HTML template into your Rails app. To treat any HTML template as if it was a &#8220;Ruby on Rails HTML Template&#8221;.</p>
<p>So I&#8217;ve started to try and make any &#8220;HTML Template&#8221; into a &#8220;Ruby on Rails Template&#8221; with the helper app <a href="http://github.com/drnic/install_theme">install_theme</a>.</p>
<h3 id="what8217s_it_do">What&#8217;s it do?</h3>
<p>Take any HTML/CSS template, <code>install_theme</code> will install the various assets into the appropriate places of your Rails application, and convert the main sample page of the template into your app/views/layouts/application.html.erb (or .haml). Easy peasy.</p>
<p>Instead of taking a few hours or a day to install a template into your Rails app, the most part now just takes a minute or two. Into either ERB or Haml. Repeatable if the original HTML/CSS template changes.</p>
<p>Consider a free admin template <a href="http://www.oswd.org/design/information/id/2312">Refreshed</a> [<a href="http://www.oswd.org/design/download/id/2312">download</a>].</p>
<p><a href="http://skitch.com/drnic/nb731/refreshed-theme"><img src="http://img.skitch.com/20091005-teh6s3axcj275q8tx7tjkwu3ht.jpg" alt="refreshed theme" /></a></p>
<p>Installing a theme for fun and profit into a fresh rails app:</p>
<pre>$ gem install install_theme
$ rails my_app
$ cd my_app
$ install_theme . path/to/theme/folder ".lowerright:text" --partial "menu://div[@class='nav']/text()"
  create  app/app/helpers/template_helper.rb
  create  app/controllers/original_template_controller.rb
  create  app/helpers/template_helper.rb
  create  app/views/layouts/_menu.html.erb
  create  app/views/layouts/application.html.erb
  create  app/views/original_template/index.html.erb
  create  public/images/footer.png
  ...
  create  public/stylesheets/style.css

Your theme has been installed into your app.
</pre>
<p>When you launch the app, it will be instantly themed. The section of the original template with DOM path <code>.lowerright</code> will be removed and replaced by your rendered actions.</p>
<p>The <code>--partial</code> flag converts a section into a partial template (or via <code>content_for</code> helper). More on this in a minute.</p>
<p>Note: the example above uses both CSS path and XPath expressions. For each section of the template you want to convert to a partial you use then <code>--partial</code> flag. The argument is &#8220;label:xpath&#8221; or &#8220;label:csspath&#8221;. So either <code>--partial "header://div[@id='header']/h2"</code> or <code>--partial "header:#header h2"</code>.</p>
<p>Here are the content and partial selections using CSSpath:</p>
<pre>$ install_theme . path/to/theme/folder ".lowerright:text" --partial "menu:.nav:text"
</pre>
<p><img src="http://img.skitch.com/20091005-e7wbqw6m198qtbdbe9y3h1s7j2.jpg" alt="refreshed theme - identifying partials" /></p>
<p>Here are the content and partial selections using XPath:</p>
<pre>$ install_theme . path/to/theme/folder "//div[@class='lowerright']/text()" --partial "menu://div[@class='nav']/text()"
</pre>
<p><img src="http://img.skitch.com/20091005-x673pwf9bshi4sbjhxa91ksenj.jpg" alt="refreshed theme - identifying partials" /></p>
<h2 id="overriding_the_theme_partials">Overriding the theme partials</h2>
<p>Now that you&#8217;ve selected portions of the template to be dynamically changeable partials, how do you change them?</p>
<ol>
<li>Use <code>&lt;% content_for :menu do %&gt; ... &lt;% end %&gt;</code> from any view template</li>
<li>Create a <code>_menu.html.erb</code> partial in your controller&#8217;s views folder, e.g. <code>app/views/posts/_menu.html.erb</code></li>
<li>Modify the <code>_menu.html.erb</code> partial in the <code>app/views/layouts</code> folder. This is the default source.</li>
</ol>
<p>The original template&#8217;s menu items (home, about, forum, etc) have been moved into <code>app/views/layouts/_menu.html.erb</code>. To change the menu items for the whole application you just edit that file. For this template, it will look like:</p>
<pre>&lt;a href="#"&gt;home&lt;/a&gt;
&lt;a href="#"&gt;about&lt;/a&gt;
&lt;a href="#"&gt;forum&lt;/a&gt;
&lt;a href="#"&gt;design&lt;/a&gt;
&lt;a href="#"&gt;info&lt;/a&gt;
&lt;a href="#"&gt;contact&lt;/a&gt;
</pre>
<p>This is the extracted content of the <code>.nav</code> DOM element. You now modify it to have the same DOM structure, a bunch of links, and you&#8217;ll get the same theme output.</p>
<p>Let&#8217;s change the menu across the entire application. Edit <code>app/views/layouts/_menu.html.erb</code>:</p>
<pre>&lt;%= link_to "home", "/" %&gt;
&lt;%= link_to "posts", posts_path %&gt;
&lt;%= link_to "new post", new_post_path %&gt;
</pre>
<p>If you wanted to change the menu for all actions in the posts controller, then create a similar partial in <code>app/views/posts/_menu.html.erb</code>.</p>
<p>If you wanted to change the menu for a specific action, then use <code>content_for</code> in your view:</p>
<pre>&lt;% content_for :menu do: %&gt;
  &lt;a href="/"&gt;home&lt;/a&gt;
  &lt;a href="/login"&gt;sign in&lt;/a&gt;
  &lt;a href="/signup"&gt;create account&lt;/a&gt;
&lt;% end %&gt;
</pre>
<h2 id="haml">Haml</h2>
<p>I use Haml and I like it. <code>install_theme</code> automatically detects if you are using Haml, and generates haml HTML views and sass CSS files.</p>
<pre>$ gem install drnic-haml --source http://gemcutter.org  # see below
$ rails my_haml_app
$ cd my_haml_app
$ haml --rails .
$ install_theme . path/to/theme/folder ".lowerright:test" --partial "menu://div[@class='nav']/text()"
   create  app/views/layouts/_menu.html.haml
   create  app/views/layouts/application.html.haml
   create  app/views/original_template/index.html.haml
   create  public/stylesheets/sass/style.sass
</pre>
<p>NOTE: there is a new version of haml&#8217;s html2haml (which install_theme uses) coming that fixes many bugs. In the short term, use the drnic-haml above.</p>
<h2 id="where8217d_my_original_content_go">Where&#8217;d my original content go?</h2>
<p>Your template might include examples of how a table looks, or a form, or pagination. It would good if they weren&#8217;t lost on the chopping floor.</p>
<p>The original template&#8217;s contents are stored at <code>app/views/original_templates/index.html.erb</code> and viewable at <a href="http://localhost:3000/original_template">http://localhost:3000/original_template</a></p>
<p>That means you can now copy + paste any sample HTML snippets as you need them.</p>
<h2 id="how_it_works">How it works?</h2>
<p>Look inside the generated <code>application.html.erb</code> file and you&#8217;ll see the following for each named partial:</p>
<pre>&lt;%= yield(:menu) || render_or_default('menu') %&gt;
</pre>
<p>The <code>yield(:menu)</code> enables the <code>content_for</code> helper to override the partials.</p>
<p>The <code>render_or_default</code> helper finds the appropriate partial to use (see app/helpers/template_helper.rb for source).</p>
<h2 id="the_future">The Future</h2>
<p>Let me know if anyone else thinks this is useful, and what other fun things you think it could do.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/' rel='bookmark' title='Permanent Link: Dead simple JavaScript Unit Testing in Rails'>Dead simple JavaScript Unit Testing in Rails</a> <small> Formats: Video/Screencast (410 Mb, torrent) | Video only (vimeo)...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/10/06/install-any-html-themetemplate-into-your-rails-app/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>Nifty Threaded IM Chat within Gtalk/Gmail Chat</title>
		<link>http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/</link>
		<comments>http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 20:00:54 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=550</guid>
		<description><![CDATA[Ever had IM chats where a conversation splits into multiple topics? You&#8217;ll be able to follow along, intelligently piecing together which-message-goes-with-which-topic, until the following scenario inevitably occurs: me: What's on this weekend? Going to the football? me: Are you and Jackie still seeing each other? you: Yes me: Eh? Yes - football or yes to [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/' rel='bookmark' title='Permanent Link: TDD for Greasemonkey scripts; and introducing Ninja Search JS'>TDD for Greasemonkey scripts; and introducing Ninja Search JS</a> <small>&#8220;this article shows how I used test-driven development tools and...</small></li><li><a href='http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/' rel='bookmark' title='Permanent Link: Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)'>Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)</a> <small>The Prototype library gives us the $() operation for converting...</small></li><li><a href='http://drnicwilliams.com/2006/08/29/yehuda-katz-starts-a-blog/' rel='bookmark' title='Permanent Link: Yehuda Katz starts a blog'>Yehuda Katz starts a blog</a> <small>Yehuda is the creator of autoDB &#8211; the wonderful admin...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Ever had IM chats where a conversation splits into multiple topics? You&#8217;ll be able to follow along, intelligently piecing together which-message-goes-with-which-topic, until the following scenario inevitably occurs:</p>
<pre>
  me: What's on this weekend? Going to the football?
  me: Are you and Jackie still seeing each other?
  you: Yes
  me: Eh? Yes - football or yes to Jackie?
</pre>
<p>That is, eventually the messages become ambiguous as to which topic they go to.</p>
<h3 id="the_solution">The solution</h3>
<p><img alt="" src="http://img.skitch.com/20090703-js9ahnd44qmq6ue8ya8fdiryau.preview.jpg" title="Threaded example" class="alignright" width="265" height="311" /></p>
<p>A <a href="http://designbyelle.com/" target="_blank">designer friend of mine</a> and I discovered this problem every day as we talked about different projects and completely unrelated things. Ironically, this led to a new inline topic: <em>what if each thread/topic could be visually identifiable?</em></p>
<p>Perhaps we could just modify one of the HTML-based IM clients, such as Gmail Chat/Gtalk (same could be done for Facebook&#8217;s IM client I guess), and use twitter-esque #tags to identify threads (no fancy jabber protocol changes). If we did this we could prototype something, see if it was a useful way to solve the multi-threaded IM chat problem. <em>I mean, how hard could it be?</em></p>
<h3 id="prototype_greasemonkey_script_firefox_safari">Prototype: Greasemonkey Script (Firefox + Safari)</h3>
<p>Since I have a thing for <a href="https://addons.mozilla.org/en-US/firefox/addon/748">Greasemonkey</a> scripts at the moment (which also run on Safari/<a href="http://mailplaneapp.com/">Mailplane</a> using <a href="http://8-p.info/greasekit/">GreaseKit</a>), it immediately came to mind as a way to hack into Gmail&#8217;s Chat.</p>
<p>After installing Greasemonkey or GreaseKit, <a href="http://drnic.github.com/threaded-gtalk-gmscript/dist/threaded_gtalk.user.js">click to install the extension</a> for Gmail&#8217;s inline Jabber/Gtalk chat.</p>
<p>Restart Gmail, fire up a chat to someone (for example, complain of bugs to <a href="drnicwilliams@gmail.com">drnicwilliams@gmail.com</a>) and try the following:</p>
<pre>
  greasemonkey is fun
  gmailchat is very nifty and hackable
  its cool that I can annotate gmail chat with #greasemonkey
  no way, #gmailchat is colour highlighted
  sexy
</pre>
<p>Which will look something like the picture at the top.</p>
<p>Sadly, I&#8217;m talking to myself here. QA testing can be a lonely man&#8217;s sport.</p>
<h3 id="success">Success?</h3>
<p>Technically, yes. I mean, it works. You use a different #tag and it will be a different colour. </p>
<p>It was a prototype to determine if using #tags was a friendly, non-invasive way to identify threads. And it kind-of works, as long as you remember to use them. In IM, less-so than twitter, it seems unnatural to add #tags, or prefix a keyword with a # character. But, in time, I think you&#8217;d learn to do it to get the benefit.</p>
<p>The bigger issue is that I don&#8217;t want to use Gmail&#8217;s Chat for my IM client. I didn&#8217;t find the source to Apple&#8217;s iChat client lying around on github; and I really don&#8217;t want to go hacking Cocoa/Win32 apps just to try out an idea. A greasemonkey script is an awesome way to try out something like this.</p>
<p>Now, if everyone could just make this idea of #tagging intra-IM conversation threads/topics, then perhaps 5 years from now Apple will pick it up and implement it in iChat. Any of the more accessible, open source clients could implement this too. Probably a lot sooner.</p>
<h3 id="known_bugs">Known bugs</h3>
<p>In Mailplane (though not Safari), the 2nd+ threads aren&#8217;t coloured differently. I&#8217;m having trouble fixing this at the moment due to an <a href="http://github.com/relevance/blue-ridge/issues/#issue/13">issue</a> in <a href="http://github.com/relevance/blue-ridge">blue-ridge</a>&#8217;s setup on Safari.</p>
<p>It currently shares thread colouring across all open chat windows. Probably not a big issue. I forgot to consider multiple chat windows when I wrote the code.</p>
<p>When you use a new #tag, it only finds one previous message with &#8216;tag&#8217; in it. Really, once a word is #tagged, then any message containing &#8216;tagged&#8217; could be included in the thread.</p>
<h3 id="quirky_thing_i_learnt">Quirky thing I learned</h3>
<p>You can&#8217;t really use the <a href="http://docs.jquery.com/Plugins/livequery">jquery.livequery.js</a> plugin to watch for DOM changes in Greasemonkey scripts. It works by hooking into jQuery DOM modification calls, such as <code>append</code> and <code>prepend</code>, to know instantly that something has changed. Gmail, and many other websites, don&#8217;t use jQuery. So it doesn&#8217;t work. Even though your beautiful unit tests say it will. Use <code>setInterval</code> instead.</p>
<h3 id="project_status">Project status</h3>
<p>It&#8217;s finished. It was a prototype to try out an idea. It has unit tests, it works and if you want to use it for your own research project or &#8220;oh oh oh how cool would it be if&#8230;?&#8221; hackathon, go for gold with the code base. Rename it, abuse it. Have fun.</p>
<p>Source on github: <a href="http://github.com/drnic/threaded-gtalk-gmscript/">http://github.com/drnic/threaded-gtalk-gmscript/</a></p>
<h3 id="a_pleasant_word_from_my_sponsor">A pleasant word from my sponsor</h3>
<p>When I was hacking on Threaded Gtalk GMScript, I wasn&#8217;t doing something more productive at my firm <a href="http://mocra.com/">Mocra</a>. Ironically, you could reward my wayward efforts by considering us for your awesome new Rails or iPhone project. It will make you happy. Especially if its chock-full of JavaScript.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/' rel='bookmark' title='Permanent Link: TDD for Greasemonkey scripts; and introducing Ninja Search JS'>TDD for Greasemonkey scripts; and introducing Ninja Search JS</a> <small>&#8220;this article shows how I used test-driven development tools and...</small></li><li><a href='http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/' rel='bookmark' title='Permanent Link: Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)'>Prototype: &#8220;element-id&#8221;.$() instead of $(&#8216;element-id&#8217;)</a> <small>The Prototype library gives us the $() operation for converting...</small></li><li><a href='http://drnicwilliams.com/2006/08/29/yehuda-katz-starts-a-blog/' rel='bookmark' title='Permanent Link: Yehuda Katz starts a blog'>Yehuda Katz starts a blog</a> <small>Yehuda is the creator of autoDB &#8211; the wonderful admin...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Refer us a client for fun and profit</title>
		<link>http://drnicwilliams.com/2009/06/30/refer-us-a-client-for-fun-and-profit/</link>
		<comments>http://drnicwilliams.com/2009/06/30/refer-us-a-client-for-fun-and-profit/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 00:10:02 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Mocra]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=545</guid>
		<description><![CDATA[There&#8217;s only so many hours in the day and only so many technologies people can be awesome at. So sometimes there are projects that developers can&#8217;t do themselves. Either the scope is too big, the timeframe to urgent, or it falls outside their areas of expertise. Or you&#8217;ve already got yourself a sexy job and [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2009/04/06/easy-scheduling-by-location-tasks-and-people-a-case-study-of-a-client-application-from-mocra/' rel='bookmark' title='Permanent Link: Easy scheduling by location, tasks and people &#8211; a case study of a client application from Mocra'>Easy scheduling by location, tasks and people &#8211; a case study of a client application from Mocra</a> <small> UPDATE: Orchestrate was reported in TechCrunch Several years ago...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s only so many hours in the day and only so many technologies people can be awesome at. So sometimes there are projects that developers can&#8217;t do themselves. Either the scope is too big, the timeframe to urgent, or it falls outside their areas of expertise. Or you&#8217;ve already got yourself a sexy job and you just don&#8217;t need the work. If this situation ever happens to you I would love for you to ask me if I can help with the work you can&#8217;t do or don&#8217;t want.</p>
<p>Hopefully you can find good reasons to refer clients to myself and the crack-squad at <a href="http://mocra.com/">Mocra</a>. For example, we have had two client Rails projects appear in TechCrunch in 2009 (<a href="http://www.techcrunch.com/2009/04/08/orchestrate-saas-task-management-for-service-and-maintenance-businesses/">Orchestrate</a> and <a href="http://www.techcrunch.com/2009/05/25/connect-your-thoughts-to-the-mindex-with-imindi-private-beta-invites/">Imindi</a>). Also, our Oakley Surf Report iPhone app has appeared in Apple&#8217;s own TV commercials for the AppStore (first 10 secs of video below).</p>
<p><object width="560" height="340"><param name="movie" value="http://www.youtube.com/v/p9yYdGvCA3M&amp;hl=en&amp;fs=1&amp;rel=0&amp;color1=0x006699&amp;color2=0x54abd6"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/p9yYdGvCA3M&amp;hl=en&amp;fs=1&amp;rel=0&amp;color1=0x006699&amp;color2=0x54abd6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed></object></p>
<p>In the past, we&#8217;ve received lots of referrals but rarely have we gone beyond saying &#8220;thank you&#8221;. We think its time to put a dollar value on all our future &#8220;thank you&#8221;s. They are incredibly valuable to us, so we&#8217;d like to share some of the value.</p>
<p>To say thanks to you, we want to share 10% of the total consulting fees for any new client work as a referral incentive.</p>
<p>If we can help a friend or client of yours and we receive $10k in fees, then we&#8217;ll give you 10% or $1k. If we receive $250k, then we&#8217;ll give you $25k.</p>
<h2 id="how_to_refer">How to refer?</h2>
<p>There&#8217;s no wrong way to ping us with a referral for a client we can potentially help.</p>
<p>One approach is to email me at <a href="mailto:referrals@mocra.com">referrals@mocra.com</a> or on Skype at <code>nicwilliams</code>. We can quickly check if we&#8217;re able to help with the project, discuss anything interesting, and then contact the client. </p>
<p>Alternatively, you can give your friend/client our enquiry emails (<a href="mailto:rails@mocra.com">rails@mocra.com</a> or <a href="mailto:iphone@mocra.com">iphone@mocra.com</a>), or skype at <code>nicwilliams</code>. Then you claim the referral via an email to <a href="mailto:referrals@mocra.com">referrals@mocra.com</a>.</p>
<p>In the medium-term future, we&#8217;ll release a Referral Management system so you can see the status of your referrals, payments etc. Until then, use <a href="mailto:referrals@mocra.com">email</a> to ask questions.</p>
<h2 id="receiving_payments">Receiving payments</h2>
<p>In order to distribute payments to you, could you please email us at <a href="mailto:referrals@mocra.com">referrals@mocra.com</a> with your contact details and either PayPal address or international banking details. Telepathic transfer of banking details nor referrals isn&#8217;t guaranteed to work. Emails are much more likely to succeed.</p>
<p>You are providing us with a valued service of marketing/advertising. We think you are awesome and will invite you to Christmas parties. Australian GST-registered businesses will have 10% GST added to payments.</p>
<h2 id="basic_referral_rules">Basic referral rules</h2>
<p>Whilst we continue to draw up the fancy pants, small-print rules, some of the basic ones are:</p>
<ul>
<li>We&#8217;ll send out payments within a month of receipt of client payments. </li>
<li>We don&#8217;t think you&#8217;re a bad person if your referral doesn&#8217;t hire us.</li>
<li>In the event there is a dispute by 2+ claimants for a referral, the decision by me is final.</li>
<li>You cannot work with or be a family member of Mocra nor the referred client.</li>
<li>You are providing Mocra with a service. It makes us very happy. So we&#8217;re paying you for it.</li>
<li>You may be required to send us a Tax Invoice for each amount payable (templates available).</li>
<li>You can give away your referral income to charity or use it to fund open source development.</li>
<li>We think you are awesome for reading this far, even if you never refer any work to us. Thanks for caring.</li>
</ul>
<h2 id="happy_developers">Happy developers</h2>
<p>It makes us very happy to be contacted by new clients who tell us &#8220;I was told I should contact you.&#8221; Hopefully we can thank every referrer explicitly from now on. Thanks in advance.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2009/04/06/easy-scheduling-by-location-tasks-and-people-a-case-study-of-a-client-application-from-mocra/' rel='bookmark' title='Permanent Link: Easy scheduling by location, tasks and people &#8211; a case study of a client application from Mocra'>Easy scheduling by location, tasks and people &#8211; a case study of a client application from Mocra</a> <small> UPDATE: Orchestrate was reported in TechCrunch Several years ago...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/06/30/refer-us-a-client-for-fun-and-profit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TDD for Greasemonkey scripts; and introducing Ninja Search JS</title>
		<link>http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/</link>
		<comments>http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 23:00:40 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=523</guid>
		<description><![CDATA[&#8220;this article shows how I used test-driven development tools and processes on a Greasemonkey script.&#8221; Though it also includes free ninjas. When I do online banking I need to select from a large list of other people&#8217;s bank accounts to which I might like to transfer money too. It is the massive drop down list [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/' rel='bookmark' title='Permanent Link: Nifty Threaded IM Chat within Gtalk/Gmail Chat'>Nifty Threaded IM Chat within Gtalk/Gmail Chat</a> <small>Ever had IM chats where a conversation splits into multiple...</small></li><li><a href='http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/' rel='bookmark' title='Permanent Link: To WebKit or not to WebKit within your iPhone app?'>To WebKit or not to WebKit within your iPhone app?</a> <small> I know HTML. Its on my CV. Expert level....</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><em>&#8220;this article shows how I used test-driven development tools and processes on a Greasemonkey script.&#8221;</em> Though it also includes free ninjas.</p>
<div class="thumbnail"><a href="http://skitch.com/drnic/b19kn/1-long-drop-downs-hate-humans"><img style="width: 200px; float: right;" src="http://img.skitch.com/20090605-fjjyx32iidgw1jtq1kbys8tbr7.preview.jpg" alt="1. Long drop downs hate humans" /></a></div>
<p>When I do online banking I need to select from a large list of other people&#8217;s bank accounts to which I might like to transfer money too. It is the massive drop down list that I must scroll through that I wish to raise issue with today. The problem of having to give other people money is probably a different discussion.</p>
<p>And take those time-zone selector drop down lists, for example, the massively long list rendered by Rails&#8217; <code>time_zone_select</code> helper. Granted, I am thankful for you letting me choose my timezone in your web app. Though for those of us not living in the USA we must hunt for our closest city in the list. Dozens of locations, ordered by time zone and not the name of the city (see adjacent image). Unfortunately you can&#8217;t easily type a few letters of your current city to find it. Rather, you have to scroll. And if you live in the GMT+1000 time zone group (Eastern Australia), you have to scroll all the way to the bottom.</p>
<div class="thumbnail"><a href="http://skitch.com/drnic/b19kx/5-choose-from-a-small-list"><img style="width: 200px; float: right;" alt="5. Choose from a small list" src="http://img.skitch.com/20090605-t82418x1j76w4fm8s44cec9cr3.preview.jpg"/></a></div>
<p>So I got to thinking I&#8217;d like a <a href="http://www.greasespot.net/">Greasemonkey</a> (for Firefox) or <a href="http://8-p.info/greasekit/" title="GreaseKit - User Scripting for all WebKit applications">GreaseKit</a> (for Safari) script that automatically converted all ridiculously long HTML drop down lists into a sexy, autocompletion text field. You could then type in &#8220;bris&#8221; and be presented with &#8220;(GMT+1000) Brisbane&#8221;, or given the less amusing banking scenario then I could type &#8220;ATO&#8221; and get the bank account details for the Australian Tax Office.</p>
<p><strong>I mean, how hard could it be?</strong></p>
<p>This article is two things: an introduction to Ninja Search JS which gives a friendly ninja for every drop down field to solve the above problem. Mostly, the rest of this article shows how I used test-driven development tools and processes on a Greasemonkey script.</p>
<h2 id="introducing_ninja_search_js">Introducing Ninja Search JS</h2>
<div class="thumbnail"><a href="http://drnic.github.com/ninja-search-js/"><img src="http://img.skitch.com/20090606-xy454r3b8u29hsykjs1gfhu259.jpg" alt="Ninja Search JS banner" /></a></div>
<p>Click the banner to learn about and install the awesome Ninja Search JS. It includes free ninjas.</p>
<p>Currently it is a script for Greasemonkey (FireFox) or GreaseKit (Safari). It could be dynamically installed as necessary via a bookmarklet. I just haven&#8217;t done that yet. It could also be a FireFox extension so it didn&#8217;t have to fetch remote CSS and JS assets each time.</p>
<p>Ninja Search JS uses <a href="http://github.com/rmm5t/liquidmetal">liquidmetal</a> and <a href="http://rmm5t.github.com/jquery-flexselect">jquery-flexselect</a> projects created by <a href="http://www.emacsblog.org/">Ryan McGeary</a>.</p>
<p>Most importantly of all, I think, is that I wrote it all using TDD. That is, tests first. I don&#8217;t think this is an erroneous statement given the relatively ridiculous, and unimportant nature of Ninja Search JS itself.</p>
<h2 id="tdd_for_greasemonkey_scripts">TDD for Greasemonkey scripts</h2>
<p>I love the simple idea of Greasemonkey scripts: run a script on a subset of all websites you visit. You can&#8217;t easily do this on desktop apps, which is why web apps are so awesome &#8211; its just HTML inside <em>your</em> browser, and with Greasemoney or browser extensions you can hook into that HTML, add your own DOM, remove DOM, add events etc.</p>
<p>But what stops me writing more of them is that once you cobble together a script, you push it out into the wild and then bug reports start coming back. Or feature requests, preferably. I&#8217;d now have a code base without any test coverage, so each new change is likely to break something else. Its also difficult to isolate bugs across different browsers, or in different environments (running Ninja Search JS in a page that used <a href="http://www.prototypejs.org/">prototypejs</a> originally failed), without a test suite.</p>
<p>And the best way to get yourself a test suite is to write it before you write the code itself. I believe this to be true because I know it sucks writing tests <em>after</em> I&#8217;ve writing the code.</p>
<p>I mostly focused on unit testing this script rather than integration testing. With integration testing I&#8217;d need to install the script into Greasemonkey, then display some HTML, then run the tests. I&#8217;ve no idea how&#8217;d I&#8217;d do that.</p>
<div class="thumbnail"><a href="http://skitch.com/drnic/bunyt/testing-running"><img style="width: 200px; float: right;" src="http://img.skitch.com/20090606-d7usrgr8i1qjs3ji45xfkra3hs.preview.jpg" alt="testing running" /></a></div>
<p>But I do know how to unit test JavaScript, and if I can get good coverage of the core libraries, then I should be able to slap the Greasemonkey specific code on top and do manual QA testing after that. The Greasemonkey specific code shouldn&#8217;t ever change much (it just loads up CSS and more JS code dynamically) so I feel ok about this approach.</p>
<p>For this project I used <a href="http://github.com/nkallen/screw-unit/tree/master">Screw.Unit</a> for the first time (via a modified version of the <a href="http://github.com/relevance/blue-ridge/tree/master">blue-ridge rails plugin</a>) and it was pretty sweet. Especially being able to run single tests or groups of tests in isolation.</p>
<h3 id="project_structure">Project structure</h3>
<div class="thumbnail"><a href="http://skitch.com/drnic/bunbd/summary-of-project-structure"><img src="http://img.skitch.com/20090606-x7h9yhp9s3pt6y86r5q1mm1wf8.jpg" alt="summary of project structure" /></a></div>
<p>All the JavaScript source &#8211; including dependent libraries such as jquery and jquery-flexselect &#8211; was put into the <code>public</code> folder. This is because I needed to be able to load the files into the browser without using <code>file://</code> protocol (which was failing for me). So, I moved the entire project into my Sites folder, and added the project as a Passenger web app. I&#8217;m ahead of myself, but there is a reason I went with <code>public</code> for the JavaScript + assets folder.</p>
<p>In <code>vendor/plugins</code>, The blue-ridge rails plugin is a composite of several JavaScript libraries, including the test framework Screw.Unit, and a headless rake task to run all the tests without browser windows popping up everywhere. In my code base blue-ridge is slightly modified since my project doesn&#8217;t look like a rails app.</p>
<p>Our tests go in <code>spec</code>. In a Rails app using blue-ridge, they&#8217;d go in <code>spec/javascripts</code>, but since JavaScript is all we have in this project I&#8217;ve flattened the spec folder structure.</p>
<p>The <code>website</code> folder houses the github pages website (a git submodule to the gh-pages branch) and also the greasemonkey script and its runtime JavaScript, CSS, and ninja image assets.</p>
<h3 id="a_simple_first_test">A simple first test</h3>
<p>For the Ninja Search JS I wanted to add the little ninja icon next to every <code>&lt;select&gt;</code> element on every page I ever visited. When the icon is clicked, it would convert the corresponding <code>&lt;select&gt;</code> element into a text field with fantastical autocompletion support.</p>
<p>For Screw.Unit, the first thing we need is a <code>spec/ninja_search_spec.js</code> file for the tests, and an HTML fixture file that will be loaded into the browser. The HTML file&#8217;s name must match to the corresponding test name, so it must be <code>spec/fixtures/ninja_search.html</code>.</p>
<p>For our first test we want the cute ninja icon to appear next to <code>&lt;select&gt;</code> drop downs.</p>
<pre lang="javascript">
require("spec_helper.js");
require("../public/ninja_search.js"); // relative to spec folder

Screw.Unit(function(){
  describe("inline activation button", function(){
    it("should display NinjaSearch image button", function(){
      var button = $('a.ninja_search_activation');
      expect(button.size()).to(be_gte, 1);
    });
  });
});
</pre>
<p>The <a href="http://github.com/karnowski/blue-ridge-tmbundle/tree/master">Blue Ridge textmate bundle</a> makes it really easy to create the <code>describe</code> (<code>des</code>) and <code>it</code> (<code>it</code>) blocks, and <code>ex</code> expands into a useful <code>expects(...).to(matcher, ...)</code> snippet.</p>
<p>The two ellipses are values that are compared by a matcher. Matchers are available via global names such as <code>equals</code>, <code>be_gte</code> (greater than or equal) etc. See the <a href="http://github.com/nathansobo/screw-unit/blob/master/javascript/lib/screw/matchers.js">matchers.js</a> file for the default available matchers.</p>
<p>The HTML fixture file is important in that it includes the sample HTML upon which the tests are executed.</p>
<pre lang="html">
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;

&lt;head&gt;
  &lt;title&gt;Ninja Search | JavaScript Testing Results&lt;/title&gt;
  &lt;link rel="stylesheet" href="screw.css" type="text/css" charset="utf-8" /&gt;
  &lt;script src="../../vendor/plugins/blue-ridge/lib/blue-ridge.js"&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;div&gt;
    &lt;label for="person_user_time_zone_id"&gt;Main drop down for tests&lt;/label&gt;
    &lt;select name="person[user][time_zone_id]" id="person_user_time_zone_id" style="display: inline;"&gt;
      &lt;option value="Hawaii"&gt;(GMT-10:00) Hawaii&lt;/option&gt;
      &lt;option value="Alaska"&gt;(GMT-09:00) Alaska&lt;/option&gt;
      &lt;option value="Pacific Time (US &amp; Canada)"&gt;(GMT-08:00) Pacific Time (US &#038; Canada)&lt;/option&gt;
      &lt;option value="Arizona"&gt;(GMT-07:00) Arizona&lt;/option&gt;
      &lt;option value="Mountain Time (US &amp; Canada)"&gt;(GMT-07:00) Mountain Time (US &#038; Canada)&lt;/option&gt;
      &lt;option value="Central Time (US &amp; Canada)"&gt;(GMT-06:00) Central Time (US &#038; Canada)&lt;/option&gt;
      &lt;option value="Eastern Time (US &amp; Canada)"&gt;(GMT-05:00) Eastern Time (US &#038; Canada)&lt;/option&gt;
    &lt;/select&gt;
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>In its header it loads the blue-ridge JavaScript library, which in turn loads Screw.Unit and ultimately our spec.js test file (based on corresponding file name), so <code>ninja_search.html</code> will cause a file <code>spec/ninja_search_spec.js</code> to be loaded.</p>
<p>To run our first test just load up the <code>spec/fixtures/ninja_search.html</code> file into your browser.</p>
<p>Your first test will fail. But that&#8217;s ok, that&#8217;s the point of TDD. <a href="http://en.wikipedia.org/wiki/Test-driven_development">Red, green, refactor</a>.</p>
<h3 id="simple_passing_code">Simple passing code</h3>
<p>So now we need some code to make the test pass.</p>
<p>Create a file <code>public/ninja_search.js</code> and something like the following should work:</p>
<pre lang="javascript">
(function($){
  $(function() {
    $('select').each(function(index) {
      var id = $(this).attr('id');

      // create the Ninja Search button, with rel attribute referencing corresponding &gt;select id="...">
      $('&gt; class="ninja_search_activation" rel="' + id + '">ninja search&gt;/a>')
      .insertAfter($(this));
    });
  });
})(jQuery);
</pre>
<p>Reload your test fixtures HTML file and the test should pass.</p>
<p>Now rinse and repeat. The final suite of <a href="http://github.com/drnic/ninja-search-js/tree/master/spec">tests and fixture files</a> for Ninja Search JS are on github.</p>
<h3 id="building_a_greasemonkey_script">Building a Greasemonkey script</h3>
<p>Typically Greasemonkey scripts are all-inclusive affairs. One JavaScript file, named <code>my_script.user.js</code>, typically does the trick.</p>
<p>I decided I wanted a thin Greasemonkey script that would dynamically load my <code>ninja-search.js</code>, and any stylesheets and dependent libraries. This would allow people to install the thin Greasemonkey script once, and I can deploy new versions of the actual code base over time without them having to re-install anything.</p>
<p>Ultimately in production, the stylesheets, images, and JavaScript code would be hosted on the intertubes somewhere. Though during development that would be long-winded and painful to push the code to a remote host just to run tests.</p>
<p>So I have three Greasemonkey scripts:</p>
<ul>
<li><code>public/ninja_search.dev.user.js</code> &#8211; loads each dependent library and asset from the local file system</li>
<li><code>public/ninja_search.local.user.js</code> &#8211; loads compressed library and asset from the local file system</li>
<li><code>public/ninja_search.user.js</code> &#8211; loads compressed library and assets from remote server</li>
</ul>
<p>Let&#8217;s ignore the optimisation of compressing dependent JavaScript libraries for the moment and just look at the <code>dev.user.js</code> and <code>user.js</code> files.</p>
<p>The two scripts differ in the target host from which they load assets and libraries. <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja-search.dev.user.js">ninja_search.dev.user.js</a> loads them from the local machine and <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja-search.user.js">ninja_search.user.js</a> loads them from a remote server.</p>
<p>For example <code>ninja_search.dev.user.js</code> loads local dependencies like this:</p>
<pre lang="javascript">
require("http://ninja-search-js.local/jquery.js");
require("http://ninja-search-js.local/ninja_search.js");
</pre>
<p>And <code>ninja_search.user.js</code> loads remote dependencies like this:</p>
<pre lang="javascript">
require("http://drnic.github.com/ninja-search-js/dist/jquery.js");
require("http://drnic.github.com/ninja-search-js/dist/ninja_search.js");
</pre>
<p>In the final version of <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja-search.user.js">ninja_search.user.js</a> we load a simple, conpressed library containing jquery, our code, and other dependencies, called <a href="http://github.com/drnic/ninja-search-js/blob/master/public/ninja_search_complete.js">ninja_search_complete.js</a>.</p>
<h3 id="using_passenger_to_server_local_libraries">Using Passenger to server local libraries</h3>
<p>The problem with loading local JavaScript libraries using the <code>file://</code> protocol, inferred earlier, is that it doesn&#8217;t work. So if I can&#8217;t load libraries using <code>file://</code> then I must use the <code>http://</code> protocol. That means I must route the requests through Apache/Ningx.</p>
<p>Fortunately there is a very simple solution: use <a href="http://www.modrails.com/">Phusion Passenger</a> which serves a &#8220;web app&#8217;s&#8221; <code>public</code> folder automatically. That&#8217;s why all the javascript, CSS and image assets have been placed in a folder <code>public</code> instead of <code>src</code> or <code>lib</code> or <code>javascript</code>.</p>
<p>On my OS X machine, I moved the repository folder into my <code>Sites</code> folder and wired up the folder as a Passenger web app using <a href="http://github.com/alloy/passengerpane/tree/master">PassengerPane</a>. It took 2 minutes and now I had <a href="http://ninja-search.local">http://ninja-search.local</a> as a valid base URL to serve my JavaScript libraries to my Greasemonkey script.</p>
<h3 id="testing_the_greasemonkey_scripts">Testing the Greasemonkey scripts</h3>
<p>I can only have one of the three Greasemonkey scripts installed at a time, so I install the <code>ninja-search.dev.user.js</code> file to check that everything is basically working inside a browser on interesting, foreign sites (outside of the unit test HTML pages).</p>
<p>Once I&#8217;ve deployed the JavaScript files and assets to the remote server I can then install the <code>ninja-search.user.js</code> file (<a href="http://drnic.github.com/ninja-search-js/dist/ninja-search.user.js">so can you</a>) and double check that I haven&#8217;t screwed anything up.</p>
<h3 id="deploying_via_github_pages">Deploying via GitHub Pages</h3>
<p>The normal, community place to upload and share Greasemonkey scripts is <a href="http://userscripts.org/">userscripts.org</a>. This is great for one file scripts, though if your script includes CSS and image assets, let alone additional JavaScript libraries, then I don&#8217;t think its as helpful, which is a pity.</p>
<p>So I decided to deploy the ninja-search-js files into the project&#8217;s own GitHub Pages site.</p>
<p>After creating the GitHub Pages site using <a href="http://github.com/blog/277-pages-generator">Pages Generator</a>, I then pulled down the gh-pages branch, and then linked (via submodules) that branch into my master branch as <code>website</code> folder.</p>
<p>Something like:</p>
<pre><code>
git checkout origin/gh-pages -b gh-pages
git checkout master
git submodule add -b gh-pages git@github.com:drnic/ninja-search-js.git website
</code></pre>
<p>Now I can access the gh-pages branch from my master branch (where the code is).</p>
<p>Then to deploy our Greasemonkey script we just copy over all the <code>public</code> files into <code>website/dist</code>, and then commit and push the changes to the gh-pages branch.</p>
<pre><code>
mkdir -p website/dist
cp -R public/* website/dist/
cd website
git commit -a "latest script release"
git push origin gh-pages
cd ..
</code></pre>
<p>Then you wait very patiently for GitHub to deploy your latest website, which now contains your Greasemonkey script (<code>dist/ninja-search.user.js</code>) and all the libraries (our actual code), stylesheets and images.</p>
<h3 id="summary">Summary</h3>
<p>Greasemonkey scripts might seem like small little chunks of code. But all code starts small and grows. At some stage you&#8217;ll wish you had some test coverage. And later you&#8217;ll hate yourself for ever having release the bloody thing in the first place.</p>
<p>I wrote all this up to summarise how I&#8217;d done TDD for the <a href="http://drnic.github.com/ninja-search-js/">Ninja Search JS</a> project, which is slightly different from how I added test cases to _why&#8217;s <a href="http://github.com/drnic/8cpj/tree/master">the octocat&#8217;s pajamas</a> greasemonkey script when I first started hacking with unit testing Greasemonkey scripts. The next one will probably be slightly different again.</p>
<p>I feel good about the current project structure, I liked Screw.Unit and blue-ridge, and I&#8217;m amused by my use of GitHub Pages to deploy the application itself.</p>
<p>If anyone has any ideas on how this could be improved, or done radically differently, I&#8217;d love to hear them!</p>
<h3 id="polish_your_rails_project_with_mocra">Polish your Rails project with Mocra</h3>
<p>I want to help you, your business, your boss and your project reach delightful levels of wickedly awesomeness. I’m so proud of the small team of ace Rails developers here at Mocra and what I know we can do for you.</p>
<p>Send an email to <a href="mailto:&#x72;&#x61;&#x69;&#x6C;&#x73;&#x40;&#x6D;&#x6F;&#x63;&#x72;&#x61;&#x2E;&#x63;&#x6F;&#x6D;">rails@mocra.com</a> about your current/future projects. Dare us to be more awesome!</p>
<p>While you wait for a reply perhaps you&#8217;d like to learn more about <a href="http://mocra.com/how-we-do-it/">How we do it</a> at <a href="http://mocra.com/">Mocra</a>?</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/07/04/nifty-threaded-im-chat-within-gtalkgmail-chat/' rel='bookmark' title='Permanent Link: Nifty Threaded IM Chat within Gtalk/Gmail Chat'>Nifty Threaded IM Chat within Gtalk/Gmail Chat</a> <small>Ever had IM chats where a conversation splits into multiple...</small></li><li><a href='http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/' rel='bookmark' title='Permanent Link: To WebKit or not to WebKit within your iPhone app?'>To WebKit or not to WebKit within your iPhone app?</a> <small> I know HTML. Its on my CV. Expert level....</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/06/07/tdd-for-greasemonkey-scripts-and-introducing-ninja-search-js/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Closing in on The Dream: &#8220;one-click-to-deploy Rails apps&#8221;</title>
		<link>http://drnicwilliams.com/2009/03/30/closing-in-on-the-dream-one-click-to-deploy-rails-apps/</link>
		<comments>http://drnicwilliams.com/2009/03/30/closing-in-on-the-dream-one-click-to-deploy-rails-apps/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 06:03:30 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=483</guid>
		<description><![CDATA[Got a simple app you want to build? Allocate 5 minutes for initial code generation, slice setup, and initial deployment. All from the command line. In one command. Booya! How long does it take to start a new Rails project? Surely just a moment? rails new_project -m path/to/some/template.rb But your application isn&#8217;t deployed yet. The [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/' rel='bookmark' title='Permanent Link: Dead simple JavaScript Unit Testing in Rails'>Dead simple JavaScript Unit Testing in Rails</a> <small> Formats: Video/Screencast (410 Mb, torrent) | Video only (vimeo)...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://img.skitch.com/20090330-8wwbeef7ngijh3qmu6g4ksr7ha.png" title="Logged in via twitter oauth" class="alignright" width="191" height="191" /></p>
<p>Got a simple app you want to build? Allocate 5 minutes for initial code generation, slice setup, and initial deployment. All from the command line. In one command. Booya!</p>
<p>How long does it take to start a new Rails project? Surely just a moment? <code>rails new_project -m path/to/some/template.rb</code></p>
<p>But your application isn&#8217;t deployed yet. The DNS isn&#8217;t ready, the remote slice doesn&#8217;t exist or the config for this new application isn&#8217;t setup. Heck, the code hasn&#8217;t even been pushed to a non-existent remote repository yet.</p>
<p>And what if you&#8217;re going to use something like twitter_auth for authentication? You&#8217;ll need to register your application with Twitter at <a href="http://twitter.com/oauth_clients">http://twitter.com/oauth_clients</a>.</p>
<p>All these things could be automated, surely. Surely?</p>
<p>If they were then you&#8217;d have a &#8220;one click&#8221; command. A new Rails app, pushed into production, and ready to rock and roll. Complete with either restful_authentication or twitter-based oauth integration.</p>
<h3 id="what_does_a_8220one_click8221_rails_and_deploy_command_look_like">What does a &#8220;one click&#8221; rails and deploy command look like?</h3>
<pre>cd Sites
rails -m rails-templates/mocra.rb default-twitter-auth-app

1. restful_authentication
2. twitter_auth
Which user authentication system? 2

1. mocra-primary
2. mocra-secondary
3. crazy-pron-sites
Install http://default-twitter-auth-app.mocra.com application on which slice? 3^H1

1. drnic
2. mocra
Which twitter user?  1
</pre>
<p><strong>Then you wait 3 minutes and 53 seconds.</strong></p>
<div style="margin-left: 30px;">
<p><a href="http://img.skitch.com/20090330-m19kq398xd47cefxu5wcxbp1d5.png"><img alt="" src="http://img.skitch.com/20090330-xjk5rhx5sgkbh22tfqxrfib3i6.png" title="1" class="alignleft" width="152" height="150" style="background-color: #FFFBCC; padding: 5px; margin: 2px; "/></a></p>
<p><a href="http://img.skitch.com/20090330-m46w5d9hqqcp87yx75bwr71ku6.png"><img alt="" src="http://img.skitch.com/20090330-m6p457erdaj14c162kth3a8m5p.png" title="2" class="alignleft" width="150" height="150" style="background-color: #FFFBCC; padding: 5px; margin: 2px" /></a></p>
<p><a href="http://img.skitch.com/20090330-83miatnsgiu6mjw66f4jaip314.png"><img alt="" src="http://img.skitch.com/20090330-8wwbeef7ngijh3qmu6g4ksr7ha.png" title="3" class="alignleft" width="150" height="150" style="background-color: #FFFBCC; padding: 5px; margin: 2px" /></a>
</div>
<p>Then you visit <a href="http://default-twitter-auth-app.mocra.com">http://default-twitter-auth-app.mocra.com</a> and it is working. You click the &#8220;Protected&#8221; link and you are redirected to Twitter to click the &#8220;Allow&#8221; link. You return to the app. You are registered with an account and logged in. You see your own face. You rock.</p>
<p>The rest of the article shows you how to test run it yourself, explain the dependencies and how to install them, and how to unit test your own templates to do similarly fancy things. Hopefully its helpful.</p>
<h3 id="waiting_a_minute_is_tutorial_destructive_to_my_precious_slices">WAITING A MINUTE &#8211; is this tutorial destructive to my precious slices?</h3>
<p>It is safe. <strong>IF you have an existing slicehost slice that was created with the latest deprec gem.</strong></p>
<p>Perhaps backup your slice anyway. But it should be safe. </p>
<p>Deprec installs each application in its own folder and the apache settings are in their own file etc. But when deprec installs apache, passenger, etc it <em>may</em> put them in places you aren&#8217;t expecting. It might not. I just can&#8217;t promise anything.</p>
<h3 id="testimonial_that_the_tutorial_works">Testimonial that the tutorial works</h3>
<p>Ryan Bigg offers the following testimonial to encourage you to actually try out the tutorial:</p>
<blockquote><p>&#8220;I have, dear readers, with as little effort as a few keystrokes, an an application base that allows my users to sign up using their twitter credentials. I have my code base here on my machine, and the running application in production over there at <a href="http://ryan.mocra.com">http://ryan.mocra.com</a>&#8221; Ryan Bigg (<a href="http://github.com/radar">radar</a>)</p></blockquote>
<h3 id="required_gems_for_the_template">Required gems for the template</h3>
<p>There are a couple of one-time-only steps to run to install some gems and setup github and slicehost API keys locally.</p>
<pre>gem install highline
gem install deprec
gem install defunkt-github --source http://gems.github.com
gem install booster-slicehost-tools --source=http://gems.github.com
</pre>
<p>To setup the github gem with your API key:</p>
<pre>* login to [http://github.com/](http://github.com/)
* click [account](https://github.com/account)
* click "Global Git Config"
* copy and paste the two lines of config into the terminal to install the config
</pre>
<p>The github gem will now use this configuration automatically.</p>
<p>To setup the slicehost gem with your API key:</p>
<p>slicehost-slice list<br />
   Please enter your API key since you did not provide one: </p>
<p>To get your slicehost API:</p>
<ul>
<li>login to <a href="https://manage.slicehost.com">https://manage.slicehost.com</a></li>
<li>click &#8220;Account&#8221;</li>
<li>click <a href="https://manage.slicehost.com/api/">API Access</a></li>
<li>click &#8220;Enable API Access&#8221;</li>
<li>copy + paste the API Password into the terminal above</li>
</ul>
<h3 id="required_gems_and_steps_for_using_twitter_auth">Required gems and steps for using twitter_auth</h3>
<p>My fork of the twitter gem includes a <code>twitter register_oauth ...</code> command. If John integrates the code, or writes his own, I&#8217;ll drop my fork and rewrite my template to use his gem. Til then use this one.</p>
<pre>gem install drnic-twitter --source=http://gems.github.com
twitter install
twitter add
</pre>
<p>And enter your twitter account details. You can run the last command any number of times to add personal and corporate/product twitter accounts. I am really impressed with the internals of this gem &#8211; it stores your data in a sqlite3 gem and uses ActiveRecord models to retrieve it. Might create a generator for this in newgem. I also liked the use of the <code>main</code> gem for its command definition. Anyway, we&#8217;re off the topic.</p>
<h3 id="cloning_and_running_the_rails_templates">Cloning and running the rails-templates</h3>
<p>Imagine the above steps were &#8220;Buy an Xbox 360. Buy Guitar Hero.&#8221; Now its the final step. It&#8217;s time to rock.</p>
<pre>cd ~/Sites
git clone git://github.com/drnic/rails-templates.git
DOMAIN=yourdomain.com ORGANIZATION="Your Company of Legends" rails -m rails-templates/mocra.rb my_app
</pre>
<p>A few minutes later you can open <a href="http://my-app.yourdomain.com">http://my-app.yourdomain.com</a> in a browser. It will have <a href="http://github.com/technoweenie/restful-authentication/tree/master">restful_authentication</a>  or twitter oauth integration all setup and working (except email settings for restful_authentication).</p>
<p>It makes me very happy watching it work.</p>
<p>If the above command has stalled after printing &#8216;executing  slicehost-slice list&#8217; then you haven&#8217;t set up your slicehost API key. See the instructions above.</p>
<h3 id="dirty_nasty_assumptions">Dirty, nasty assumptions?</h3>
<p>How can you deploy an entire app and have it up and running without some more configuration? Surely&#8230; surely I&#8217;ve made some nasty assumptions and come up with some dirty defaults?</p>
<p>Yes.</p>
<p>Your application url will be <code>my-app-name.mocra.com</code>. The subdomain is a dasherized version of your application&#8217;s folder name. Use <code>DOMAIN=mycompany.com</code> to change the domain.</p>
<p>Your local and remote database is mysql, accessible with user <code>root</code> and no password. I&#8230; look&#8230; you see there was this dog&#8230; and he ate my homework&#8230; it wasn&#8217;t me&#8230; there was an earthquate, a volcano, a flood&#8230; it wasn&#8217;t me!</p>
<p>You are deploying to slicehost. I do. It has command-line applications to manage slices and DNS. Since I&#8217;m deploying to a subdomain of mocra.com I use slicehost to create a CNAME in the DNS.</p>
<p>Your target slice already exists and has been built using the latest <a href="http://deprec.failmode.com/">deprec</a>. The template let&#8217;s you select an existing slicehost slice to use. If you don&#8217;t have one that was built with deprec, perhaps create a new one.</p>
<p>Gems? Plugins? Yes this template installs the ones that I want. That&#8217;s the point of rails templates &#8211; you create your own set of defaults.</p>
<h3 id="what_do_i_do_to_get_my_own_uber_template">What do I do to get my own uber-template?</h3>
<p>Copy + paste the <em>mocra.rb</em> template and hack in your configuration. Fork the github project and push up your file so others can see your awesomeness. </p>
<p>See the section on unit testing templates too.</p>
<h3 id="what8217s_missing">What&#8217;s missing?</h3>
<p>The primary thing that I want that I haven&#8217;t gotten around to writing/fixing/finding a solution is the creation of private, company github projects. That is, instead of public/open-source, personal projects using <code>github create-from-local</code>.</p>
<p>I guess I would want a <code>github create-from-local --private</code> flag to create a private repo instead of a public repo.</p>
<p>Then I&#8217;d want the github gem to know that I live in a world of multiple github accounts: my personal account (<a href="http://github.com/drnic/">drnic</a>) and my company&#8217;s account (<a href="http://github.com/mocra/">mocra</a>). That is, I&#8217;ll want new private company projects to go on the company account.</p>
<p>And then I&#8217;ll want it to add me (drnic) as a collaborator. Or a whole group of people.</p>
<p>Since the github gem currently derives its user + API token information from your global git config (<code>git config --get github.user</code>), instead of a nice external sqlite3 database like the twitter gem, I&#8217;m not sure what the best/correct data structure would be to add multiple user support to the github gem. </p>
<p>Or perhaps the <code>github create-from-local</code> mechanism should be extracted out of the github gem all together into a <code>github-admin</code> gem which would have multiple users, create public/private repos, add collaborators etc. Yeah, that might be better.</p>
<h3 id="want_a_default_application_theme">Want a default application theme?</h3>
<p>The template will attempt to invoke a generator <code>app_layout</code> if it can find it. Watch the <a href="http://railscasts.com/episodes/58-how-to-make-a-generator">railscast on generators</a> for an example of how to create a local generator and he gives an example of creating a default application theme generator. That&#8217;s why all the railscasts applications look the same!</p>
<h3 id="bonus_section_unit_testing_a_rails_template">Bonus section: unit testing a Rails template</h3>
<p>If you look in the rails-templates project you cloned you&#8217;ll see a <em>spec</em> folder. There is a mock <em>template_runner.rb</em> which is used by the <em>spec/mocra/template_spec.rb</em>. This way I can stub out calls to command-line tools like <code>slicehost-slice list</code> and <code>twitter register_oauth</code> and check that the template installs the correct plugins, creates the correct files, etc without actually installing or creating anything.</p>
<p>More importantly its a lot bloody faster to run than the full template.</p>
<p>If you&#8217;re creating Rails templates with interesting logic in them then writing some unit tests for your template might be a helpful idea to save time.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2010/03/15/using-coffeescript-in-rails-and-even-on-heroku/' rel='bookmark' title='Permanent Link: Using CoffeeScript in Rails and even on Heroku'>Using CoffeeScript in Rails and even on Heroku</a> <small>I&#8217;m pretty excited about CoffeeScript as a clean-syntax replacement for...</small></li><li><a href='http://drnicwilliams.com/2009/11/12/dead-simple-javascript-unit-testing-in-rails/' rel='bookmark' title='Permanent Link: Dead simple JavaScript Unit Testing in Rails'>Dead simple JavaScript Unit Testing in Rails</a> <small> Formats: Video/Screencast (410 Mb, torrent) | Video only (vimeo)...</small></li><li><a href='http://drnicwilliams.com/2009/11/03/first-look-at-rails-3-0-pre/' rel='bookmark' title='Permanent Link: First look at rails 3.0.pre'>First look at rails 3.0.pre</a> <small> This article is out of date in some aspects....</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/03/30/closing-in-on-the-dream-one-click-to-deploy-rails-apps/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>RailsCamp.au #5 &#8211; book now</title>
		<link>http://drnicwilliams.com/2009/02/22/railscampau-5-book-now/</link>
		<comments>http://drnicwilliams.com/2009/02/22/railscampau-5-book-now/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 03:24:01 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Mocra]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=466</guid>
		<description><![CDATA[Imagine yourself and a posse of like-minded Ruby hackers on a country retreat with zero internet for a weekend of fun. You&#8217;ll laugh, hack, learn, cry (well, you probably won’t cry… but you know… it felt poetic) and most likely play a crap-load of guitar hero. [manifesto] In chronological order, the first RailsCamps in Australia [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/07/09/web-directions-south-workshop/' rel='bookmark' title='Permanent Link: I Still Call Australia Home'>I Still Call Australia Home</a> <small>On the 25th of September I&#8217;m doing a one-day workshop...</small></li><li><a href='http://drnicwilliams.com/2007/04/26/introducing-myconfplan/' rel='bookmark' title='Permanent Link: Railsconf &#8211; the sessions I&#8217;ll be attending'>Railsconf &#8211; the sessions I&#8217;ll be attending</a> <small> http://myconfplan.com/conferences/RailsConf2007/users/drnic This is a new site called MyConfPlan, built...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://railscampau.github.com"><img alt="" src="http://railscampau.github.com/images/yield.png" title="Yield" class="alignright" width="247" height="166" /></a></p>
<blockquote><p>Imagine yourself and a posse of like-minded Ruby hackers on a country retreat with zero internet for a weekend of fun. You&#8217;ll laugh, hack, learn, cry (well, you probably won’t cry… but you know… it felt poetic) and most likely play a crap-load of guitar hero. [<a href="http://railscamp08.org/" title="Rails Camps">manifesto</a>]</p></blockquote>
<p>In chronological order, the first RailsCamps in Australia were in the states: New South Wales, Victoria, New South Wales, and South Australia. </p>
<p>This time, between May 15th and 18th, it&#8217;s in Queensland. God&#8217;s Country. The Sunshine State. Home of <a href="http://en.wikipedia.org/wiki/Steve_Irwin">Steve Irwin</a> (deceased), <a href="http://en.wikipedia.org/wiki/Joh_Bjelke-Petersen">Sir Joh Bjelke-Petersen</a> (deceased), <a href="http://en.wikipedia.org/wiki/Greg_Norman">Greg Norman</a> (expat), <a href="http://images.google.com.au/images?hl=en&amp;client=firefox-a&amp;rls=org.mozilla:en-US:official&amp;q=Keith%20Urban%20Nicole%20Kidman&amp;um=1&amp;ie=UTF-8&amp;sa=N&amp;tab=wi">Keith Urban</a> (expat), and <a href="http://images.google.com.au/images?q=Kristy%20Hinze&amp;oe=utf-8&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a&amp;um=1&amp;ie=UTF-8&amp;sa=N&amp;hl=en&amp;tab=wi">Kristy Hinze</a> (marrying ex-Silicon Graphics/ex-Netscape billionaire Jim Clark; expat). So its a pretty famous and popular place to come from.</p>
<p><a href="http://www.flickr.com/photos/lachlanhardy/3045076837/" title="More Mexican (by Lachlan Hardy)"><img title="More Mexican (by Lachlan Hardy)" class="alignright" src="http://farm4.static.flickr.com/3016/3045076837_f1ff415033_m.jpg" alt="More Mexican (by Lachlan Hardy)" width="240" height="160"></a></p>
<p><a href="http://railscampau5.eventwax.com/rails-camp-5/register">Book your tickets now</a> for <a href="http://railscampau.github.com">RailsCamp #5</a>.</p>
<p><span id="more-466"></span></p>
<ul>
<li>Date: May 15-18 2009</li>
<li>Cost: $164</li>
<li>Where: <a href="http://www.koonjewarre.com/index.html">Koonjewarre Retreat Centre</a>, Gold Coast Hinterland, Queensland</li>
<li>Airport: Gold Coast Airport, Coolangatta</li>
<li>Website for bookings: <a href="http://railscampau.github.com/" title="RailsCamp.au 5 - May 15-18th 2008">http://railscampau.github.com/</a>
</ul>
<h3 id="foreigners_and_railscampau">Foreigners and RailsCamp.au</h3>
<p>There is no official foreigners policy. More generally, there aren&#8217;t too many policies on anything for RailsCamps. Its noteworthy that we&#8217;re a country founded 200 years ago on Britain&#8217;s primary export in the 1800s: shoplifters. So we&#8217;ll accept just about anyone. If you can get through Customs and Quarantine into our country, then we&#8217;ll let you come to RailsCamp. </p>
<p>Since RailsCamp.au starts just after RailsConf finishes, it would seem like an idea back-to-back &#8220;working&#8221; holiday. If you arrive early into Brisbane we&#8217;ll find you some office space to hang out in, or we&#8217;ll point you in the direction of some places to go touristing.</p>
<p>RailsCamp tickets sell out faster than RailsConf tickets, so <a href="http://railscampau.github.com/">decide fast</a>.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/07/09/web-directions-south-workshop/' rel='bookmark' title='Permanent Link: I Still Call Australia Home'>I Still Call Australia Home</a> <small>On the 25th of September I&#8217;m doing a one-day workshop...</small></li><li><a href='http://drnicwilliams.com/2007/04/26/introducing-myconfplan/' rel='bookmark' title='Permanent Link: Railsconf &#8211; the sessions I&#8217;ll be attending'>Railsconf &#8211; the sessions I&#8217;ll be attending</a> <small> http://myconfplan.com/conferences/RailsConf2007/users/drnic This is a new site called MyConfPlan, built...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2009/02/22/railscampau-5-book-now/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Migrating project websites to github pages with sake tasks, new websites with jekyll_generator</title>
		<link>http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator/</link>
		<comments>http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator/#comments</comments>
		<pubDate>Sun, 21 Dec 2008 13:25:21 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Gems]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/?p=380</guid>
		<description><![CDATA[Its almost Christmas time and that means presents. It also means that sometime between today and December 25th you need to go out and buy other people some presents because you haven&#8217;t done it yet. But there&#8217;s someone else special in your life that deserves an Xmas gift this year. That special someone is your [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2009/11/04/hacking-someones-gem-with-github-and-gemcutter/' rel='bookmark' title='Permanent Link: Hacking someone&#8217;s gem with github and gemcutter'>Hacking someone&#8217;s gem with github and gemcutter</a> <small> Ever used a rubygem, found a bug, and just...</small></li><li><a href='http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/' rel='bookmark' title='Permanent Link: Future proofing your Ruby code. Ruby 1.9.1 is coming.'>Future proofing your Ruby code. Ruby 1.9.1 is coming.</a> <small> Bugger. I&#8217;m a Ruby monogamist. I use the Ruby...</small></li><li><a href='http://drnicwilliams.com/2008/10/31/newgem-100-all-thanks-to-cucumber/' rel='bookmark' title='Permanent Link: newgem 1.0.0 all thanks to Cucumber'>newgem 1.0.0 all thanks to Cucumber</a> <small>The New Gem Generator (newgem) was exciting, moderately revolutionary, and...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://france.worldcupblog.org/files/2007/12/christmas-presents.jpg" title="Christmas present" class="alignright" width="300" height="278" /></p>
<p>Its almost Christmas time and that means presents.</p>
<p>It also means that sometime between today and December 25th you need to go out and buy other people some presents because you haven&#8217;t done it yet.</p>
<p>But there&#8217;s someone else special in your life that deserves an Xmas gift this year. That special someone is your open source projects.</p>
<p>You might think, &#8220;But, Dr Nic, what do I get for the open source project that already has everything? What gift would my open source projects possible appreciate?&#8221;</p>
<p>Its true &#8211; this year has been a boon for open source. You probably migrated your projects from SVN to Git this year. Specifically, you probably clicked the &#8220;create a new one&#8221; link on your GitHub home page a lot this year: either to migrate your old projects to github or start new ones. Lots of new ones.</p>
<p>And now that your code is on github, your README file is rendered beautifully on the home page, so you were more inclined to rename it to README.markdown or README.textile and thusforthly fill it full of education information about your projects. </p>
<p>More people would then instantaneously figure out what the f@#$ your project actually does, <strong>thus</strong> more people used it, <strong>thus</strong> more people wrote patches or forked your code and sent Pull Requests. </p>
<p>All round, in 2008, I bet your open source projects had a sweet year. </p>
<p>Nonetheless, it is Christmas time and you should now get them a present. Something they wouldn&#8217;t get for themselves. Something you wouldn&#8217;t have done for them except for the free loving spirit of Christmas.</p>
<h3>The Gift for all Open Source projects</h3>
<p><a href="http://drnic.github.com/macruby-tmbundle/"><img alt="" src="http://img.skitch.com/20081221-trfsetaeesnnk4p5u5i35yxckd.png" title="Sample website" class="alignright" width="358" height="216" /></a></p>
<p><strong>A website.</strong></p>
<p>Oh sure, github renders your README.markdown file. Yeah, yeah, github gives you a wiki for your project. Sure, sure, Google Groups let you communicate with your co-developers and users. Certainly, you don&#8217;t <em>need</em> a website for your project.</p>
<p>That&#8217;s why its a Christmas gift. You&#8217;re going to do it because you care.</p>
<p>Websites sell your project. READMEs and Wikis educate. The project website will sell it and make people want to use your stuff.</p>
<p>A website could have a blog with an RSS/atom feed. Then you could post updates about your project. People could subscribe and also leave comments. Oh the novelty.</p>
<p>And if it only took 5 minutes to get all this setup &#8211; the website code, the blog engine, the RSS feed, the comments, and published to its own hosted server &#8211; then that would just be oh so sweet.</p>
<p>So we&#8217;re going to do some craft for our Xmas present. A little DIY project, if you will. You&#8217;ll need a few things that you&#8217;ll find around your house, a command-line interface, and a beer or perhaps some port or sherry. Christmas cake is good too.</p>
<p><span id="more-380"></span></p>
<p>The commands below take about 5 minutes to execute and you&#8217;ll have a sweet website for your project, setup on GitHub Pages, just like the <a href="http://drnic.github.com/macruby-tmbundle/">macruby-tmbundle</a> and <a href="http://drnic.github.com/jekyll_generator/">jekyll_generator</a> sites, and the sample image above.</p>
<h3>Jekyll and GitHub Pages</h3>
<p><a href="http://github.com/mojombo/jekyll/">Jekyll</a>, by Tom Preston-Werner, is one of several static website generators. All your website content will be written in textile or markdown, rendered against some HTML layouts, and published on a website somewhere. We&#8217;re going to use <a href="http://github.com/blog/272-github-pages">GitHub Pages</a> because they are new and shiny, and free, and I&#8217;ve written some sake tasks (below) to make it all easy peasy to get up and running.</p>
<p>There are a bunch of reasons we&#8217;re going to use Jekyll to render our website:</p>
<p><a href="http://drnic.github.com/macruby-tmbundle/2008/12/19/running-macruby-inside-textmate.html"><img alt="" src="http://img.skitch.com/20081221-gkweyr5rq32frgfawhd17cpm5r.png" title="disqus - javascript comment system for static blog sites" class="alignright" width="316" height="322" /></a></p>
<p>One, textile and markdown are much nicer to write/edit text than HTML.</p>
<p>Two, Jekyll is &#8220;blog enabled&#8221;. That is, some of your pages will be specifically &#8220;blog post&#8221; pages, and elsewhere in your layout you can programmatically list them. Like a blog. Yeah.</p>
<p>Three, GitHub Pages automatically supports Jekyll but no other static-website generators. This saves you from having to manually render your HTML from your Textile/Markdown pages before pushing the site to the remove server.</p>
<p>Four, I wrote a stand-alone generator to create a Jekyll website for any project. It is preconfigured with <a href="http://disqus.com/">Disqus</a> for comments, including badges for latest comments etc. </p>
<h2 id="living-with-jekyll">Living with a Jekyll</h2>
<p>Jekyll comes as a RubyGem:</p>
<pre>sudo gem source -a http://gems.github.com/
sudo gem install mojombo-jekyll
</pre>
<p>You can either read the Jekyll <a href="http://github.com/mojombo/jekyll/tree/master#readme">README</a> and create your project website by hand (and then skip below to <a href="#living-with-github-pages">Living with GitHub Page</a>).</p>
<p>Alternately, you can cheat and use a generator.</p>
<h3>jekyll_generator</h3>
<p>For the last few years, newgem has come with the ability to create a website for your project. For the jekyll_generator I decided to go with a separate generator so that any project &#8211; rubygem, rails plugin, javascript project, etc &#8211; can easily use it.</p>
<pre>sudo gem install jekyll_generator
cd path/to/project
jekyll_generator website --title "Project Name"
cd website
jekyll
open _site/index.html</pre>
<p>The final steps performs the local rendering of your website (<code>jekyll</code>) and then on OS X it opens the rendered website into your browser. Otherwise, manually open the index.html from the _site folder.</p>
<p>Currently the generator assumes that your project is already in a git repository that is hosted on github (specifically that you&#8217;ve added the github project as the origin remote).</p>
<h2 id="living-with-github-pages">Living with GitHub Pages</h2>
<p>GitHub recently released <a href="http://github.com/blog/272-github-pages">GitHub Pages</a> as a place for you to publish a personal website and websites for each of your projects. Instead of requiring you to rsync or &#8220;rake website&#8221; your way to publishing glory, you just use git.</p>
<p>Specifically, you put your website in a branch called &#8220;gh-pages&#8221;. When you push commits in that branch to github it will automatically refresh your website. No rsyncing required. Also, it will run your website through Jekyll. </p>
<p>So much delicious magic.</p>
<p>Except our website is not currently in another branch. Its in master. In a folder called <code>website</code>. Where it should be.</p>
<p>But the boffins at github say we need to move our shit across to a branch called <cide>gh-pages</code>, and who are we to argue.</p>
<p>I personally will never be doing this migration manually. I figured it out once and slapped it into a sake task. It moves all the content in your website folder into this branch, and replaces it with a submodule link so you can access the website from your master branch. Didn't follow that? No, me neither. Let's just run the sake task and move on with our lives, and eat fresh prawns and Christmas pudding.</p>
<h3>Sake tasks to get started with GitHub Pages</h3>
<p>To install them from scratch (<a href="http://drnicwilliams.com/2008/08/19/my-attempt-at-sake-task-management/">initial blog post</a>):</p>
<pre>sudo gem install sake
cd /tmp
git clone git://github.com/drnic/sake-tasks.git
cd sake-tasks
rake install:all</pre>
<p>You can toss away the repo after installing the sake tasks.</p>
<p>You now have some tasks to manage <a href="http://github.com/drnic/sake-tasks/tree/master/github/pages">github:pages</a>:</p>
<pre>sake github:pages:migrate_website   # Migrates an existing website folder into a gh-pages branch, and links back as submodule
sake github:pages:setup             # Creates the gh-pages branch, and links to it as 'website' as submodule</pre>
<p>Since we've already created the website above, we're going to use the first task to migrate this folder into the required gh-pages branch.</p>
<pre>sake github:pages:migrate_website</pre>
<p>Um, and your done.</p>
<p>Note, if sake crashes and burns in your project it might be that you don't have a Rakefile. Try, "touch Rakefile" and rerun the sake command.</p>
<p>In 1-10 minutes your fancy new site will appear at <a href="http://drnic.github.com/macruby-tmbundle">http://username.github.com/projectname</a>. It even has a complimentary first blog post. You might want to change it to something useful.</p>
<p>You can now update your website via your website folder, commit changes and they automatically appear, automatically rendered via Jekyll, on your website. </p>
<h3>Disqus for comments</h3>
<p>Since your new website is static text there is no way to support comments on the blog posts. I've bundled into the theme's layouts the access code for Disqus. Like the image above, each blog post has Disqus comments at the bottom, and the sidebar shows the latest comments from all your blog posts.</p>
<p>You need to create a Disqus account, and <a href="http://disqus.com/add/">create a project</a> with the same name as your github project name. For example, if <code>jekyll_generator</code> is the project name on github, then make it the name on Disqus.</p>
<p><img alt="" src="http://img.skitch.com/20081221-1j37b58t1t69xxn8k2a3jx98q3.png" title="new disqus project" width="525" height="270" /></p>
<p>In my example above, my github project name was <code>jekyll_generator</code> but I couldn't use underscores on Disqus, so it is <code>jekyll-generator</code>. Fortunately, the generator templates already know this, and have converted your underscored name to hyphens already.</p>
<p>You can skip the "Choose your platform to install" steps as this is all done by the generator templates.</p>
<p>If you reload your project's website it should have Disqus badges on the sidebar, and the posts should have comment boxes.</p>
<h3>Lighthouse for tickets</h3>
<p>Lighthouse offers free access for open source projects to track their bugs. After you've created your Lighthouse project, you need to change the TODO values in <code>_layouts/default.html</code> and <code>_layouts/post.html</code> to your Lighthouse project number.</p>
<p><img alt="" src="http://img.skitch.com/20081221-f6fuha9emjecfuebbyncsaufm9.png" title="lighthouse url details" width="498" height="58" /></p>
<h3>Updating your website</h3>
<p>Your website now appears within your project source under the website folder. Though if you change it, add new posts, etc, you won't be able to commit the changes back normally. The contents of the website folder are effectively another git repository.</p>
<p>To commit changes to your website, go into the website folder and proceed normally:</p>
<pre>project(master) $ cd website
project/website(gh-pages) $ git commit -m "some changes"
project/website(gh-pages) $ git push origin gh-pages
project/website(gh-pages) $ cd ..
project(master) $</pre>
<p>Now your submodule may be dirty and need updating:</p>
<pre>git submodule update --init</pre>
<p>Not sure what this is all about.</p>
<h3>Summary</h3>
<p>A website is a great way to show that your pride and joy isn't ignored by new visitors and reminds existing users just how awesome the project is, and by clever association, how awesome you are.</p>
<p>A sexy website has to be even better.</p>
<p>Jekyll is great, and the Github Pages concept seems fun. Perhaps it wouldn't be necessary if the Github Wiki content was available as its own git repo, or if you could theme your project's source browser like a diry MySpace page.</p>
<p>Hopefully the sake tasks make migration of any existing websites to the Github Pages system easy peasy, and hopefully the jekyll_generator is useful for any new projects.</p>
<p>Hopefully.</p>
<p>Merry Christmas.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2009/11/04/hacking-someones-gem-with-github-and-gemcutter/' rel='bookmark' title='Permanent Link: Hacking someone&#8217;s gem with github and gemcutter'>Hacking someone&#8217;s gem with github and gemcutter</a> <small> Ever used a rubygem, found a bug, and just...</small></li><li><a href='http://drnicwilliams.com/2008/12/11/future-proofing-your-ruby-code/' rel='bookmark' title='Permanent Link: Future proofing your Ruby code. Ruby 1.9.1 is coming.'>Future proofing your Ruby code. Ruby 1.9.1 is coming.</a> <small> Bugger. I&#8217;m a Ruby monogamist. I use the Ruby...</small></li><li><a href='http://drnicwilliams.com/2008/10/31/newgem-100-all-thanks-to-cucumber/' rel='bookmark' title='Permanent Link: newgem 1.0.0 all thanks to Cucumber'>newgem 1.0.0 all thanks to Cucumber</a> <small>The New Gem Generator (newgem) was exciting, moderately revolutionary, and...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
