<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
	<title>technicalpickles - Josh Nichols on the Internet</title>

	
	<link href="http://technicalpickles.com/posts.html" type="text/html" />

	<updated>2011-08-02T00:00:00-07:00</updated>
	<author>
		<name>Josh Nichols</name>
		<email>josh@technicalpickles.com</email>
	</author>

	<id>tag:technicalpickles.com,2005:/posts</id>

	
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TechnicalPickles" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="technicalpickles" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
		<title>Rsync an iTunes Library like a boss</title>
		<link href="http://technicalpickles.com/posts/rsync-an-itunes-library-like-a-boss" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/rsync-an-itunes-library-like-a-boss</id>
		<updated>2011-08-02T00:00:00-07:00</updated>
		<content type="html">&lt;h2 id='motivation'&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Shiny new MacBook Air, and I wanted to do this install from scratch (no TimeMachine recovery), but still get the good stuff from my old laptop. Also, rsync is awesome.&lt;/p&gt;

&lt;h2 id='prepare_old_computer'&gt;Prepare old computer&lt;/h2&gt;

&lt;p&gt;On old computer, from iTunes: &lt;code&gt;File -&amp;gt;  Library -&amp;gt; Organize Library&lt;/code&gt; and check &lt;code&gt;Consolidate files&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After this looks like it finished (would be displayed in status area, i.e. song progress), &lt;strong&gt;quit iTunes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;System Preferences&lt;/code&gt;, go to &lt;code&gt;Sharing&lt;/code&gt; and make sure &lt;code&gt;Remote Login&lt;/code&gt; is enabled.&lt;/p&gt;

&lt;p&gt;Make note of this computer&amp;#8217;s IP address. You can use &lt;code&gt;/sbin/ifconfig&lt;/code&gt; or the &lt;code&gt;Network&lt;/code&gt; preferences.&lt;/p&gt;

&lt;h2 id='prepare_new_computer'&gt;Prepare new computer&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Quit iTunes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Backup existing files, just in case:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd ~/Music
mv iTunes iTunes.bak&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='rsync_in_boss_like_fashion'&gt;rsync in boss like fashion:&lt;/h2&gt;

&lt;p&gt;Remember that IP address from earlier? Let&amp;#8217;s pretend it&amp;#8217;s 192.168.1.4 for demonstration.&lt;/p&gt;

&lt;p&gt;On new computer:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd ~/Music
rsync -av --delete 192.168.1.4:Music/iTunes .&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now wait, and have a glass of scotch.&lt;/p&gt;

&lt;h2 id='the_result'&gt;The result&lt;/h2&gt;

&lt;p&gt;Open iTunes on your new computer, and you should have all these things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Music&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playlists&lt;/li&gt;

&lt;li&gt;Song plays&lt;/li&gt;

&lt;li&gt;Ratings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Videos&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Syncability with iPhones/iPods&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='troubleshooting'&gt;Troubleshooting&lt;/h2&gt;

&lt;p&gt;The first time I tried this, it didn&amp;#8217;t recognize anything in the Library. Not sure if these matter, or if the second run was just luckier. In any event, these are things I tried, and are reflected above when it&amp;#8217;s pretty likely to have helped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tried to add existing Library to itself. Cancelled partway through&lt;/li&gt;

&lt;li&gt;On old computer, exported Library using &lt;code&gt;File -&amp;gt; Library -&amp;gt; Export Library&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;Added &amp;#8211;delete to rsync run&lt;/li&gt;

&lt;li&gt;Made sure iTunes wasn&amp;#8217;t running during rsync&lt;/li&gt;
&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=Qfh24_FlQXs:49didowhSOs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=Qfh24_FlQXs:49didowhSOs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=Qfh24_FlQXs:49didowhSOs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=Qfh24_FlQXs:49didowhSOs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=Qfh24_FlQXs:49didowhSOs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=Qfh24_FlQXs:49didowhSOs:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=Qfh24_FlQXs:49didowhSOs:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/Qfh24_FlQXs" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Capybara (and Cucumber) and Domains</title>
		<link href="http://technicalpickles.com/posts/capybara-and-domains" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/capybara-and-domains</id>
		<updated>2011-04-07T00:00:00-07:00</updated>
		<content type="html">&lt;p&gt;While hacking on a new application, it took a good few weeks to find out how to, using &lt;a href='http://cukes.info/'&gt;cucumber&lt;/a&gt; and &lt;a href='https://github.com/jnicklas/capybara'&gt;Capybara&lt;/a&gt;, interact with domains that weren&amp;#8217;t localhost. Consider this a note to my future self :)&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s imagine your Rails application has a parimary domain and allows users to have subdomains (as if, granted by the power of &lt;a href='https://github.com/mbleigh/subdomain-fu'&gt;subdomain-fu&lt;/a&gt;). By default, everything is hitting localhost, for example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;visit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/about&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# =&amp;gt; http://localhost/about&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To get around this, you can tell Capybara to use a different domain:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;Capybara&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_host&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;awesome.com&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;visit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/about&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# =&amp;gt; http://awesome.com/about&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I found it useful to make a step to navigate to a particular domain:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='no'&gt;When&lt;/span&gt; &lt;span class='sr'&gt;/^I visit (.*)$/&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;site_domain&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='n'&gt;site_domain&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;localhost&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;site_domain&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;the main domain&amp;quot;&lt;/span&gt;

  &lt;span class='no'&gt;Capybara&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_host&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;site_domain&lt;/span&gt;
  &lt;span class='n'&gt;visit&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Armed with this, we can write our features:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cucumber'&gt;&lt;span class='k'&gt;Scenario:&lt;/span&gt;&lt;span class='nf'&gt; Visit the main domain&lt;/span&gt;
&lt;span class='k'&gt;  When &lt;/span&gt;&lt;span class='nf'&gt;I visit the main domain&lt;/span&gt;
&lt;span class='nf'&gt;  &lt;/span&gt;&lt;span class='k'&gt;Then &lt;/span&gt;&lt;span class='nf'&gt;I should see information about the main domain&lt;/span&gt;

