<?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; Programming</title>
	<atom:link href="http://drnicwilliams.com/category/programming/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>Thu, 25 Feb 2010 11:39:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Installing Mingle with Capistrano/Deprec</title>
		<link>http://drnicwilliams.com/2007/11/27/installing-mingle-with-capistranodeprec/</link>
		<comments>http://drnicwilliams.com/2007/11/27/installing-mingle-with-capistranodeprec/#comments</comments>
		<pubDate>Mon, 26 Nov 2007 23:20:18 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Capistrano]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2007/11/27/installing-mingle-with-capistranodeprec/</guid>
		<description><![CDATA[The other day I visited the ThoughtWorks office in Melbourne (they hosted the Melb Ruby meeting). The most notable feature of their office versus any office I&#8217;ve ever worked in before were the 5&#215;3 cards (and post-it notes) &#8230; all over the walls.
From my understanding &#8211; which came after asking lots of questions &#8211; is [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I visited the ThoughtWorks office in Melbourne (they hosted the Melb Ruby meeting). The most notable feature of their office versus any office I&#8217;ve ever worked in before were the 5&#215;3 cards (and post-it notes) &#8230; all over the walls.</p>
<p>From my understanding &#8211; which came after asking lots of questions &#8211; is that the cards help with:</p>
<ul>
<li>The team (developers, clients, etc) deciding what parts of the application are most important to be built. The cards are isolated stories/use cases and should implicitly/explicitly state the business value. At each stage of the project &#8211; &#8220;iterations&#8221; which are 1 or 2 week long &#8211; the team decides which cards/stories should be implemented.</li>
<li>The cards for an iteration are placed on the wall. Thus it is transparent to all the team what work is being performed.</li>
<li>From left to right, the wall is divided into columns. Each card can be placed in one column. Columns are typically labelled with stage names like &#8220;Under development&#8221;, &#8220;Completed&#8221;, &#8220;QA/Testing&#8221;, &#8220;Accepted&#8221;. This gives a visualisation of what work/card is where in the development/release process. It can also indicate if there is a bottleneck &#8211; a lot of cards in the &#8220;QA/Testing&#8221; column might mean you need more testers.</li>
</ul>
<p>The first point &#8211; using stories on cards to decide what should be built now &#8211; seemed like a winning idea. A new client of mine has trouble translating a gazillion feature requests into a sequence of &#8220;this part should be built now&#8221; stages. Everything is uber cricital, all the time. And often the feature requests don&#8217;t seem related to something a user might actually want to use.</p>
<p>Whilst cards on a wall would work if the client and developers were co-located (aka &#8220;sitting together&#8221;), that&#8217;s not the situation here. I&#8217;m in Brisbane, and they are in Sydney (1000km).</p>
<p>With colourful 5&#215;3 cards and the promise of fruitful client relationships burned into my retina I wondered what web tools might help with emulating this process. The cards. The wall. The transparency. The understanding that &#8220;software costs money to build so what is most important?&#8221;</p>
<p>And I remembered <a href="http://studios.thoughtworks.com/mingle-project-intelligence">Mingle</a> &#8211; a tool built by ThoughtWorks for agile project development, but not (to my knowledge) used by any ThoughtWorks teams themselves. UPDATE: Jay Fields says several teams are currently using it.</p>
<p>But I can understand why they don&#8217;t use it. They have their own 5&#215;3 cards with their &#8220;ThoughtWorks&#8221; logo on it. Well, they had some. I stole a bunch. They also have walls and co-location. </p>
<p>Nonetheless, I gave it a burl. I runs nicely when the server is installed on my CoreDuo 2gig MacBook. It didn&#8217;t run nicely at all on my 256Mb VPS that was already busy running a bunch of other things (mongrels, mysql, etc).</p>
<p>Mingle requires 2 gig of RAM. Even on the ever affordable Slicehost, that&#8217;s $140 USD a month. Mingle might be free for < 5 users (and OSS projects) but there is a notable hardware requirement, thanks I guess to the Java/JRuby/Rails stack.</p>
<p>But I've done something useful - I've written capistrano/deprec recipies to install Mingle on a remote machine with (minimal) manual intervention. You just need to choose a machine with 2G RAM spare. You also need Java and MySQL installed, but there are capistrano tasks to help with that too.</p>
<p>Ahh, the world of remote automation.</p>
<p>The recipe below is mostly *nix agnostic, except the <code>java_install</code> task which uses ubuntu/debian's <code>apt-get</code> system. Actually, it tells you what to manually run yourself, as Sun are tools and require you to "click" the word "Yes" twice. I don't know how to automate this with Capistrano.</p>
<p>The <code>mingle_install</code> task downloads and installs Mingle, and includes an JVM optimisation option that I found on the forums (the MingleServer.vmoptions file created).</p>
<p>So, from scratch, if you want to install Mingle on a remote server (independently of any Rails app etc), do the following:</p>
<pre>
sudo gem install deprec -v 1.9.1
alias cap1='cap _1.4.1_'
mkdir -p mingle_installer/config
cd !$
vim deploy.rb
</pre>
<p>And insert the following into the deploy.rb script.</p>
<textarea name="code" class="ruby" cols="60" rows="10">
require 'deprec/recipes'
role :scm, "YOURDOMAIN"
set :user, "mingle"

set :mingle_path, "/var/www/apps/mingle"
set :mingle_data_path, "#{mingle_path}/data"
set :mingle_port, 8080
set :mingle_src_version, 'mingle_unix_1_1_5169'
set :mingle_src_package, {
  :file => mingle_src_version + '.tar.gz',   
  :dir => "mingle",  
  :url => "http://studios.thoughtworks.com/mingle/download/#{mingle_src_version}.tar.gz",
  :unpack => "tar zxf #{mingle_src_version}.tar.gz;"
}

desc "Install Mingle"
task :mingle_install, :roles => :scm do
  puts "Checking that Java is installed..."
  run "test -x '/usr/bin/java'"
  puts "Checking that MySQL is installed..."
  run "test -x '/usr/bin/mysqladmin'"
    
  deprec.download_src(mingle_src_package, src_dir)
  deprec.install_from_src(mingle_src_package, src_dir)

  deprec.mkdir mingle_data_path, :user => user
  template = <<-EOS
mingle.port=<%= mingle_port %>
mingle.dataDir=<%= mingle_data_path %>
  EOS

  mingle_install_path = "#{src_dir}/#{mingle_src_package[:dir]}"
  tmp_conf = "/tmp/mingle.properties"
  put ERB.new(template,0, "%<>").result(binding), tmp_conf
  sudo "mv #{tmp_conf} #{mingle_install_path}/mingle.properties", :as => user
  
  tmp_vmoptions = "/tmp/MingleServer.vmoptions"
  put "-Xmx1024m -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:MaxPermSize=256m", tmp_vmoptions
  sudo "mv #{tmp_vmoptions} #{mingle_install_path}/MingleServer.vmoptions", :as => user

  mysql.create_database('mingle', user)

end

desc "Start the Mingle server"
task :mingle_start, :roles => :scm do
  mingle_install_path = "#{src_dir}/#{mingle_src_package[:dir]}"
  run_with_input "su - #{user} -c '#{mingle_install_path}/MingleServer start'"
  
  mingle_domain = roles[:scm].first.host
  puts "Open browser to http://#{mingle_domain}:#{mingle_port}"
end

desc "Stop the Mingle server"
task :mingle_stop, :roles => :scm do
  mingle_install_path = "#{src_dir}/#{mingle_src_package[:dir]}"
  run "#{mingle_install_path}/MingleServer stop"
end


desc "Install Java"
task :java_install do
  enable_multiverse
  puts <<-EOS
  Run the following commands on each machine:"
  1. sudo apt-get install sun-java6-jre"
  2. sudo perl -pi -e 's/^([^#]*multiverse)/#\\1/g' /etc/apt/sources.list"

  Why? Because Sun are tools, and force you to answer licence questions.
  EOS
  exit
end
</textarea>
<p>Modify YOURDOMAIN to an IP that you have root access to. The script will create two folders - /usr/local/src/mingle and /var/www/apps/mingle. Its pretty harmless.</p>
<p>To install, run the capistrano tasks:</p>
<pre>
cd ..
cap1 java_install
cap1 mingle_install
cap1 mingle_start
</pre>
<p>BUT, mingle_start doesn't work. The server just doesn't start and I don't know why.</p>
<p>So, ssh into your machine (you had to do this for the java install step too BTW), and run:</p>
<pre>
/usr/local/src/mingle/MingleServer start
</pre>
<p>If we can fix this then that'd be uber cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2007/11/27/installing-mingle-with-capistranodeprec/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Going offline without your favourite Subversion repository?</title>
		<link>http://drnicwilliams.com/2007/11/22/going-offline-without-your-favourite-subversion-repository/</link>
		<comments>http://drnicwilliams.com/2007/11/22/going-offline-without-your-favourite-subversion-repository/#comments</comments>
		<pubDate>Thu, 22 Nov 2007 05:01:46 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2007/11/22/going-offline-without-your-favourite-subversion-repository/</guid>
		<description><![CDATA[UPDATE: useful gitify command below.
All my client projects are hosted on Subversion repos. All my OSS projects are hosted on Rubyforge Subversion repos.
And tomorrow I head off for the 2nd &#8220;no internet&#8221; RailsCamp megafest, being held outside of Melbourne. From what I heard about the 1st one, it involved a lot of Guitar Hero II [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE</strong>: useful <code>gitify</code> command below.</p>
<p>All my client projects are hosted on Subversion repos. All my OSS projects are hosted on Rubyforge Subversion repos.</p>
<p>And tomorrow I head off for the 2nd &#8220;no internet&#8221; <a href="http://wiki.railscamp07.org/railscamp07/">RailsCamp megafest</a>, being held outside of Melbourne. From what I heard about the 1st one, it involved a lot of Guitar Hero II and beer. This weekend I&#8217;m promised that someone is bringing a Wii &#8211; dear God I do love the tennis game.</p>
<p>Like MacDonalds burgers and Veganism, if there are two things that don&#8217;t go together its Subversion and &#8220;No Internet&#8221;.</p>
<p>Fortunately, for all RailsCampers, there is a solution to your fears that you won&#8217;t be able to hack on your favourite project, and will be forced into playing Guitar Hero II/III and/or the Wii for the whole weekend.</p>
<p><a href="http://git.or.cz/">Git</a>.</p>
<p>Specifically, the <a href="http://www.kernel.org/pub/software/scm/git/docs/v1.5.3/git-svn.html">git-svn</a> command.</p>
<p>More specifically, follow the following steps:</p>
<ol>
<li><code>git-svn clone &lt;your svn url&gt; projectname.git</code></li>
<li>Go camping for the weekend.</li>
<li>Commit changes with <code>git commit -a -m "hahaha I'm camping and working - doh!"</code></li>
<li>Come home from camping.</li>
<li><code>git-svn rebase</code> to re-import any SVN changes that might have been committed whilst you were away. If there are conflicts, just follow the instructions.</li>
<li><code>git-svn dcommit</code> and your svn repository will be updated with all your fancy changes; no one will ever know you used Git.</li>
</ol>
<h2>Installing Git</h2>
<p>I remember having problems getting <code>git-svn</code> to run because the default path to the perl cmd is crap, and you need to specify <code>PERL_PATH='/usr/bin/env perl'</code>, I think, before installation.</p>
<p>For MacPorts etc, its <code>sudo port install git-core</code>. I think the reason its not just called &#8216;git&#8217; is to remind you that you know nothing about git. Which is fair. You don&#8217;t if you don&#8217;t know how to install it, I guess.</p>
<p>From source, get the tarball from the <a href="http://git.or.cz/">home page</a>.</p>
<p>For Windows, use <a href="http://www.cygwin.com/">cygwin</a>.</p>
<h2>Gitify command</h2>
<p>Want a utility cmd to create a Git repo in the parent folder of a Subversion project? That is, go to your Rails app that is checked out from a Subversion repo, and run <code>gitify</code>, and you will have a <code>foldername.git</code> folder in the parent folder.</p>
<p>Stick this code into ~/bin/gitify and add ~/bin to your path:</p>
<textarea name="code" class="ruby" cols="60" rows="10">
#!/usr/bin/env ruby -wKU

# get svn info location
svnurl = `svn info | grep "^URL:"`.gsub('URL: ','').chomp

# project = basename
project = File.basename(Dir.pwd)

puts cmd = "git-svn clone #{svnurl} ../#{project}.git"

`#{cmd}`
</textarea>
]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2007/11/22/going-offline-without-your-favourite-subversion-repository/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</title>
		<link>http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/</link>
		<comments>http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/#comments</comments>
		<pubDate>Thu, 12 Apr 2007 21:26:17 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[Magic Models]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/</guid>
		<description><![CDATA[At this point in time there’s no facility in Rails to talk to more than one database at a time.
Alex Payne
I possibly have such a facility. Perhaps it will help, and I will get some DHH-love and perhaps a free Twitter account for my troubles. Or perhaps a t-shirt.
As a bonus, the solution even includes [...]


Related posts:<ol><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><li><a href='http://drnicwilliams.com/2009/10/07/rails-themes-can-remember-things/' rel='bookmark' title='Permanent Link: Rails themes can remember things'>Rails themes can remember things</a> <small>I was getting annoyed at having to remember all the...</small></li><li><a href='http://drnicwilliams.com/2009/10/06/install-any-html-themetemplate-into-your-rails-app/' rel='bookmark' title='Permanent Link: Install any HTML theme/template into your Rails app'>Install any HTML theme/template into your Rails app</a> <small> Have you ever even bothered to Google for &#8220;rails...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<blockquote><p>At this point in time there’s no facility in Rails to talk to more than one database at a time.</p></blockquote>
<p><cite><a href="http://www.radicalbehavior.com/5-question-interview-with-twitter-developer-alex-payne/">Alex Payne</a></cite></p>
<p>I possibly have such a <em>facility</em>. Perhaps it will help, and I will get some <a href="http://www.loudthinking.com/arc/000608.html">DHH-love</a> and perhaps a free <a href="http://www.twitter.com">Twitter</a> account for my troubles. Or perhaps a t-shirt.</p>
<p>As a bonus, the solution even includes decent Ruby-fu syntax. So, if you&#8217;re just here for the view:</p>
<pre>class PeopleController < ApplicationController
  def index
    @people = conn::Person.find(:all)
  end
end
</pre>
<p>That code just there solves all our problems. It will invoke Person.find(:all) on a random database connection to (assumably) a clone database. Awesomeness I think. I hope it helps Twitter and all the Twit-sers (or whatever you call a user of Twitter).</p>
<p>This solution comes from the <a href="http://magicmodels.rubyforge.org/magic_multi_connections">magic_multi_connections</a> gem.</p>
<h1>What is going on here?</h1>
<p>I think a tutorial is the best way to demonstrate what is happening here. So, let's create a rails app and mix in the <a href="http://magicmodels.rubyforge.org/magic_multi_connections">magic_multi_connections</a> gem.</p>
<p>First, get the gem. Second, create a rails app:</p>
<pre>$ sudo gem install magic_multi_connections
$ rails multi -d sqlite3</pre>
<p>Now edit the <code>config/database.yml</code> file to create some more databases:</p>
<pre>development:
  adapter: sqlite3
  database: db/development.sqlite3
  timeout: 5000

development_clone1:
  adapter: sqlite3
  database: db/development_clone1.sqlite3
  timeout: 5000

development_clone2:
  adapter: sqlite3
  database: db/development_clone2.sqlite3
  timeout: 5000
</pre>
<p>But please pretend these are uber-MySQL clusters or whatever.</p>
<p>Think of <strong>:development</strong> as the <strong>read-write</strong> connection, and the <strong>:development_cloneN</strong> connections are for read-only access.</p>
<p>At the bottom of your <strong>environment.rb</strong> file, add the following:</p>
<pre>
require 'magic_multi_connections'
connection_names = ActiveRecord::Base.configurations.keys.select do |name|
  name =~ /^#{ENV['RAILS_ENV']}_clone/
end
@@connection_pool = connection_names.map do |connection_name|
  Object.class_eval <<-EOS
    module #{connection_name.camelize}
      establish_connection :#{connection_name}
    end
  EOS
  connection_name.camelize.constantize
end
</pre>
<p>Let's test what this gives us in the console:</p>
<pre>$ ruby script/console
>> @@connection_pool
=> [DevelopmentClone1, DevelopmentClone2]
>> DevelopmentClone1.class
=> Module
>> DevelopmentClone1.connection_spec
=> :development_clone1
</pre>
<p>Our new modules will act as connections. One module per connection. The code above gives them names to match the connection names, but its really irrelevant what they are called, thanks to the mysterious <code>conn</code> method.</p>
<p>So, go create some models and some data. I'll use <code>Person</code> as the class here.</p>
<p>To setup the schemas in our clone databases, we'll use <code>rake db:migrate</code>. To do this:</p>
<pre>$ cp config/environments/development.rb config/environments/development_clone1.rb
$ cp config/environments/development.rb config/environments/development_clone2.rb
$ rake db:migrate RAILS_ENV=development
$ rake db:migrate RAILS_ENV=development_clone1
$ rake db:migrate RAILS_ENV=development_clone2
</pre>
<p>To differentiate the databases in our example, assume there are two <code>Person</code> records in the <code>:development</code> database, and none in the two clones. Of course, in real-life, they are clones. You'd have a replicate mechanism in there somewhere.</p>
<p>Now, we can access our normal Rails modules through our connection modules. Magically of course.</p>
<pre>>> ActiveRecord::Base.active_connections.keys
=> []
>> Person.count
=> 2
>> ActiveRecord::Base.active_connections.keys
=> ["ActiveRecord::Base"]
>> DevelopmentClone1::Person.count
=> 0
>> ActiveRecord::Base.active_connections.keys
=> ["ActiveRecord::Base", "DevelopmentClone1::Person"]
</pre>
<p>Wowzers. <code>Person</code> <strong>and</strong> <code>DevelopmentClone1::Person</code> classes? </p>
<p>But note - <code>Person.count => 2</code> and <code>DevelopmentClone1::Person.count => 0</code> - they are accessing different databases. The same class definition <code>Person</code> is being used for multiple database connections. We never defined more <code>Person</code> classes. Just the standard default one in <code>app/models/person.rb</code>.</p>
<p>The <code>active_connections</code> result shows that <code>DevelopmentClone1::Person</code> has its own connection. Yet you never had to manually call <code>DevelopmentClone1::Person.establish_connection :development_clone1</code> - it was called automatically when the class is created.</p>
<p>Of course, <code>DevelopmentClone2::Person</code> is automatically connected to <code>:development_clone2</code>, and so on.</p>
<h2>Behind the scenes</h2>
<p>Let's look at our generated classes:</p>
<pre>$ ruby script/console
>> DevelopmentClone1::Person
=> DevelopmentClone1::Person
>> Person
=> Person
>> DevelopmentClone1::Person.superclass
=> Person
</pre>
<p>That is, there is a <code>DevelopmentClone1::Person</code> class, automagically generated for you, which is a subclass of <code>Person</code>, so it has all its behaviour etc.</p>
<h2>Dynamic connection pools within Rails controllers</h2>
<p>The magic of the <code>conn</code> method will now be revealed:</p>
<pre>$ ruby script/console
>> def conn
>>   @@connection_pool[rand(@@connection_pool.size)]
>> end
>> conn::Person.name
=> "DevelopmentClone2::Person"
>> conn::Person.name
=> "DevelopmentClone1::Person"
</pre>
<p>The <code>conn</code> method randomly returns one of the connection modules. Subsequently, <code>conn::Person</code> returns a Person class that is connected to a random clone database. Booya. Free Twitter swag coming my way.</p>
<p>Place the <code>conn</code> method in the ApplicationController class, and you can get dynamic connection pooling within Rails actions as needed, as in the following example (from the top of the article):</p>
<pre>class PeopleController < ApplicationController
  def index
    @people = conn::Person.find(:all)
  end
end
</pre>
<p>Decent Ruby-fu, I think. Certainly better than manually calling <code>establish_connection</code> on model classes before each call (or in a <code>before_filter</code> call, I guess).</p>
<h1>This is just a concept</h1>
<p>I know this tutorial above works. But that might be the extent of what I know. Let me know if this has any quirks (especially if you solve them), or if this is a stupid idea for implementing connection pooling with nice Ruby syntax.</p>
<p><strong>Hope it helps.</strong></p>


<p>Related posts:<ol><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><li><a href='http://drnicwilliams.com/2009/10/07/rails-themes-can-remember-things/' rel='bookmark' title='Permanent Link: Rails themes can remember things'>Rails themes can remember things</a> <small>I was getting annoyed at having to remember all the...</small></li><li><a href='http://drnicwilliams.com/2009/10/06/install-any-html-themetemplate-into-your-rails-app/' rel='bookmark' title='Permanent Link: Install any HTML theme/template into your Rails app'>Install any HTML theme/template into your Rails app</a> <small> Have you ever even bothered to Google for &#8220;rails...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/feed/</wfw:commentRss>
		<slash:comments>59</slash:comments>
		</item>
		<item>
		<title>Post-Halloween RadRails trick &#8211; all TextMate snippets available</title>
		<link>http://drnicwilliams.com/2006/11/06/post-halloween-radrails-trick-all-textmate-snippets-available/</link>
		<comments>http://drnicwilliams.com/2006/11/06/post-halloween-radrails-trick-all-textmate-snippets-available/#comments</comments>
		<pubDate>Mon, 06 Nov 2006 14:30:29 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[RadRails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Translation]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/11/06/post-halloween-radrails-trick-all-textmate-snippets-available/</guid>
		<description><![CDATA[



HTML snippets
48


Ruby snippets
199

I tease myself with things I can&#8217;t have &#8211; like watching TextMate demo videos. One wonderful video shows a test-driven design demonstration by James Edward Gray II where he used Textmate snippets to generate the various assert statements. For example:


ase => assert_equal(expected, actual)
asn => assert_nil(instance)
asm => assert_match(/expected_pattern/, actual_string)

I&#8217;d been using Corban Brook&#8217;s templates [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2008/06/11/using-ruby-within-textmate-snippets-and-commands/' rel='bookmark' title='Permanent Link: Using Ruby within TextMate snippets and commands'>Using Ruby within TextMate snippets and commands</a> <small>I didn&#8217;t know you could run Ruby within TextMate snippets....</small></li><li><a href='http://drnicwilliams.com/2008/05/12/textmate-bundles-for-merb/' rel='bookmark' title='Permanent Link: TextMate bundles for Merb'>TextMate bundles for Merb</a> <small>If you are using TextMate (OS X) or E Text...</small></li><li><a href='http://drnicwilliams.com/2008/04/01/writing-c-extensions-in-rubygems/' rel='bookmark' title='Permanent Link: Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)'>Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)</a> <small>Already know C extensions in RubyGems? Cool &#8211; then just...</small></li></ol>]]></description>
			<content:encoded><![CDATA[
<p><img id="image113" src="http://drnicwilliams.com/wp-content/uploads/2006/11/textmate-to-radrails.png" alt="Textmate Snippets to Radrails" /></p>
<div>
<div class="version clickable" onclick='document.location = "http://drnicwilliams.com/wp-content/uploads/2006/11/rhtml-rr-templates.xml"; return false'>
<div>HTML snippets</div>
<div class="numbers">48</div>
</div>
<div class="version clickable" onclick='document.location = "http://drnicwilliams.com/wp-content/uploads/2006/11/ruby-rr-templates.xml"; return false'>
<div>Ruby snippets</div>
<div class="numbers">199</div>
</div>
<p>I tease myself with things I can&#8217;t have &#8211; like watching TextMate <a href="http://macromates.com/screencasts">demo videos</a>. One wonderful video shows a <a href="http://macromates.com/screencast/ruby_quiz_screencast.mov">test-driven design</a> demonstration by James Edward Gray II where he used Textmate snippets to generate the various assert statements. For example:
</div>
<pre>
ase => assert_equal(expected, actual)
asn => assert_nil(instance)
asm => assert_match(/expected_pattern/, actual_string)
</pre>
<p>I&#8217;d been using Corban Brook&#8217;s <a href="http://schf.uc.org/articles/2006/09/18/textmate-like-template-syntax-for-radrails">templates</a> but they didn&#8217;t include any assert or migration templates. And I wanted them without having to spend $3049 on TextMate [<a href="#radrails-snippets1">1</a>]</p>
<h3>This made me cranky</h3>
<p><strong>Solution 1:</strong> Learn <a href="http://www.rubyinside.com/ruby-and-rails-on-emacs-screencast-281.html">Emacs</a>. Setting up Emacs with all the modules you&#8217;ll need is a non-trival exercise. That is, put aside a day or so and don&#8217;t expect to be finished when time runs out. Plus, a version of GNU Emacs for Windows hasn&#8217;t been released since 2005. Not a lot of OSS love there.</p>
<p><strong>Solution 2: </strong> Offer to build Textmate for Windows. I&#8217;m sure I read once that the Textmate author was open to porting of Textmate to Windows. That must be the past, because their website claims very strongly that there will <a href="http://macromates.com/">never be a port</a>:</p>
<blockquote><p>countless requests for both a Windows and Linux port, but TextMate remains exclusive for the Mac, and that is how we like it!</p></blockquote>
<p>That&#8217;s just lazy if you ask me.</p>
<p><strong>Solution 3:</strong> Port Textmate&#8217;s snippet libraries (bundles) over to RadRails. Textmate has a more powerful syntax for its snippets than RadRails has for its templates (a limitation inherited from Eclipse), but <strong>SUCCESS!</strong> On the 31st of October &#8211; the day when Textmate was lauded around the blogosphere for its Halloween theme, I ported all their snippets into RadRails. OoooOOOOHHH spooooky.</p>
<p>You can now access the latest and greatest in templates/snippets for Radrails, for <a href="http://drnicwilliams.com/wp-content/uploads/2006/11/ruby-rr-templates.xml">Ruby/Rails</a> and <a href="http://drnicwilliams.com/wp-content/uploads/2006/11/rhtml-rr-templates.xml">RHTML</a> (or click on the yellow boxes at the top).</p>
<h3>Installation</h3>
<ol>
<li>Download the two template XML files.</li>
<li>Open RadRails</li>
<li>Go to Windows > Preferences > Ruby > Editor > Templates, to see the list of included templates</li>
<li>Click on any template, and press Ctrl-A to select them all.</li>
<li>Click on Remove, to delete them all</li>
<li>Click Import&#8230;, select the file <a href="http://drnicwilliams.com/wp-content/uploads/2006/11/ruby-rr-templates.xml">ruby-rr-templates.xml</a></li>
<li>Change to Rails > Editiors > RHTML Editor > RHTML Templates</li>
<li>Remove all the current templates</li>
<li>Click Import&#8230;, select the file <a href="http://drnicwilliams.com/wp-content/uploads/2006/11/rhtml-rr-templates.xml">rhtml-rr-templates.xml</a></li>
<li>Press Ok to close the dialog and you&#8217;re done</li>
</ol>
<p>Too difficult? The next release of RadRails will include these new templates.</p>
<h3>How to use templates/snippets?</h3>
<p>You can peruse a <a href="http://clarkware.com/cgi/blosxom/2006/05/03">textmate-snippets-cheat-sheet</a>, but really, spend 20 minutes looking through the template lists in RadRails. The <em>name</em> of the template is the text you type into the editor to activate the template.</p>
<p>So, the name of <code>assert_equals</code> is <code>ase</code>. So, type <code>ase</code> and press CTRL-SPACE, and a list of options pops up. Press return on the selected option.</p>
<p>Want to see all available <code>assert_*</code> templates? Type <code>as</code> and CTRL-SPACE and there they are. Nifty.</p>
<h3>Patching/Updating</h3>
<p>The RadRails guys are going to host these templates to allow anonymous access to make submitting patches relatively easy (if you know how to wield SVN). In future perhaps there will be a nice website for collaboratively sharing and downloading updates to templates.</p>
<h3>Templates for JavaScript and CSS</h3>
<p>I&#8217;ve put in a request for adding template support for JS and CSS as I have ported the JavaScript+CSS bundles as well. We just need a UI to import them into RadRails.</p>
<p><a name="radrails-snippets1">[1]</a> TextMate is 39 euros = $49 at the moment. Plus $3000 for a new Mac.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2008/06/11/using-ruby-within-textmate-snippets-and-commands/' rel='bookmark' title='Permanent Link: Using Ruby within TextMate snippets and commands'>Using Ruby within TextMate snippets and commands</a> <small>I didn&#8217;t know you could run Ruby within TextMate snippets....</small></li><li><a href='http://drnicwilliams.com/2008/05/12/textmate-bundles-for-merb/' rel='bookmark' title='Permanent Link: TextMate bundles for Merb'>TextMate bundles for Merb</a> <small>If you are using TextMate (OS X) or E Text...</small></li><li><a href='http://drnicwilliams.com/2008/04/01/writing-c-extensions-in-rubygems/' rel='bookmark' title='Permanent Link: Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)'>Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)</a> <small>Already know C extensions in RubyGems? Cool &#8211; then just...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/11/06/post-halloween-radrails-trick-all-textmate-snippets-available/feed/</wfw:commentRss>
		<slash:comments>75</slash:comments>
<enclosure url="http://macromates.com/screencast/ruby_quiz_screencast.mov" length="44523350" type="video/quicktime" />
		</item>
		<item>
		<title>53 cheat sheets and growing</title>
		<link>http://drnicwilliams.com/2006/10/19/53-cheat-sheets-and-growing/</link>
		<comments>http://drnicwilliams.com/2006/10/19/53-cheat-sheets-and-growing/#comments</comments>
		<pubDate>Thu, 19 Oct 2006 08:42:54 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/10/19/53-cheat-sheets-and-growing/</guid>
		<description><![CDATA[I said previously that errtheblog&#8217;s cheat app would have 100s+ of cheat sheets.
After a month and a half, they are now half way. There is still more cheating to be done.

> require 'map_by_method'
> require 'hpricot'
> require 'open-uri'
> doc = Hpricot(open("http://cheat.errtheblog.com/b"))
> cheatsheets = doc.search('div.content/ul/li').children.map_inner_html.flatten
=> ["ascii", "assertions", "assert_select", "balloon", "bash", "belongs_to", "blogs",
"callbacks", "capistrano", "cheat", "database_yml", "deprecated", "environments",
"exceptions", [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/02/01/radrails-templates-cheat-sheets/' rel='bookmark' title='Permanent Link: RadRails Templates Cheat Sheets'>RadRails Templates Cheat Sheets</a> <small>Now that RadRails is blessed with 100s of templates/snippets the...</small></li><li><a href='http://drnicwilliams.com/2006/10/18/create-and-deploy-command-line-apps-with-rubygems/' rel='bookmark' title='Permanent Link: Create and deploy command line apps with RubyGems'>Create and deploy command line apps with RubyGems</a> <small>RubyGems have many things going for them: they are a...</small></li><li><a href='http://drnicwilliams.com/2006/09/03/100s-cheatsheets-for-ruby-and-rails/' rel='bookmark' title='Permanent Link: 100s cheatsheets for Ruby and Rails'>100s cheatsheets for Ruby and Rails</a> <small>Ok, disclaimer. As of writing there aren&#8217;t exactly 100+ cheatsheets...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://drnicwilliams.com/2006/09/03/100s-cheatsheets-for-ruby-and-rails/">I said previously</a> that errtheblog&#8217;s <a href="http://cheat.errtheblog.com/b">cheat</a> app would have 100s+ of cheat sheets.</p>
<p>After a month and a half, they are now half way. There is still more cheating to be done.</p>
<pre>
> require '<a href="http://rubyforge.org/projects/drnicutilities/">map_by_method</a>'
> require '<a href="http://code.whytheluckystiff.net/hpricot/wiki/HpricotBasics">hpricot</a>'
> require '<a href="http://www.ruby-doc.org/stdlib/libdoc/open-uri/rdoc/"><a href="http://www.ruby-doc.org/stdlib/libdoc/open-uri/rdoc/">open-uri</a></a>'
> doc = Hpricot(open("<span class=string>http://cheat.errtheblog.com/b</span>"))
> cheatsheets = doc.search('div.content/ul/li').children.map_inner_html.flatten
=> ["ascii", "assertions", "assert_select", "balloon", "bash", "belongs_to", "blogs",
"callbacks", "capistrano", "cheat", "database_yml", "deprecated", "environments",
"exceptions", "firebug", "google_mail", "google_reader", "gruff", "has_and_belongs_to_many",
"has_many", "has_one", "http_status_codes", "iomodes", "jedit_ruby_editor_plugin",
"link_to_remote", "markaby", "markdown", "matz_bot", "microformats_helper",
"migrations", "mocha", "nonsense", "prototype", "rails_console", "rails_edge", "rdoc",
"readline", "regex", "rjs", "rspec", "ruby", "scrapi", "sprintf", "sti", "strftime", "svn",
"tempfile", "textmate_rails", "tld", "validations", "vim", "vim_goodies", "wmii3"]
> puts "#{cheatsheets.length} cheat sheets and counting..."
<span class=string>53 cheat sheets and counting...</span>
</pre>
<p>By the way, they <a href="http://errtheblog.com/post/34">celebrated</a> when they hit 42.</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/02/01/radrails-templates-cheat-sheets/' rel='bookmark' title='Permanent Link: RadRails Templates Cheat Sheets'>RadRails Templates Cheat Sheets</a> <small>Now that RadRails is blessed with 100s of templates/snippets the...</small></li><li><a href='http://drnicwilliams.com/2006/10/18/create-and-deploy-command-line-apps-with-rubygems/' rel='bookmark' title='Permanent Link: Create and deploy command line apps with RubyGems'>Create and deploy command line apps with RubyGems</a> <small>RubyGems have many things going for them: they are a...</small></li><li><a href='http://drnicwilliams.com/2006/09/03/100s-cheatsheets-for-ruby-and-rails/' rel='bookmark' title='Permanent Link: 100s cheatsheets for Ruby and Rails'>100s cheatsheets for Ruby and Rails</a> <small>Ok, disclaimer. As of writing there aren&#8217;t exactly 100+ cheatsheets...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/10/19/53-cheat-sheets-and-growing/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>[ANN] Generating new gems for graceful goodliness</title>
		<link>http://drnicwilliams.com/2006/10/11/generating-new-gems/</link>
		<comments>http://drnicwilliams.com/2006/10/11/generating-new-gems/#comments</comments>
		<pubDate>Wed, 11 Oct 2006 07:23:47 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Gems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[map_by_method]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/10/11/generating-new-gems/</guid>
		<description><![CDATA[
I don&#8217;t like you [1]. You don&#8217;t share code. I know, I know, you&#8217;ve had good reasons &#8211; you don&#8217;t know how to create a Ruby gem, how to upload it to a gem server like RubyForge, and you&#8217;re a chicken. Today we&#8217;ll remove the first of these minor roadblocks, with a New Gem Generator!
Now [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2008/12/05/my-rubygems-development-tools-and-workflow/' rel='bookmark' title='Permanent Link: My RubyGems development tools and workflow'>My RubyGems development tools and workflow</a> <small> The Open Source Developers Conference (osdc) is a nifty...</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><li><a href='http://drnicwilliams.com/2008/04/01/writing-c-extensions-in-rubygems/' rel='bookmark' title='Permanent Link: Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)'>Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)</a> <small>Already know C extensions in RubyGems? Cool &#8211; then just...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<div style="float: right;"><img src="http://drnicwilliams.com/wp-content/uploads/2006/10/chicken.jpg" alt="Chicken!" /></div>
<p>I don&#8217;t like you [<a href="#newgem1">1</a>]. You don&#8217;t share code. I know, I know, you&#8217;ve had good reasons &#8211; you don&#8217;t know how to create a Ruby gem, how to upload it to a gem server like RubyForge, and you&#8217;re a chicken. Today we&#8217;ll remove the first of these minor roadblocks, with a New Gem Generator!</p>
<p>Now you can take any <em>library</em> or <em>Rails plugin</em> or <em>command line application</em>, gemify it, and easily share it with the Ruby world. With gems you get in-built version support (you can specify which version of a gem you want when you use it via the <a href="http://rubygems.org/read/chapter/4#page71">require_gem</a> method), an encapsulated, consistent folder structure for your bin/lib/test folders, and you get cross-platform support for bin apps. Too much niftiness to ignore, really.</p>
<p>The New Gem Generator is like the <code>rails</code> command for rails applications, but it creates the folders and starting files for a new gem. It&#8217;s called <code>newgem</code>.</p>
<h2>Tutorial</h2>
<h3>Aim</h3>
<p>To convert the <strong>Map by Method</strong> (previously called Map by Pluralisation) library into a gem.</p>
<p>See <a href="http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/">original</a> and <a href="http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/">demo</a> articles. Sex on a stick &#8211; soon to be gemified before your very eyes. (<a href="#newgem_remote">Download instructions</a> for the prebuilt gem)</p>
<h3>Installation</h3>
<pre>
> gem install <span class=constant>newgem</span>
</pre>
<p>Download from <a href="http://rubyforge.org/frs/?group_id=2340&#038;release_id=7337">rubyforge</a> if you have firewall problems (as I do at work) and need to get the gem explicitly first. THEN run the above command in the folder you saved the gem.</p>
<h3>Create new gem</h3>
<pre>
> <span class=constant>newgem map_by_method</span>
creating: map_by_method
creating: map_by_method/CHANGELOG
creating: map_by_method/README
creating: map_by_method/lib
creating: map_by_method/lib/map_by_method
creating: map_by_method/lib/map_by_method.rb
creating: map_by_method/lib/map_by_method/version.rb
creating: map_by_method/Rakefile
creating: map_by_method/test
creating: map_by_method/test/all_tests.rb
creating: map_by_method/test/test_helper.rb
creating: map_by_method/test/map_by_method_test.rb
creating: map_by_method/examples
creating: map_by_method/bin
</pre>
<h3>Copy in the library</h3>
<p>The generated <code>lib/map_by_method.rb</code> file looks like:</p>
<pre>
Dir['map_by_method/**/*.rb'].sort.each { |lib| require lib }
</pre>
<p>This will automatically include (<code>require</code>), in alphabetical order, the files in the<br />
<code>lib/map_by_method</code> folder. If you need the files required in a specific order, then do it explicitly here, for example:</p>
<pre>
require 'foo'
require 'bar'
require 'tar'
</pre>
<p>or</p>
<pre>
%w(foo bar tar).each {|lib| require lib}
</pre>
<p>For this gem there won&#8217;t be any additional library files, so we&#8217;ll just copy in the following code into the <code>lib/map_by_method.rb</code> file and remove the library loading code.</p>
<pre>
module <span class=constant>MapByMethod</span>
  def self.included(base)
    super

    base.module_eval <<-EOS
      def method_missing(method, *args, &#038;block)
        super
      rescue NoMethodError
        error = $!
        begin
          re = /(map|collect|select|each|reject)_([\\w\\_]+\\??)/
          if (match = method.to_s.match(re))
            iterator, callmethod = match[1..2]
            return self.send(iterator) {|item| item.send callmethod}
          end
          return self.map {|item| item.send method.to_s.singularize.to_sym}
        rescue NoMethodError
          nil
        end
        raise error
      end
    EOS
  end
end

unless String.instance_methods.include? "singularize"
  class String
    def singularize
      self.gsub(/e?s\Z/,'')
    end
  end
end

<span class=constant>Array</span>.send :include, <span class=constant>MapByMethod</span>
</pre>
<h3>Package your gem into a .gem file</h3>
<p>From the root folder of your gem run <code>rake package</code>:</p>
<pre>
> rake <span class=constant>package</span>
(in C:/InstantRails/ruby_apps/map_by_method)
rm -r .config
  Successfully built RubyGem
  Name: map_by_method
  Version: 0.0.1
  File: map_by_method-0.0.1.gem
mv map_by_method-0.0.1.gem pkg/map_by_method-0.0.1.gem
</pre>
<p>Tada! You are the owner of a gem.</p>
<h3>Install your gem onto your machine</h3>
<p>Your Ruby (and Rails) applications can only use the gemified libraries once you have installed the packaged gem. This is the same for other people who will use your gem.</p>
<p>Typically you install a gem from a remote gem server such as rubyforge. Today, you will install the gem locally:</p>
<pre>
> gem install <span class=constant>pkg/map_by_method-0.0.1.gem</span>
Attempting local installation of 'pkg/map_by_method-0.0.1.gem'
Successfully installed map_by_method, version 0.0.1
Installing RDoc documentation for map_by_method-0.0.1...
</pre>
<p>Note that it created and installed RDoc documentation for the library too. Each user automatically has a copy of the generated documentation for your libraries (if you actually added documentation to your code).</p>
<h3>Unit testing</h3>
<p>Look in the <code>test</code> folder and see that it has created a <code>map_by_method_test.rb</code> unit test file to get you started. Put tests in there. Add more test files. Run <code>rake test</code> from the project&#8217;s root folder and watch all your tests succeed or fail. Be good.</p>
<h3>Version numbers</h3>
<p>Note that the generated gem is <code>map_by_method-0.0.1.gem</code>. The 0.0.1 is the version number of the gem, and you can easily change this as you wish as you gem takes on new features and fixes.</p>
<p>There are two common version number formats:</p>
<p>X.Y.Z &#8211; X = major release number, Y = minor release number, Z = patch/bug fix number</p>
<p>or</p>
<p>X.Y.Z.svn = svn is the subversion number at the time the gem was released.</p>
<p>The latter is the default implementation generated by newgem. If you want the simpler version number format (the 1st one), then remove the following line from your Rakefile (around line 13):</p>
<pre>
REV = File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil
</pre>
<p>Your gem has a prebuilt mechanism for specifying the X.Y.Z portion of the version number.</p>
<p>Go to <code>lib/map_by_method/version.rb</code></p>
<pre>
module <span class=constant>MapByMethod</span> <span class=comments>#:nodoc:</span>
  module <span class=constant>VERSION</span> <span class=comments>#:nodoc:</span>
    <span class=constant>MAJOR</span> = 0
    <span class=constant>MINOR</span> = 0
    <span class=constant>TINY</span>  = 1

    <span class=constant>STRING</span> = [MAJOR, MINOR, TINY].join('.')
  end
end
</pre>
<p>Change MINOR and TINY to:</p>
<pre>
    <span class=constant>MINOR</span> = 1
    <span class=constant>TINY</span>  = 0
</pre>
<p>And repackage and reinstall your gem:</p>
<pre>
> rake <span class=constant>package</span>
(in C:/InstantRails/ruby_apps/map_by_method)
rm -r .config
  Successfully built RubyGem
  Name: map_by_method
  Version: 0.1.0
  File: map_by_method-0.1.0.gem
mv map_by_method-0.1.0.gem pkg/map_by_method-0.1.0.gem

> gem install <span class=constant>pkg/map_by_method-0.1.0.gem</span>
Attempting local installation of 'pkg/map_by_method-0.1.0.gem'
Successfully installed map_by_method, version 0.1.0
Installing RDoc documentation for map_by_method-0.1.0...
</pre>
<p>And you&#8217;re done. Next you would upload your gem to a gem server such as RubyForge, or one your company runs internally to share gems via the &#8220;gem install&#8221; mechanism.</p>
<h2 name="newgem_remote">map_by_method already on RubyForge</h2>
<p>If you want the <strong>map_by_method</strong> gem, its already on RubyForge, so you can remotely install it:</p>
<pre>
gem install <span class=constant>map_by_method</span>
</pre>
<h2>Inspiration</h2>
<p><a href="http://jayfields.blogspot.com">Jay Fields</a> created a great &#8220;ruby application setup&#8221; <a href="http://jayfields.blogspot.com/2006/10/ruby-project-tree.html">script</a>.</p>
<p><a name="newgem1">[1]</a> That&#8217;s not true. I do like you. </p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2008/12/05/my-rubygems-development-tools-and-workflow/' rel='bookmark' title='Permanent Link: My RubyGems development tools and workflow'>My RubyGems development tools and workflow</a> <small> The Open Source Developers Conference (osdc) is a nifty...</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><li><a href='http://drnicwilliams.com/2008/04/01/writing-c-extensions-in-rubygems/' rel='bookmark' title='Permanent Link: Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)'>Writing C extensions in RubyGems using newgem generators (plus a free TextMate bundle)</a> <small>Already know C extensions in RubyGems? Cool &#8211; then just...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/10/11/generating-new-gems/feed/</wfw:commentRss>
		<slash:comments>62</slash:comments>
		</item>
		<item>
		<title>I love &#8220;map by pluralisation&#8221; [now: map_by_method]</title>
		<link>http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/</link>
		<comments>http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/#comments</comments>
		<pubDate>Wed, 04 Oct 2006 14:12:51 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Meta-Programming]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[map_by_method]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/</guid>
		<description><![CDATA[Update: this is a gem called map_by_method.
The other day I introduced a new syntax idea that I call &#8220;map by pluralisation&#8221;. Everyday I use it in code and in the console/irb I fall more in love with its simplicity &#8211; both to type and to read.
The following are all equivalent:

>> BankTransaction.columns.names  # map by [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/09/07/map_by_method-the-final-announcement/' rel='bookmark' title='Permanent Link: map_by_method &#8211; the final announcement'>map_by_method &#8211; the final announcement</a> <small>I don&#8217;t really talk about my projects after I release...</small></li><li><a href='http://drnicwilliams.com/2007/08/12/map_by_method-now-works-with-activerecord-associations/' rel='bookmark' title='Permanent Link: map_by_method now works with ActiveRecord associations'>map_by_method now works with ActiveRecord associations</a> <small>I was always annoyed that map_by_method was broken for ActiveRecord...</small></li><li><a href='http://drnicwilliams.com/2007/03/02/5-things-im-in-love-with/' rel='bookmark' title='Permanent Link: 5 things I&#8217;m in love with'>5 things I&#8217;m in love with</a> <small>In no specific order, but enumerated for good measure: autotest...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Update: this is a gem called <a href="http://drnicwilliams.com/2006/10/11/generating-new-gems/">map_by_method</a>.</p>
<p>The other day I <a href="http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/">introduced a new syntax idea</a> that I call &#8220;map by pluralisation&#8221;. Everyday I use it in code and in the console/irb I fall more in love with its simplicity &#8211; both to type and to read.</p>
<p>The following are all equivalent:</p>
<pre>
>> BankTransaction.columns.<span class=constant>names</span>  <span class=comments># map by pluralisation</span>
=> ["id", "amount", "date", "description", "balance"]
>> BankTransaction.columns.<span class=constant>name</span>   <span class=comments># singular works too</span>
=> ["id", "amount", "date", "description", "balance"]
>> BankTransaction.columns.<span class=constant>map_name</span>  <span class=comments># merge collector (map) + operation (name is method of BankTransaction object)</span>
=> ["id", "amount", "date", "description", "balance"]
>> BankTransaction.columns.<span class=constant>collect_name</span>  <span class=comments># merge collector (collect) + operation</span>
=> ["id", "amount", "date", "description", "balance"]
</pre>
<p>All of which are <strong>easier to read and quicker to type</strong> than the current equivalents:</p>
<pre>
>> BankTransaction.columns.<span class=constant>map {|p| p.name}</span>  <span class=comments># standard map</span>
=> ["id", "amount", "date", "description", "balance"]
>> BankTransaction.columns.<span class=constant>map &#038;:name</span>  <span class=comments># Symbol.to_proc</span>
=> ["id", "amount", "date", "description", "balance"]
</pre>
<p>You can now type:</p>
<pre>
>> BankTransaction.columns.<span class=constant>select_primary</span>  <span class=comments># merge collector (select) and operator (primary returns true/false on a Column object)</span>
=> [#&lt;...MysqlColumn:0x3c8a4f0 @limit=11, @sql_type="int(11)", @primary=true, @type=:integer, @number=true, @name="id"&gt;]
</pre>
<p>Instead of:</p>
<pre>
>> BankTransaction.columns.<span class=constant>select {|c| c.primary}</span>
>> BankTransaction.columns.<span class=constant>select &#038;:primary</span>
</pre>
<h3>Use with ActiveRecords</h3>
<p>&#8220;Map by pluralisation&#8221; is truly wonderful in the console for exploring and collecting data models.</p>
<p>Without knowing a thing about the data model, I bet you can understand either of the following:</p>
<pre>
@transactions = BankTransaction.find :all, :conditions => ['date = ?', Date.today], :include => [:accounts => [:owner]]
return @transactions.<span class=constant>collect_accounts</span>.<span class=constant>select_overdrawn?</span>.<span class=constant>collect_owner</span>.<span class=constant>full_names</span>
</pre>
<p>Answer: the full name of each owner of an overdrawn bank accounts for all today&#8217;s bank transactions.</p>
<p>It reads well as there is a minimum of {, }, |, &#038;, : characters.</p>
<h3>Download</h3>
<p><a href="http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/">Code available here</a></p>
<h3>Tip for use with ActiveRecord Associations</h3>
<p>You may need to cast associations to Arrays.</p>
<pre>
@account.transactions.<span class=string>to_a</span>.<span class=constant>map_dates</span>
</pre>
<p>The result of the transactions assocation on the Account class is not an Array. My initial attempts to provide the &#8220;map by pluralisation&#8221; code (a method_missing) didn&#8217;t work, and casting it to an explicit Array using <code>to_a</code> seemed simple and harmless.</p>
<h3>Discussion of Syntax Ideas</h3>
<p><a href="http://www.ruby-forum.com/topic/82905">Ruby Forum</a></p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/09/07/map_by_method-the-final-announcement/' rel='bookmark' title='Permanent Link: map_by_method &#8211; the final announcement'>map_by_method &#8211; the final announcement</a> <small>I don&#8217;t really talk about my projects after I release...</small></li><li><a href='http://drnicwilliams.com/2007/08/12/map_by_method-now-works-with-activerecord-associations/' rel='bookmark' title='Permanent Link: map_by_method now works with ActiveRecord associations'>map_by_method now works with ActiveRecord associations</a> <small>I was always annoyed that map_by_method was broken for ActiveRecord...</small></li><li><a href='http://drnicwilliams.com/2007/03/02/5-things-im-in-love-with/' rel='bookmark' title='Permanent Link: 5 things I&#8217;m in love with'>5 things I&#8217;m in love with</a> <small>In no specific order, but enumerated for good measure: autotest...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>zip vs transpose</title>
		<link>http://drnicwilliams.com/2006/10/03/zip-vs-transpose/</link>
		<comments>http://drnicwilliams.com/2006/10/03/zip-vs-transpose/#comments</comments>
		<pubDate>Tue, 03 Oct 2006 10:16:35 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/10/03/zip-vs-transpose/</guid>
		<description><![CDATA[Prelude
If I wanted to create a Hash from two arrays &#8211; one containing the keys and the other the values &#8211; I have used transpose:

>> keys = %w(name description country)
>> values = ["Dr Nic", "Good lookin'", "Netherlands"]
>> [keys, values].transpose
=> [["name", "Dr Nic"], ["description", "Good lookin'"], ["country", "Netherlands"]]
>> hash = Hash[*[keys, values].transpose.flatten]
=> {"name"=>"Dr Nic", "country"=>"Netherlands", "description"=>"Good [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/08/12/map_by_method-now-works-with-activerecord-associations/' rel='bookmark' title='Permanent Link: map_by_method now works with ActiveRecord associations'>map_by_method now works with ActiveRecord associations</a> <small>I was always annoyed that map_by_method was broken for ActiveRecord...</small></li><li><a href='http://drnicwilliams.com/2006/12/25/my-year-in-cities-2006/' rel='bookmark' title='Permanent Link: My Year in Cities, 2006'>My Year in Cities, 2006</a> <small>This game seemed like fun, so I thought I&#8217;d play....</small></li><li><a href='http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/' rel='bookmark' title='Permanent Link: I love &#8220;map by pluralisation&#8221; [now: map_by_method]'>I love &#8220;map by pluralisation&#8221; [now: map_by_method]</a> <small>Update: this is a gem called map_by_method. The other day...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<h3>Prelude</h3>
<p>If I wanted to create a Hash from two arrays &#8211; one containing the keys and the other the values &#8211; I have used <code>transpose</code>:</p>
<pre>
>> keys = %w(name description country)
>> values = ["Dr Nic", "Good lookin'", "Netherlands"]
>> [keys, values].<span class=constant>transpose</span>
=> [["name", "Dr Nic"], ["description", "Good lookin'"], ["country", "Netherlands"]]
>> hash = Hash[*[keys, values].<span class=constant>transpose</span>.flatten]
=> {"name"=>"Dr Nic", "country"=>"Netherlands", "description"=>"Good lookin'"}
</pre>
<p>I was happy with that.</p>
<h3>The newcomer from outta town&#8230;</h3>
<p>Today I <a href="http://msdn.safaribooksonline.com/0768666759/ch01lev1sec5">found</a> <code>zip</code> for Arrays.</p>
<pre>
>> keys.<span class=constant>zip</span>(values)
=> [["name", "Dr Nic"], ["description", "Good lookin'"], ["country", "Netherlands"]]
>> hash = Hash[*keys.<span class=constant>zip</span>(values).flatten]
=> {"name"=>"Dr Nic", "country"=>"Netherlands", "description"=>"Good lookin'"}
</pre>
<p>Now I don&#8217;t know which is better. Nor do I know which syntax is cleaner and more meaningful. </p>
<p>Both are as meaningless as each other:</p>
<ul>
<li>How many people remember what <code>transpose</code> means from matrix mathematics at school anyway?</li>
<li>How many people would look at <code>keys.zip(values)</code> and guess what the result will be?</li>
</ul>
<p>Anyone with any thoughts on this?</p>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/08/12/map_by_method-now-works-with-activerecord-associations/' rel='bookmark' title='Permanent Link: map_by_method now works with ActiveRecord associations'>map_by_method now works with ActiveRecord associations</a> <small>I was always annoyed that map_by_method was broken for ActiveRecord...</small></li><li><a href='http://drnicwilliams.com/2006/12/25/my-year-in-cities-2006/' rel='bookmark' title='Permanent Link: My Year in Cities, 2006'>My Year in Cities, 2006</a> <small>This game seemed like fun, so I thought I&#8217;d play....</small></li><li><a href='http://drnicwilliams.com/2006/10/04/i-love-map-by-pluralisation/' rel='bookmark' title='Permanent Link: I love &#8220;map by pluralisation&#8221; [now: map_by_method]'>I love &#8220;map by pluralisation&#8221; [now: map_by_method]</a> <small>Update: this is a gem called map_by_method. The other day...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/10/03/zip-vs-transpose/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Turn-based game DSL</title>
		<link>http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/</link>
		<comments>http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/#comments</comments>
		<pubDate>Thu, 07 Sep 2006 09:28:17 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[BTS]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/</guid>
		<description><![CDATA[Late in the night, whilst the baby feeds, I continue to develop Dr Nic&#8217;s Civilizations game. This led me to develop a DSL for the specification of game rules. You need to see this.
Here&#8217;s an example definition of some terrain:

  class Desert < Terrain
    title       [...]


Related posts:<ol><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li><li><a href='http://drnicwilliams.com/2006/11/20/coming-home-to-brisbane/' rel='bookmark' title='Permanent Link: Coming home to Brisbane'>Coming home to Brisbane</a> <small>I left Australia on the 3rd of July last year...</small></li><li><a href='http://drnicwilliams.com/2006/11/06/post-halloween-radrails-trick-all-textmate-snippets-available/' rel='bookmark' title='Permanent Link: Post-Halloween RadRails trick &#8211; all TextMate snippets available'>Post-Halloween RadRails trick &#8211; all TextMate snippets available</a> <small> HTML snippets 48 Ruby snippets 199 I tease myself...</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Late in the night, whilst the baby feeds, I continue to develop <strong>Dr Nic&#8217;s Civilizations</strong> game. This led me to develop a DSL for the specification of game rules. You need to see this.</p>
<p>Here&#8217;s an example definition of some terrain:</p>
<pre>
  class Desert < Terrain
    title           "Desert"
    letter          "d"
    graphic         "desert"
    movement_cost   1
    defense_bonus   10
    food            0
    shield          1
    trade           0
  end
  class Oasis < Desert
    title           "Oasis"
    special_code    1
    food            3
    shield          1
    trade           0
    graphic         "oasis"
  end
</pre>
<p>An Oasis is a special version of the Desert terrain, so Ruby subclasses offer a compatible relationship.</p>
<p>This is seriously cool. All in Ruby.</p>
<h3>Why write a DSL for something trite like game rules?</h3>
<p>The descriptions of terrain (plains, hills, ocean), the improvements (roads, irrigation, mines), etc. all need defining somewhere. Here are the standard options:</p>
<ol>
<li>Rows in a database, imported into ActiveRecords at startup</li>
<li>Files that are loaded at startup, parsed and converted into an internal data model</li>
<li>Ruby DSL</li>
</ol>
<p>The sort of configuration we're dealing with is static: its a part of the game design to a certain extent. Yes, I could put the configuration in a database and access/modify it via an <a href="http://trac.visualjquery.com/admin_console">admin console</a>, though version control becomes an additional administrative hassle.</p>
<p>Storing game rule configuration in external files makes version control trivial, though there is a one-time cost of implementing special purpose syntax, parsers, internal game data models and testing.</p>
<p>A Ruby DSL is exactly the same as implementing option 2 - the configuration is stored in files, though as the syntax is pure Ruby, there is no need to implement a parser and internal data model. </p>
<p>There was a one time cost for supporting the syntax. But <a href="http://redhanded.hobix.com/">why the lucky stiff</a> paid this cost for me with his <a href="http://poignantguide.net/ruby/chapter-6.html#section3">traits definition for slaying dragons</a> <a href="#game-dsl1">[1]</a>. So I was free and clear of any actual effort.</p>
<h3>"Yes, smart arse, but you still had to write up all those Ruby classes"</h3>
<p>An irrelevant argument, you'd have to enter the configuration for any of the 3 options, but...</p>
<p>I wrote a generator to build the Ruby class definitions for me from the <a href="http://www.freeciv.org/index.php">Freeciv</a>'s GPL rule sets. Sweet.</p>
<p><a name="game-dsl1">[1]</a> The definition of the <code>Terrain</code> class, using the <code>traits</code> mechanism, is simple:</p>
<pre>
  class <span class="constant">Terrain</span>
    <span class="string">traits</span> :title,
      :letter,
      :graphic,
      :movement_cost,
      :defense_bonus,
      :food,
      :shield,
      :trade,
      :special_code
  end
</pre>


<p>Related posts:<ol><li><a href='http://drnicwilliams.com/2007/04/12/magic-multi-connections-a-facility-in-rails-to-talk-to-more-than-one-database-at-a-time/' rel='bookmark' title='Permanent Link: Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;'>Magic Multi-Connections: A &#8220;facility in Rails to talk to more than one database at a time&#8221;</a> <small>At this point in time there’s no facility in Rails...</small></li><li><a href='http://drnicwilliams.com/2006/11/20/coming-home-to-brisbane/' rel='bookmark' title='Permanent Link: Coming home to Brisbane'>Coming home to Brisbane</a> <small>I left Australia on the 3rd of July last year...</small></li><li><a href='http://drnicwilliams.com/2006/11/06/post-halloween-radrails-trick-all-textmate-snippets-available/' rel='bookmark' title='Permanent Link: Post-Halloween RadRails trick &#8211; all TextMate snippets available'>Post-Halloween RadRails trick &#8211; all TextMate snippets available</a> <small> HTML snippets 48 Ruby snippets 199 I tease myself...</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/09/07/turn-based-game-dsl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[Trick] Natural language DSL in Ruby</title>
		<link>http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/</link>
		<comments>http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/#comments</comments>
		<pubDate>Mon, 04 Sep 2006 15:15:29 +0000</pubDate>
		<dc:creator>Dr Nic</dc:creator>
				<category><![CDATA[DSL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Trick]]></category>

		<guid isPermaLink="false">http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/</guid>
		<description><![CDATA[Ever tried to explain DSLs (domain specific languages) to someone, so that they know how wonderful Ruby is, and just run out of useful examples? Try this piece of Street Magic on them&#8230;
The effect
See if your unsuspecting friend can figure out what this code will do. If they can, then say, &#8220;That&#8217;s because you are [...]


Related posts:<ol><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/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li><li><a href='http://drnicwilliams.com/2008/06/11/using-ruby-within-textmate-snippets-and-commands/' rel='bookmark' title='Permanent Link: Using Ruby within TextMate snippets and commands'>Using Ruby within TextMate snippets and commands</a> <small>I didn&#8217;t know you could run Ruby within TextMate snippets....</small></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Ever tried to explain DSLs (domain specific languages) to someone, so that they know how wonderful Ruby is, and just run out of useful examples? Try this piece of Street Magic on them&#8230;</p>
<h2>The effect</h2>
<p>See if your unsuspecting friend can figure out what this code will do. If they can, then say, &#8220;That&#8217;s because you are a domain expert in English. Good for you. Now use Ruby you Java boy.&#8221;</p>
<pre>
>> I.say "<span class="string">I love the Ruby language</span>"
<span class="constant">You said, 'I love the Ruby language'</span>
</pre>
<p>Cool, yes? Yes.</p>
<h2>How this trick works</h2>
<p>To set this up for your unsuspecting Ruby noob, type the following into your console/irb:</p>
<pre>
>> class I; def self.say(text); puts "You said, '#{text}'"; end; end
=> nil
</pre>
<p>Now you have a constant <code>I</code> upon which you can call class methods. </p>
<p>In long hand, this is:</p>
<pre>
class I
  def self.say(text)
    puts "You said, '#{text}'"
  end
end
</pre>
<p>Create other pronoun classes, such as <code>You</code>, <code>Everyone</code>, etc and give them methods representing verbs, such as <code>say</code>, <code>said</code>, <code>want_to</code>. </p>
<p>For example,</p>
<pre>
class You
  def self.cannot(action, target)
    puts "Didn't your mother tell you never say never? Of course you can #{action} #{target}"
  end
end
</pre>
<p>Which delights us with:</p>
<pre>
>> You.cannot <span class="string">:learn</span>, "<span class="string">Ruby</span>"
<span class="constant">Didn't your mother tell you never say never? Of course you can learn Ruby</span>
</pre>
<h2>&#8220;I still don&#8217;t know what a DSL is&#8221;</h2>
<p>That&#8217;s unfortunate for you.</p>


<p>Related posts:<ol><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/07/04/unit-testing-iphone-apps-with-ruby-rbiphonetest/' rel='bookmark' title='Permanent Link: Unit Testing iPhone apps with Ruby: rbiphonetest'>Unit Testing iPhone apps with Ruby: rbiphonetest</a> <small> Everything to love about Ruby: the concise, powerful language;...</small></li><li><a href='http://drnicwilliams.com/2008/06/11/using-ruby-within-textmate-snippets-and-commands/' rel='bookmark' title='Permanent Link: Using Ruby within TextMate snippets and commands'>Using Ruby within TextMate snippets and commands</a> <small>I didn&#8217;t know you could run Ruby within TextMate snippets....</small></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://drnicwilliams.com/2006/09/04/trick-natural-language-dsl/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