&lt;span class='k'&gt;Scenario:&lt;/span&gt;&lt;span class='nf'&gt; Visit another domain&lt;/span&gt;
&lt;span class='k'&gt;  When &lt;/span&gt;&lt;span class='nf'&gt;I visit awesome.com&lt;/span&gt;
&lt;span class='nf'&gt;  &lt;/span&gt;&lt;span class='k'&gt;Then &lt;/span&gt;&lt;span class='nf'&gt;I should see awesomeness&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=09b1n6dg_7M:m_uabCLwwcQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=09b1n6dg_7M:m_uabCLwwcQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=09b1n6dg_7M:m_uabCLwwcQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=09b1n6dg_7M:m_uabCLwwcQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=09b1n6dg_7M:m_uabCLwwcQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=09b1n6dg_7M:m_uabCLwwcQ:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=09b1n6dg_7M:m_uabCLwwcQ:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/09b1n6dg_7M" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Rails Permanent Redirects</title>
		<link href="http://technicalpickles.com/posts/rails-permanent-redirects" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/rails-permanent-redirects</id>
		<updated>2011-02-14T00:00:00-08:00</updated>
		<content type="html">&lt;p&gt;I feel silly writing something so short and simple, but horribly outdated information when googling &amp;#8216;rails permanent redirect&amp;#8217; drove me to it. I&amp;#8217;m just hoping the SEO gods smile upon me.&lt;/p&gt;

&lt;p&gt;So, my friends, check it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;redirect_to &amp;quot;http://somewhere.com&amp;quot;, :status =&amp;gt; 301
redirect_to posts_url, :status =&amp;gt; :moved_permanently&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For the curious, &lt;code&gt;:status&lt;/code&gt; &amp;#8220;can either be a standard &lt;a href='http://www.iana.org/assignments/http-status-codes'&gt;HTTP Status code&lt;/a&gt; as an integer, or a symbol representing the downcased, underscored and symbolized description&amp;#8221; (&lt;a href='http://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to'&gt;source&lt;/a&gt;)&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=ZoH2ip_Shso:rk8yM2ZlUxc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=ZoH2ip_Shso:rk8yM2ZlUxc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=ZoH2ip_Shso:rk8yM2ZlUxc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=ZoH2ip_Shso:rk8yM2ZlUxc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=ZoH2ip_Shso:rk8yM2ZlUxc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=ZoH2ip_Shso:rk8yM2ZlUxc:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=ZoH2ip_Shso:rk8yM2ZlUxc:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/ZoH2ip_Shso" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Crosspost: Developing and testing system automation with capistrano-cowboy</title>
		<link href="http://technicalpickles.com/posts/crosspost-developing-and-testing-system-automation-with-capistrano-cowboy" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/crosspost-developing-and-testing-system-automation-with-capistrano-cowboy</id>
		<updated>2010-12-17T00:00:00-08:00</updated>
		<content type="html">&lt;p&gt;Just this morning, I posted an article about &lt;a href='http://blog.railsmachine.com/articles/2010/12/16/developing-and-testing-system-automation-with-capistrano-cowboy/'&gt;developing and testing system automation with capistrano-cowboy&lt;/a&gt; over at the &lt;a href='http://blog.railsmachine.com/'&gt;Rails Machine Blog&lt;/a&gt;. Check it out :)&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=x5lStJeyS04:-8Jalxgl7Jo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=x5lStJeyS04:-8Jalxgl7Jo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=x5lStJeyS04:-8Jalxgl7Jo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=x5lStJeyS04:-8Jalxgl7Jo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=x5lStJeyS04:-8Jalxgl7Jo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=x5lStJeyS04:-8Jalxgl7Jo:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=x5lStJeyS04:-8Jalxgl7Jo:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/x5lStJeyS04" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Jeweler 1.5.0</title>
		<link href="http://technicalpickles.com/posts/jeweler-1-5-0" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/jeweler-1-5-0</id>
		<updated>2010-11-13T00:00:00-08:00</updated>
		<content type="html">&lt;p&gt;It&amp;#8217;s been awhile, dear reader. After a lull in development, Jeweler 1.5.1 is finally released. I spent a lot of time cleaning up and revising the README, so I&amp;#8217;m just going to put that right here. It tells the story of going from 0 to jewelered, so I don&amp;#8217;t think it&amp;#8217;s a cop out :)&lt;/p&gt;

&lt;h1 id='jeweler_craft_the_perfect_rubygem'&gt;Jeweler: Craft the perfect RubyGem&lt;/h1&gt;

&lt;p&gt;Jeweler provides the noble ruby developer with two primary features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a library for managing and releasing RubyGem projects&lt;/li&gt;

&lt;li&gt;a scaffold generator for starting new RubyGem projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='hello_world'&gt;Hello, world&lt;/h2&gt;

&lt;p&gt;Use RubyGems to install the heck out of jeweler to get started:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install jeweler&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With jeweler installed, you can use the &lt;code&gt;jeweler&lt;/code&gt; command to generate a new project. For the most basic use, just give it a name:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ jeweler hello-gem&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This requires some Git configuration (like name, email, GitHub account, etc), but &lt;code&gt;jeweler&lt;/code&gt; will prompt along the way.&lt;/p&gt;

&lt;p&gt;Your new &lt;code&gt;hello-gem&lt;/code&gt; gem is ready in the &lt;code&gt;hello-gem&lt;/code&gt; directory. Take a peek, and you&amp;#8217;ll see several files and directories&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Rakefile&lt;/code&gt; setup for jeweler, running tests, generating documentation, and releasing to &lt;a href='http://rubygems.org/'&gt;rubygems.org&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;README.rdoc&lt;/code&gt; with contribution guidelines and copyright info crediting you&lt;/li&gt;

&lt;li&gt;&lt;code&gt;LICENSE&lt;/code&gt; with the MIT licensed crediting you&lt;/li&gt;

&lt;li&gt;&lt;code&gt;Gemfile&lt;/code&gt; with development dependencies filled in&lt;/li&gt;

&lt;li&gt;&lt;code&gt;lib/hello-gem.rb&lt;/code&gt; waiting for you to code&lt;/li&gt;

&lt;li&gt;&lt;code&gt;test/&lt;/code&gt; containing a (failing) shoulda test suite &lt;a href='http://github.com/thoughtbot/shoulda'&gt;shoulda&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='more__options'&gt;More &lt;code&gt;jeweler&lt;/code&gt; options&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;jeweler&lt;/code&gt; command supports a lot of options. Mostly, they are for generating baked in support for this test framework, or that.&lt;/p&gt;

&lt;p&gt;Check out &lt;code&gt;jeweler --help&lt;/code&gt; for the most up to date options.&lt;/p&gt;

&lt;h2 id='hello_rake_tasks'&gt;Hello, rake tasks&lt;/h2&gt;

&lt;p&gt;Beyond just editing source code, you&amp;#8217;ll be interacting with your gem using &lt;code&gt;rake&lt;/code&gt; a lot. To see all the tasks available with a brief description, you can run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake -T&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll need a version before you can start installing your gem locally. The easiest way is with the &lt;code&gt;version:write&lt;/code&gt; Rake task. Let&amp;#8217;s imagine you start with 0.1.0&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake version:write MAJOR=0 MINOR=1 PATCH=0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can now go forth and develop, now that there&amp;#8217;s an initial version defined. Eventually, you should install and test the gem:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake install&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;install&lt;/code&gt; rake task builds the gem and &lt;code&gt;gem install&lt;/code&gt;s it. You&amp;#8217;re all set if you&amp;#8217;re using &lt;a href='http://rvm.beginrescueend.com/'&gt;RVM&lt;/a&gt;, but you may need to run it with sudo if you have a system-installed ruby:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo rake install&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='releasing'&gt;Releasing&lt;/h3&gt;

&lt;p&gt;At last, it&amp;#8217;s time to &lt;a href='http://img.skitch.com/20100310-nrgxbwqm58tibiq2un6mujqmm5.png'&gt;ship it&lt;/a&gt;! Make sure you have everything committed and pushed, then go wild:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake release&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate &lt;code&gt;hello-gem.gemspec&lt;/code&gt; and commit it&lt;/li&gt;

&lt;li&gt;Use &lt;code&gt;git&lt;/code&gt; to tag &lt;code&gt;v0.1.0&lt;/code&gt; and push it&lt;/li&gt;

&lt;li&gt;Build &lt;code&gt;hello-gem-0.1.0.gem&lt;/code&gt; and push it to &lt;a href='http://rubygems.org/gems/'&gt;rubygems.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='version_bumping'&gt;Version bumping&lt;/h3&gt;

&lt;p&gt;It feels good to release code. Do it, do it often. But before that, bump the version. Then release it. There&amp;#8217;s a few ways to update the version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# version:write like before
$ rake version:write MAJOR=0 MINOR=3 PATCH=0

# bump just major, ie 0.1.0 -&amp;gt; 1.0.0
$ rake version:bump:major

# bump just minor, ie 0.1.0 -&amp;gt; 0.2.0
$ rake version:bump:minor

# bump just patch, ie 0.1.0 -&amp;gt; 0.1.1
$ rake version:bump:patch&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then it&amp;#8217;s the same &lt;code&gt;release&lt;/code&gt; we used before:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake release&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='customizing_your_gem'&gt;Customizing your gem&lt;/h2&gt;

&lt;p&gt;If you&amp;#8217;ve been following along so far, your gem is just a blank slate. You&amp;#8217;re going to need to make it colorful and full of metadata.&lt;/p&gt;

&lt;p&gt;You can customize your gem by updating your &lt;code&gt;Rakefile&lt;/code&gt;. With a newly generated project, it will look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require &amp;#39;jeweler&amp;#39;
Jeweler::Tasks.new do |gem|
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
  gem.name = &amp;quot;whatwhatwhat&amp;quot;
  gem.summary = %Q{TODO: one-line summary of your gem}
  gem.description = %Q{TODO: longer description of your gem}
  gem.email = &amp;quot;josh@technicalpickles.com&amp;quot;
  gem.homepage = &amp;quot;http://github.com/technicalpickles/whatwhatwhat&amp;quot;
  gem.authors = [&amp;quot;Joshua Nichols&amp;quot;]
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s crucial to understand the &lt;code&gt;gem&lt;/code&gt; object is just a Gem::Specification. You can read up about it at &lt;a href='http://docs.rubygems.org/read/chapter/20'&gt;docs.rubygems.org/read/chapter/20&lt;/a&gt;. This is the most basic way of specifying a gem, Jeweler-managed or not. Jeweler just exposes this to you, in addition to providing some reasonable defaults, which we&amp;#8217;ll explore now.&lt;/p&gt;

&lt;h3 id='project_information'&gt;Project information&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;gem.name = &amp;quot;whatwhatwhat&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Every gem has a name. Among other things, the gem name is how you are able to &lt;code&gt;gem install&lt;/code&gt; it. &lt;a href='http://docs.rubygems.org/read/chapter/20#name'&gt;Reference&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.summary = %Q{TODO: longer description of your gem}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a one line summary of your gem. This is displayed, for example, when you use &lt;code&gt;gem list --details&lt;/code&gt; or view it on &lt;a href='http://rubygems.org/gems/'&gt;rubygems.org&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.description = %Q{TODO: longer description of your gem}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Description is a longer description. Scholars ascertain that knowledge of where the description is used was lost centuries ago.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.email = &amp;quot;josh@technicalpickles.com&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This should be a way to get a hold of you regarding the gem.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.homepage = &amp;quot;http://github.com/technicalpickles/whatwhatwhat&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The homepage should have more information about your gem. The jeweler generator guesses this based on the assumption your code lives on &lt;a href='http://github.com/'&gt;GitHub&lt;/a&gt;, using your Git configuration to find your GitHub username. This is displayed by &lt;code&gt;gem list --details&lt;/code&gt; and on rubygems.org.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.authors = [&amp;quot;Joshua Nichols&amp;quot;]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hey, this is you, the author (or me in this case). The &lt;code&gt;jeweler&lt;/code&gt; generator also guesses this from your Git configuration. This is displayed by &lt;code&gt;gem list --details&lt;/code&gt; and on rubygems.org.&lt;/p&gt;

&lt;h3 id='files'&gt;Files&lt;/h3&gt;

&lt;p&gt;The quickest way to add more files is to &lt;code&gt;git add&lt;/code&gt; them. Jeweler uses your Git repository to populate your gem&amp;#8217;s files by including added and committed and excluding &lt;code&gt;.gitignore&lt;/code&gt;d. In most cases, this is reasonable enough.&lt;/p&gt;

&lt;p&gt;If you need to tweak the files, that&amp;#8217;s cool. Jeweler populates &lt;code&gt;gem.files&lt;/code&gt; as a &lt;code&gt;Rake::FileList&lt;/code&gt;. It&amp;#8217;s like a normal array, except you can &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt; file globs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.files.exclude &amp;#39;tmp&amp;#39; # exclude temporary directory
gem.files.include &amp;#39;lib/foo/bar.rb&amp;#39; # explicitly include lib/foo/bar.rb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If that&amp;#8217;s not enough, you can just set &lt;code&gt;gem.files&lt;/code&gt; outright&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.files = Dir.glob(&amp;#39;lib/**/*.rb&amp;#39;)&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='dependencies'&gt;Dependencies&lt;/h3&gt;

&lt;p&gt;Dependencies let you define other gems that your gem needs to function. &lt;code&gt;gem install your-gem&lt;/code&gt; will install your-gem&amp;#8217;s dependencies along with it, and when you use your-gem in an application, the dependencies will be made available. Use &lt;code&gt;gem.add_dependency&lt;/code&gt; to register them. &lt;a href='http://docs.rubygems.org/read/chapter/20#dependencies'&gt;Reference&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.add_dependency &amp;#39;nokogiri&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will ensure a version of &lt;code&gt;nokogiri&lt;/code&gt; is installed, but it doesn&amp;#8217;t require anything more than that. You can provide extra args to be more specific:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.add_dependency &amp;#39;nokogiri&amp;#39;, &amp;#39;= 1.2.1&amp;#39; # exactly version 1.2.1
gem.add_dependency &amp;#39;nokogiri&amp;#39;, &amp;#39;&amp;gt;= 1.2.1&amp;#39; # greater than or equal to 1.2.1, ie, 1.2.1, 1.2.2, 1.3.0, 2.0.0, etc
gem.add_dependency &amp;#39;nokogiri&amp;#39;, &amp;#39;&amp;gt;= 1.2.1&amp;#39;, &amp;#39;&amp;lt; 1.3.0&amp;#39; # greater than or equal to 1.2.1, but less than 1.3.0
gem.add_dependency &amp;#39;nokogiri&amp;#39;, &amp;#39;~&amp;gt; 1.2.1&amp;#39; # same thing, but more concise&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When specifying which version is required, there&amp;#8217;s a bit of the condunrum. You want to allow the most versions possible, but you want to be sure they are compatible. Using &lt;code&gt;&amp;gt;= 1.2.1&lt;/code&gt; is fine most of the time, except until the point that 2.0.0 comes out and totally breaks backwards the API. That&amp;#8217;s when it&amp;#8217;s good to use &lt;code&gt;~&amp;gt; 1.2.1&lt;/code&gt;, which requires any version in the &lt;code&gt;1.2&lt;/code&gt; family, starting with &lt;code&gt;1.2.1&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id='executables'&gt;Executables&lt;/h3&gt;

&lt;p&gt;Executables let your gem install shell commands. Just put any executable scripts in the &lt;code&gt;bin/&lt;/code&gt; directory, make sure they are added using &lt;code&gt;git&lt;/code&gt;, and Jeweler will take care of the rest.&lt;/p&gt;

&lt;p&gt;When you need more finely grained control over it, you can set it yourself:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.executables = [&amp;#39;foo&amp;#39;] # note, it&amp;#39;s the file name relative to `bin/`, not the project root&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='versioning'&gt;Versioning&lt;/h3&gt;

&lt;p&gt;We discussed earlier how to bump the version. The rake tasks are really just convience methods for manipulating the &lt;code&gt;VERSION&lt;/code&gt; file. It just contains a version string, like &lt;code&gt;1.2.3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;VERSION&lt;/code&gt; is a convention used by Jeweler, and is used to populate &lt;code&gt;gem.version&lt;/code&gt;. You can actually set this yourself, and Jeweler won&amp;#8217;t try to override it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gem.version = &amp;#39;1.2.3&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A common pattern is to have this in a version constant in your library. This is convenient, because users of the library can query the version they are using at runtime.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# in lib/foo/version.rb
class Foo
  module Version
    MAJOR = 1
    MINOR = 2
    PATCH = 3
    BUILD = &amp;#39;pre3&amp;#39;

    STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join(&amp;#39;.&amp;#39;)
  end
end

# in Rakefile
require &amp;#39;jeweler&amp;#39;
require &amp;#39;./lib/foo/version.rb&amp;#39;
Jeweler::Tasks.new do |gem|
  # snip
  gem.version = Foo::Version::STRING
end&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='rake_tasks'&gt;Rake tasks&lt;/h3&gt;

&lt;p&gt;Jeweler lives inside of Rake. As a result, they are dear friends. But, that friendship doesn&amp;#8217;t interfere with typical Rake operations.&lt;/p&gt;

&lt;p&gt;That means you can define your own namespaces, tasks, or use third party Rake libraries without cause for concern.&lt;/p&gt;

&lt;h2 id='contributing_to_jeweler'&gt;Contributing to Jeweler&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check out the latest master to make sure the feature hasn&amp;#8217;t been implemented or the bug hasn&amp;#8217;t been fixed yet&lt;/li&gt;

&lt;li&gt;Check out the &lt;a href='http://github.com/technicalpickles/jeweler/issues'&gt;issue tracker&lt;/a&gt; to make sure someone already hasn&amp;#8217;t requested it and/or contributed it&lt;/li&gt;

&lt;li&gt;Fork the project&lt;/li&gt;

&lt;li&gt;Start a feature/bugfix branch&lt;/li&gt;

&lt;li&gt;Commit and push until you are happy with your contribution&lt;/li&gt;

&lt;li&gt;Make sure to add tests for the feature/bugfix. This is important so I don&amp;#8217;t break it in a future version unintentionally.&lt;/li&gt;

&lt;li&gt;Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate it to its own commit so I can cherry-pick around it.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=O6l9U1nybtk:YNFBok9gWIs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=O6l9U1nybtk:YNFBok9gWIs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=O6l9U1nybtk:YNFBok9gWIs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=O6l9U1nybtk:YNFBok9gWIs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=O6l9U1nybtk:YNFBok9gWIs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=O6l9U1nybtk:YNFBok9gWIs:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=O6l9U1nybtk:YNFBok9gWIs:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/O6l9U1nybtk" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Never Leave Your Dotfiles Behind Again With Homesick</title>
		<link href="http://technicalpickles.com/posts/never-leave-your-dotfiles-behind-again-with-homesick" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/never-leave-your-dotfiles-behind-again-with-homesick</id>
		<updated>2010-03-31T00:00:00-07:00</updated>
		<content type="html">&lt;p&gt;I was on a server the other day, and was getting a little weepy. I missed my dotfiles. The thought of doing this manually, especially on multiple servers, was even worse than the homesickness I had. Basically, I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A convention for laying out dotfiles repos&lt;/li&gt;

&lt;li&gt;A command to clone my dotfiles from git&lt;/li&gt;

&lt;li&gt;A command to symlink the files into my home directory&lt;/li&gt;

&lt;li&gt;A delicious scotch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lots of folks, myself included, have started sharing their configuration files, ie &lt;code&gt;.vimrc&lt;/code&gt;, &lt;code&gt;.bashrc&lt;/code&gt;, and &lt;code&gt;.screenrc&lt;/code&gt;, on &lt;a href='http://github.com'&gt;GitHub&lt;/a&gt; and elsewhere. Sometimes though, I think they are really more for personal backup and maybe to just share tips and tricks, rather than share them for consumption by others.&lt;/p&gt;

&lt;p&gt;Why would I say such a thing? Well, let&amp;#8217;s say you found someone that has put together the ultimate set vim configuration. How would you go about using them?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;git clone whatever&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Peek into the repo, try to figure out how it&amp;#8217;s laid out and where the config files are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are the files at the top level of the repo?&lt;/li&gt;

&lt;li&gt;Do they include the dot in the file name, ie &lt;code&gt;.vimrc&lt;/code&gt;, or exclude it so it&amp;#8217;s easier to see when doing &lt;code&gt;ls&lt;/code&gt;, ie &lt;code&gt;vimrc&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Symlink the files into your home directory&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After deliberating and coding for an evening, I had something to show for my troubles: &lt;a href='http://github.com/technicalpickles/homesick'&gt;homesick&lt;/a&gt;. Basically, it provides what I just described, less the scotch.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install homesick
$ homesick clone git://github.com/technicalpickles/pickled-vim.git
   git clone  git://github.com/technicalpickles/pickled-vim.git to /Users/technicalpickles/.homesick/repos/pickled-vim
$ homesick list
 pickled-vim  git://github.com/technicalpickles/pickled-vim.git
$ homesick symlink pickled-vim
     symlink  /Users/technicalpickles/.homesick/repos/pickled-vim/home/.gvimrc to /Users/technicalpickles/.gvimrc
     symlink  /Users/technicalpickles/.homesick/repos/pickled-vim/home/.vim to /Users/technicalpickles/.vim
     symlink  /Users/technicalpickles/.homesick/repos/pickled-vim/home/.vimrc to /Users/technicalpickles/.vimrc&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;homesick assumes a few things about the repos it clones and how to symlink files from them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It&amp;#8217;s a git repo (duh)&lt;/li&gt;

&lt;li&gt;It contains a &lt;code&gt;home&lt;/code&gt; directory&lt;/li&gt;

&lt;li&gt;&lt;code&gt;home&lt;/code&gt; contain any number of dotfiles, including the &lt;code&gt;.&lt;/code&gt; prefix&lt;/li&gt;

&lt;li&gt;Any file in &lt;code&gt;home&lt;/code&gt; will be symlinked into the current user&amp;#8217;s home directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;homesick uses &lt;a href='http://github.com/wycats/thor'&gt;thor&lt;/a&gt; under the hood, which provides a number of advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pretty, pretty colors&lt;/li&gt;

&lt;li&gt;Simple parsing of commandline arguments&lt;/li&gt;

&lt;li&gt;Helper methods for creating files, directories, etc&lt;/li&gt;

&lt;li&gt;Builtin support for running the command without output, or only pretending to run the commands, or forcing the commands no matter what the cost&lt;/li&gt;

&lt;li&gt;Ease to add new &amp;#8216;commands&amp;#8217;, ie &lt;code&gt;symlink&lt;/code&gt;, &lt;code&gt;clone&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;Conflict resolution when files already exist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, I&amp;#8217;m pretty happy where homesick is right now. It does what I wanted it to do, and looks pretty while doing so, so I can&amp;#8217;t really complain.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=eac4OxcryCY:WbedzXMZoKo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=eac4OxcryCY:WbedzXMZoKo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=eac4OxcryCY:WbedzXMZoKo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=eac4OxcryCY:WbedzXMZoKo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=eac4OxcryCY:WbedzXMZoKo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=eac4OxcryCY:WbedzXMZoKo:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=eac4OxcryCY:WbedzXMZoKo:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/eac4OxcryCY" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>A Pattern For Using Standard In And Out In Your Ruby Code</title>
		<link href="http://technicalpickles.com/posts/a-pattern-for-using-standard-in-and-out-in-your-ruby-code" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/a-pattern-for-using-standard-in-and-out-in-your-ruby-code</id>
		<updated>2009-12-13T00:00:00-08:00</updated>
		<content type="html">&lt;p&gt;If you think about it, programming is really about taking some input from a user, and displaying some output back to them. When we&amp;#8217;re down at the command line, this usually means reading from the standard input and writing to the standard output.&lt;/p&gt;

&lt;p&gt;In ruby, you&amp;#8217;ll see code that interacts with standard in and standard out like so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;MyApp&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;prompt_user&lt;/span&gt; 
    &lt;span class='n'&gt;user_selection&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;gets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chomp&lt;/span&gt;             &lt;span class='c1'&gt;# =&amp;gt; &amp;#39;ponies&amp;#39;&lt;/span&gt;
    &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;User selected: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;user_selection&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# Displays User selected: ponies&lt;/span&gt;
    &lt;span class='n'&gt;user_selection&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sadly though, when it comes testing, usually the input/output stuff is glossed over. Why though?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extraneous output is often generated during testing&lt;/li&gt;

&lt;li&gt;It&amp;#8217;s hard to specify what stdin returns and verify what stdout displays back to the user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;#8220;Don&amp;#8217;t let not having the tools be your trepidation&amp;#8230; I will never make a criticism if I don&amp;#8217;t have a resolution.&amp;#8221; - &lt;a href='http://www.youtube.com/watch?v=4YBxeDN4tbk'&gt;Joel Bauer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Allow me, then, to outline a pattern for using standard input and standard output in your Ruby code in a way that&amp;#8217;s testable.&lt;/p&gt;

&lt;p&gt;First off, don&amp;#8217;t use just &amp;#8216;puts&amp;#8217; and &amp;#8216;gets&amp;#8217; by themselves. If you check out the &lt;a href='http://ruby-doc.org/core/classes/Kernel.html#M005954'&gt;rdoc for &lt;code&gt;Kernel&lt;/code&gt;&lt;/a&gt;, you&amp;#8217;ll see that these are just shorthand for &lt;code&gt;$stdout.puts&lt;/code&gt; and &lt;code&gt;$stdin.gets&lt;/code&gt;. So we&amp;#8217;ll change our code to be more like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;MyApp&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;prompt_user&lt;/span&gt; 
    &lt;span class='n'&gt;user_selection&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vg'&gt;$stdin&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chomp&lt;/span&gt;              &lt;span class='c1'&gt;# =&amp;gt; &amp;#39;ponies&amp;#39;&lt;/span&gt;
    &lt;span class='vg'&gt;$stdout&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;User selected: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;user_selection&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# Displays User selected: ponies&lt;/span&gt;
    &lt;span class='n'&gt;user_selection&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tests still pass, right? Alright, next we&amp;#8217;re going to create some &lt;code&gt;attr_accessor&lt;/code&gt;s on &lt;code&gt;MyApp&lt;/code&gt; for the input/output. By default, we&amp;#8217;ll make them point at &lt;code&gt;$stdin&lt;/code&gt; and &lt;code&gt;$stdout&lt;/code&gt; so they&amp;#8217;ll work as expected by default, but during your tests&amp;#8230; well, we&amp;#8217;ll get to that in a minute.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;MyApp&lt;/span&gt;
  &lt;span class='kp'&gt;attr_accessor&lt;/span&gt; &lt;span class='ss'&gt;:input&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:output&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;initialize&lt;/span&gt;
    &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;input&lt;/span&gt;  &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vg'&gt;$stdin&lt;/span&gt;
    &lt;span class='nb'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;output&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vg'&gt;$stdout&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;prompt_user&lt;/span&gt; 
    &lt;span class='n'&gt;user_selection&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;input&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;gets&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;chomp&lt;/span&gt;              &lt;span class='c1'&gt;# =&amp;gt; &amp;#39;ponies&amp;#39;&lt;/span&gt;
    &lt;span class='n'&gt;output&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;User selected: &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;user_selection&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt; &lt;span class='c1'&gt;# Displays User selected: ponies&lt;/span&gt;
    &lt;span class='n'&gt;user_selection&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we&amp;#8217;re setup to test this proper like.&lt;/p&gt;

&lt;p&gt;But first, we need a little background on &lt;code&gt;$stdin&lt;/code&gt; and &lt;code&gt;$stdout&lt;/code&gt;. If you pop up an &lt;code&gt;irb&lt;/code&gt; session and enter &lt;code&gt;$stdout.class&lt;/code&gt;, you&amp;#8217;ll see its is &lt;a href='http://ruby-doc.org/core/classes/IO.html'&gt;IO&lt;/a&gt;. I&amp;#8217;m not going to go into much more detail, but suffice to say, &lt;a href='http://ruby-doc.org/core/classes/StringIO.html'&gt;StringIO&lt;/a&gt; exists as a way to make an &lt;code&gt;IO&lt;/code&gt; that you can muck around with more easily for testing. To provide input to &lt;code&gt;StringIO&lt;/code&gt;, you pass a string to its constructor. To check the output to &lt;code&gt;StringIO&lt;/code&gt;, use the &lt;code&gt;string&lt;/code&gt; method to return it. Knowing that, we can test it now:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;describe&lt;/span&gt; &lt;span class='no'&gt;MyApp&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;prompt_user&amp;quot;&lt;/span&gt;
  &lt;span class='n'&gt;before&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
    &lt;span class='vi'&gt;@my_app&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;MyApp&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;

    &lt;span class='vi'&gt;@input&lt;/span&gt;  &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;StringIO&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;ponies&lt;/span&gt;&lt;span class='se'&gt;\n&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='vi'&gt;@output&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;StringIO&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;

    &lt;span class='vi'&gt;@my_app&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;input&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vi'&gt;@input&lt;/span&gt;
    &lt;span class='vi'&gt;@my_app&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;output&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vi'&gt;@output&lt;/span&gt;

    &lt;span class='vi'&gt;@user_selection&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='vi'&gt;@my_app&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;prompt_user&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='n'&gt;it&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;should output the user&amp;#39;s input&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
    &lt;span class='vi'&gt;@output&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;string&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='o'&gt;=~&lt;/span&gt; &lt;span class='sr'&gt;/ponies/&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='n'&gt;it&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;should return the user&amp;#39;s selection&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
    &lt;span class='vi'&gt;@user_selection&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ponies&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there we go: ruby code using stdin and stdout that we&amp;#8217;re able to test easily.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=1CHhijGNsDI:peZQ9Gkb-PI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=1CHhijGNsDI:peZQ9Gkb-PI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=1CHhijGNsDI:peZQ9Gkb-PI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=1CHhijGNsDI:peZQ9Gkb-PI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=1CHhijGNsDI:peZQ9Gkb-PI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=1CHhijGNsDI:peZQ9Gkb-PI:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=1CHhijGNsDI:peZQ9Gkb-PI:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/1CHhijGNsDI" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Managing binaries of your gem with Jeweler</title>
		<link href="http://technicalpickles.com/posts/managing-binaries-with-jeweler" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/managing-binaries-with-jeweler</id>
		<updated>2009-11-18T00:00:00-08:00</updated>
		<content type="html">&lt;p&gt;It&amp;#8217;s pretty useful to inclue a binary with your gems. Maybe it generates something. Or perhaps it&amp;#8217;s what your gem is all about. Regardless, adding a binary to your gem is almost effortless.&lt;/p&gt;

&lt;p&gt;Basically, it plays out like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;code&gt;bin&lt;/code&gt; directory&lt;/li&gt;

&lt;li&gt;Make a ruby script in the &lt;code&gt;bin&lt;/code&gt; directory (I&amp;#8217;ll provide an example in a second)&lt;/li&gt;

&lt;li&gt;Make the ruby script executable&lt;/li&gt;

&lt;li&gt;Regenerate the gemspec with &lt;code&gt;rake gemspec&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;git add&lt;/code&gt; and &lt;code&gt;git commit&lt;/code&gt; the executable and gemspec&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that we don&amp;#8217;t actually touch the &lt;code&gt;Rakefile&lt;/code&gt; to update the gemspec &lt;code&gt;Jeweler::Tasks&lt;/code&gt;. Under the hood, Jeweler checks the &lt;code&gt;bin&lt;/code&gt; directory and populates the &lt;a href='http://docs.rubygems.org/read/chapter/20#executables'&gt;executables&lt;/a&gt; section of the gemspec accordingly.&lt;/p&gt;

&lt;h2 id='an_example_binary'&gt;An example binary&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s use the &lt;code&gt;jeweler&lt;/code&gt; binary as a template. A few goals I have are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It should be runnable regardless of where ruby is on the path&lt;/li&gt;

&lt;li&gt;It should be runnable from within the project directory, and NOT have to be installed&lt;/li&gt;

&lt;li&gt;It should be a good unix citizen and return an appropriate exit code&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;#!/usr/bin/env ruby&lt;/span&gt;
&lt;span class='vg'&gt;$LOAD_PATH&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unshift&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;join&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='bp'&gt;__FILE__&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;..&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;lib&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;jeweler/generator&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;exit&lt;/span&gt; &lt;span class='ss'&gt;Jeweler&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='ss'&gt;:Generator&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Application&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run!&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='no'&gt;ARGV&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On line 1, we have a shebang. &lt;code&gt;/usr/bin/env ruby&lt;/code&gt; basically finds any executable in the &lt;code&gt;PATH&lt;/code&gt;, and executes that.&lt;/p&gt;

&lt;p&gt;On line 2, we manipulate the the &lt;code&gt;LOAD_PATH&lt;/code&gt; so that the lib directory is searched first. This lets us just run &lt;code&gt;bin/jeweler&lt;/code&gt; and have it load this copy of jeweler, rather than using the installed rubygems&lt;/p&gt;

&lt;p&gt;On line 3, we require the code we&amp;#8217;re going to be using.&lt;/p&gt;

&lt;p&gt;Lastly, on line 4, we call the the &lt;code&gt;run!&lt;/code&gt; method. This takes the arguments passed to the binary, does stuff, and eventually returns an integer. &lt;code&gt;exit&lt;/code&gt; then, uh, exists, with this as the exit code.&lt;/p&gt;

&lt;p&gt;I like this particular approach because it&amp;#8217;s a lot easier to test a method on class returning something, than it is to stub out &lt;code&gt;exit&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='straying_from_the_defaults'&gt;Straying from the defaults&lt;/h2&gt;

&lt;p&gt;Maybe you don&amp;#8217;t like there automatically being stuff. Perhaps there&amp;#8217;s stuff that you that&amp;#8217;s only for development. Or something super secret. The trick here is to modify &lt;code&gt;executables&lt;/code&gt; in your &lt;code&gt;Rakefile&lt;/code&gt;&amp;#8217;s &lt;code&gt;Jeweler::Tasks&lt;/code&gt;. For example, you could go:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='ss'&gt;Jeweler&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='ss'&gt;:Tasks&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;gem&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='c1'&gt;# The plebs aren&amp;#39;t ready for super-jeweler yet...&lt;/span&gt;
  &lt;span class='n'&gt;gem&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;executables&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;jeweler&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='c1'&gt;# note, this is just the file name, not the full path inside of bin&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=LVgaDM1RDDE:3kMk_pKAxpE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=LVgaDM1RDDE:3kMk_pKAxpE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=LVgaDM1RDDE:3kMk_pKAxpE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=LVgaDM1RDDE:3kMk_pKAxpE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=LVgaDM1RDDE:3kMk_pKAxpE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=LVgaDM1RDDE:3kMk_pKAxpE:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=LVgaDM1RDDE:3kMk_pKAxpE:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/LVgaDM1RDDE" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Some jeweler resources you probably didn't know about</title>
		<link href="http://technicalpickles.com/posts/some-jeweler-resources-you-probably-didnt-know-about" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/some-jeweler-resources-you-probably-didnt-know-about</id>
		<updated>2009-11-03T00:00:00-08:00</updated>
		<content type="html">&lt;p&gt;If you&amp;#8217;ve been using &lt;a href='http://technicalpickles'&gt;jeweler&lt;/a&gt; for awhile or are just starting out, there are a few resources you should be aware of. I admit, maybe I&amp;#8217;ve been a little undervocal about their existence. Anyways, here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href='http://github.com/technicalpickles/jeweler/blob/master/README.markdown'&gt;README&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;The &lt;a href='http://wiki.github.com/technicalpickles/jeweler'&gt;Wiki&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;The &lt;a href='http://github.com/technicalpickles/jeweler/issues'&gt;Issue Tracker&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;The &lt;a href='irc://irc.freenode.net/jeweler'&gt;IRC Channel&lt;/a&gt; (#jeweler on irc.freenode.net)&lt;/li&gt;

&lt;li&gt;The &lt;a href='http://groups.google.com/group/jeweler-rb'&gt;Mailing List&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://wiki.github.com/technicalpickles/jeweler/projects-using-jeweler'&gt;Projects using jeweler&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;The &lt;a href='irc://irc.freenode.net/jeweler'&gt;RDoc&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;The &lt;a href='github.com/technicalpickles/jeweler'&gt;Source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IF you have questions or whatnot, I&amp;#8217;d suggest trying these resources out in that order.&lt;/p&gt;

&lt;p&gt;For the IRC channel, I&amp;#8217;ll try to be available when I can. If a particular question/issue might take more than a bit to deal with, there&amp;#8217;s a good chance I&amp;#8217;ll direct you to post an ticket on the &lt;a href='http://github.com/technicalpickles/jeweler/issues'&gt;Issue Tracker&lt;/a&gt; or to post on the &lt;a href='http://groups.google.com/group/jeweler-rb'&gt;Mailing List&lt;/a&gt; for a less synchronous response.&lt;/p&gt;

&lt;p&gt;As for the &lt;a href='http://github.com/technicalpickles/jeweler/issues'&gt;Issue Tracker&lt;/a&gt; and &lt;a href='http://groups.google.com/group/jeweler-rb'&gt;Mailing List&lt;/a&gt;, I&amp;#8217;ll try to respond as a quickly as is reasonable with stuff like &amp;#8216;Hmm, yes, this is definitely a bug&amp;#8217; or &amp;#8216;Could you elaborate a bit more?&amp;#8217; or &amp;#8216;Ah, you probably want to take a look at this documentation&amp;#8217; or &amp;#8216;Oh, that works, it&amp;#8217;s just not documented well yet&amp;#8217;.&lt;/p&gt;

&lt;p&gt;Also, I&amp;#8217;d like to note that sending email or GitHub messages directly to me is probably not the way to work things out. I only say this because they tend to get lost in my inbox, and when I go to work on jeweler, the places I check are almost always going to be the &lt;a href='http://github.com/technicalpickles/jeweler/issues'&gt;Issue Tracker&lt;/a&gt; and &lt;a href='http://groups.google.com/group/jeweler-rb'&gt;Mailing List&lt;/a&gt;. So, don&amp;#8217;t be offended if I end up forwarding your questions to the mailing list and answer them there. I&amp;#8217;m doing this mostly for public archival and accountability.&lt;/p&gt;

&lt;p&gt;I guess that&amp;#8217;s it. Open the flood gates, and I&amp;#8217;ll see how long I can manage this&amp;#8230;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=cKnbGDhy2Gs:vsvnPzmbCdo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=cKnbGDhy2Gs:vsvnPzmbCdo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=cKnbGDhy2Gs:vsvnPzmbCdo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=cKnbGDhy2Gs:vsvnPzmbCdo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=cKnbGDhy2Gs:vsvnPzmbCdo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=cKnbGDhy2Gs:vsvnPzmbCdo:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=cKnbGDhy2Gs:vsvnPzmbCdo:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/cKnbGDhy2Gs" height="1" width="1"/&gt;</content>
	</entry>
	
	<entry>
		<title>Spelunking your Ruby install's configuration with RbConfig</title>
		<link href="http://technicalpickles.com/posts/spelunking-your-ruby-installs-configuration-with-rbconfig" rel="alternate" type="text/html" />
		<id>http://technicalpickles.com/posts/spelunking-your-ruby-installs-configuration-with-rbconfig</id>
		<updated>2009-11-01T00:00:00-07:00</updated>
		<content type="html">&lt;p&gt;Let me tell you, there is this thing called RbConfig, and it has a treasure trove of information about the configuration of your Ruby installation. Even better is that it comes as part of a stock Ruby installation, so no addition gems are required.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s a quick example: I need to know the operating system my ruby code is running, and react accordingly.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rbconfig&amp;#39;&lt;/span&gt;

&lt;span class='c1'&gt;# snip my otherwise flawless code&lt;/span&gt;
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='ss'&gt;RbConfig&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='ss'&gt;:CONFIG&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;host_os&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=~&lt;/span&gt; &lt;span class='sr'&gt;/mswin|windows|cygwin/i&lt;/span&gt;
  &lt;span class='c1'&gt;# insert hacks for windows&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='c1'&gt;# snip more otherwise flawless code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a complete list of configuration details it contains, I&amp;#8217;d suggest busting out an irb, and poking around.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d love to go into further detail, but alas, all my past attempts at digging up more information have failed. I only came across it by chance while trying to figure out how to detect if I was on Windows for &lt;a href='http://github.com/technicalpickles/jeweler'&gt;jeweler&lt;/a&gt;, but even then, it was only code examples that I came across.&lt;/p&gt;

&lt;p&gt;What I do know, is that it contains information gathered at the time that you configure and build Ruby.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=oNniBjvI5l8:QUPLxHRIrdE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=oNniBjvI5l8:QUPLxHRIrdE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=oNniBjvI5l8:QUPLxHRIrdE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=oNniBjvI5l8:QUPLxHRIrdE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=oNniBjvI5l8:QUPLxHRIrdE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TechnicalPickles?a=oNniBjvI5l8:QUPLxHRIrdE:GLiUmhXMQSk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TechnicalPickles?i=oNniBjvI5l8:QUPLxHRIrdE:GLiUmhXMQSk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TechnicalPickles/~4/oNniBjvI5l8" height="1" width="1"/&gt;</content>
	</entry>
	
</feed>
