<?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>ideas.each &#38;:post &#187; ruby</title>
	<atom:link href="http://blog.tobiascrawley.net/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tobiascrawley.net</link>
	<description>Another not so cleverly named blog mostly about software.</description>
	<lastBuildDate>Fri, 28 May 2010 13:56:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>open_exception gem: now with better emacs support!</title>
		<link>http://blog.tobiascrawley.net/2010/05/28/open_exception-gem-now-with-better-emacs-support/</link>
		<comments>http://blog.tobiascrawley.net/2010/05/28/open_exception-gem-now-with-better-emacs-support/#comments</comments>
		<pubDate>Fri, 28 May 2010 13:56:51 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=325</guid>
		<description><![CDATA[I just released v0.3.1 of the open_exception gem. This release does a better job of handling exceptions that have been munged by Rails, and now provides a tempfile containing the full stack trace to the open command. If you are using emacs, you can use the :emacs_with_trace open command, and get the stack trace as [...]]]></description>
			<content:encoded><![CDATA[<p>I just released <a href="http://rubygems.org/gems/open_exception">v0.3.1</a> of the <a href="http://blog.tobiascrawley.net/2010/04/26/open_exception-gem-auto-open-exceptions-in-your-editor/">open_exception gem</a>. This release does a better job of handling exceptions that have been munged by Rails, and now provides a tempfile containing the full stack trace to the open command. </p>

<p>If you are using emacs, you can use the <code>:emacs_with_trace</code> open command, and get the stack trace as a navigable compilation buffer (next to || below) the source file in a split frame. For this to work, you&#8217;ll need to add the following function to your emacs init:</p>

<script src="http://gist.github.com/417151.js?file=gistfile1.el"></script>

<p>See github for the <a href="http://github.com/tobias/open_exception">code</a> and <a href="http://github.com/tobias/open_exception/blob/master/README.md"><span class="caps">README</span></a>.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2010/05/28/open_exception-gem-now-with-better-emacs-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>open_exception gem: auto open exceptions in your editor</title>
		<link>http://blog.tobiascrawley.net/2010/04/26/open_exception-gem-auto-open-exceptions-in-your-editor/</link>
		<comments>http://blog.tobiascrawley.net/2010/04/26/open_exception-gem-auto-open-exceptions-in-your-editor/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 21:58:13 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=318</guid>
		<description><![CDATA[open_exception opens an exception in your favorite editor when developing locally. It works by parsing the backtrace, and opening the offending file at the offending line in your favorite editor (assuming your favorite editor supports remote open commands). You can add filters that allow you to ignore some exceptions, and filters that allow you to [...]]]></description>
			<content:encoded><![CDATA[<p>open_exception opens an exception in your favorite editor when developing locally. It works by parsing the backtrace, and opening the offending file at the offending line in your favorite editor (assuming your favorite editor supports remote open commands).</p>

<p>You can add filters that allow you to ignore some exceptions, and filters that allow you to scope the backtrace search. The backtrace scoping is useful for opening the last call in your application code when the exception occurs in a framework or lib.</p>

<p>If you are on MacOSX and have the <a href="http://rubygems.org/gems/growl">growl gem</a> installed, you will get a growl notification with the exception message when the file is opened.</p>

<h3>Editors</h3>

<p>Out if the box, the gem supports three editors (with the following open commands):</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    <span style="color:#ff3333; font-weight:bold;">:emacs</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/usr/bin/emacsclient -n +{line} {file}'</span>,
    <span style="color:#ff3333; font-weight:bold;">:textmate</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/usr/local/bin/mate -a -d -l {line} {file}'</span>,
    <span style="color:#ff3333; font-weight:bold;">:macvim</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/usr/local/bin/mvim +{line} {file}'</span></pre></div></div>




<p>Note: if using emacs, you will need to be running <code>emacsserver</code>. To start the server: <code>M-x server-start</code><br />
or add <code>(server-start)</code> to your init.</p>

<h3>Configuration</h3>

<p>To configure, pass a block to the configure method:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    OpenException.<span style="color:#9900CC;">configure</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>oe<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#008000; font-style:italic;"># open_with can be one of the built in editors (:emacs, :macvim, :textmate)</span>
      <span style="color:#008000; font-style:italic;"># or a command to execute to open the file, where {file} and {line} will be replaced</span>
      <span style="color:#008000; font-style:italic;"># with the file path and line number, respectively. See 'Editors' above for an example.</span>
      <span style="color:#008000; font-style:italic;"># The default editor is :emacs.</span>
&nbsp;
      oe.<span style="color:#9900CC;">open_with</span> = <span style="color:#ff3333; font-weight:bold;">:emacs</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># you can add exclusion filters to ignore exceptions. A filter can be an exception class to </span>
      <span style="color:#008000; font-style:italic;"># ignore, or a proc that is passed the exception, and should evaluate to true if the exception </span>
      <span style="color:#008000; font-style:italic;"># should be ignored. Be careful with using a class - it uses is_a?, so any subclasses of the</span>
      <span style="color:#008000; font-style:italic;"># passed class will be ignored as well. The list of filters is [] by default.</span>
&nbsp;
      oe.<span style="color:#9900CC;">exclusion_filters</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> SomeErrorClass
      oe.<span style="color:#9900CC;">exclusion_filters</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>exception<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">if</span> exception_should_be_excluded <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># you can scope the search for the file:line to open with a filter as well. A filter can be a </span>
      <span style="color:#008000; font-style:italic;"># regular expression that is matched against the line, or a proc that is passed the line and </span>
      <span style="color:#008000; font-style:italic;"># should evaluate to true if the line should be used. The first line that any filter passes for </span>
      <span style="color:#008000; font-style:italic;"># will be the file:line that is opened. This is useful for opening the point in the stack just</span>
      <span style="color:#008000; font-style:italic;"># before control passes out of your app code when the exception occurs in an external </span>
      <span style="color:#008000; font-style:italic;"># lib/framework. The list of filters is [] by default. </span>
&nbsp;
      oe.<span style="color:#9900CC;">backtrace_line_filters</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>r<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">/</span>app<span style="color:#006600; font-weight:bold;">/</span>root<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>app<span style="color:#006600; font-weight:bold;">|</span>lib<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#125;</span> 
      oe.<span style="color:#9900CC;">backtrace_line_filters</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>backtrace_line<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">if</span> line_should_be_used <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>




<h3>Rails Integration</h3>

<p>The gem also alias chains in to rails&#8217; <code>ActionController#rescue_action_locally</code> method to automatically open exceptions in development mode. The gem also adds the following filter to the <code>:backtrace_line_filters</code> to scope the opened files to the app:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    @<span style="color:#006600; font-weight:bold;">%</span>r<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#008000; font-style:italic;">#{Rails.root}/(app|lib)}@</span></pre></div></div>




<p>To replace or remove this filter, you will need to reset the <code>:backtrace_line_filters</code> in your configure block:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    OpenException.<span style="color:#9900CC;">configure</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>oe<span style="color:#006600; font-weight:bold;">|</span>
      oe.<span style="color:#9900CC;">backtrace_line_filters</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      oe.<span style="color:#9900CC;">backtrace_line_filters</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> my_new_filter
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>




<p>This has been tested with rails v2.3.5, but should work fine with 2.1 &lt;= rails &lt; 3. It may work with rails 3 as well, I just haven&#8217;t yet looked at rails 3.</p>

<h3>Standalone/Other Frameworks</h3>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    <span style="color:#008000; font-style:italic;"># To manually open an exception, or wire it up in another framework, you call:</span>
    OpenException.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>exception<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># You can override the default (or configured) options by passing a hash as the second arg:</span>
    OpenException.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>exception, <span style="color:#006600; font-weight:bold;">&#123;</span>:open_with <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:textmate</span>, <span style="color:#ff3333; font-weight:bold;">:backtrace_line_filters</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span>filter, another_filter<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>




<p>The source is on <a href="http://github.com/tobias/open_exception">github</a>, and the gem is on <a href="http://rubygems.org/gems/open_exception">rubygems</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2010/04/26/open_exception-gem-auto-open-exceptions-in-your-editor/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Commenting out blocks of ruby in emacs</title>
		<link>http://blog.tobiascrawley.net/2010/02/17/commenting-out-blocks-of-ruby-in-emacs/</link>
		<comments>http://blog.tobiascrawley.net/2010/02/17/commenting-out-blocks-of-ruby-in-emacs/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 04:56:37 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=302</guid>
		<description><![CDATA[I&#8217;ve been an emacs user for 12+ years, and am ashamed to admit that I&#8217;ve never learned emacs lisp (yes, my last post was about emacs lisp code, but it was a copy and paste with a few changes, and I certainly didn&#8217;t understand what it was doing). Until now, that is. I started reading [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been an <a href="http://www.gnu.org/software/emacs/">emacs</a> user for 12+ years, and am ashamed to admit that I&#8217;ve never learned <a href="http://en.wikipedia.org/wiki/Emacs_Lisp">emacs lisp</a> (yes, my last post was about emacs lisp code, but it was a copy and paste with a few changes, and I certainly didn&#8217;t understand what it was doing). Until now, that is. I started reading the <a href="http://www.gnu.org/software/emacs/emacs-lisp-intro/">emacs lisp intro</a>, but only got about fifty pages in to it before I got the itch to write some code.</p>

<p>So here it is. Its a package that allows you to comment out a block of ruby code from a keybinding (I&#8217;m sure there is code out there to do this already, but it was a fun learning challenge).</p>

<p>The main function is <code>comment-ruby</code>, which I have bound to <code>C-:</code>. If there is a region active, it comments out the region. If that region is less than five lines, each line is commented with  &#8216;# &#8216;, otherwise the entire region is wrapped in <code>=begin...=end</code>. If the region is not active, the current line is commented out with &#8216;# &#8216;.</p>

<p>After a region has been commented out, the point (cursor) is set to the line above or below the region, depending on whether the point was at the beginning or end of the region when called.</p>

<p>Here is the code &#8211; it probably isn&#8217;t idiomatic lisp. If you have any suggestions on improving the code or making it more idiomatic, please let me know!</p>

<script src="http://gist.github.com/306302.js?file=comment-ruby.el"></script>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2010/02/17/commenting-out-blocks-of-ruby-in-emacs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The quest for a better keyboard layout</title>
		<link>http://blog.tobiascrawley.net/2009/12/05/the-quest-for-a-better-keyboard-layout/</link>
		<comments>http://blog.tobiascrawley.net/2009/12/05/the-quest-for-a-better-keyboard-layout/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 00:40:54 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[keyboard layout]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ukelele]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=241</guid>
		<description><![CDATA[The Quest Like most programmers, I type a lot &#8211; many hours a day, most days of the week. The keyboard is the primary conduit of my creative expression most of the time, whether I&#8217;m writing code or constructing elaborate stories to impress friends, clients, or co-workers (aka email/chat/this blog). For the last couple of [...]]]></description>
			<content:encoded><![CDATA[<h3>The Quest</h3>

<p> <img src="http://blog.tobiascrawley.net/wp-content/uploads/2009/12/AdventureQuest-header5-300x166.jpg" alt="" title="" width="300" height="166" class="alignleft size-medium wp-image-249" /></p>

<p>Like most programmers, I type a lot &#8211; many hours a day, most days of the week. The keyboard is the primary conduit of my creative expression most of the time, whether I&#8217;m writing code or constructing elaborate stories to impress friends, clients, or co-workers (aka email/chat/this blog). For the last couple of years, I&#8217;ve been mildly obsessed with making that conduit more efficient. I&#8217;ve <a href="http://en.wikipedia.org/wiki/IBM_Model_M">tried</a> <a href="http://www.microsoft.com/hardware/mouseandkeyboard/productdetails.aspx?pid=043">several</a> <a href="http://www.kinesis-ergo.com/images/freestyle-solo_690x375.jpg">different</a> <a href="http://www.kinesis-ergo.com/index.htm">keyboards</a> and entirely new <a href="http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard">keyboard</a> <a href="http://en.wikipedia.org/wiki/Colemak#Colemak">layouts</a>. </p>

<p>I stopped the keyboard search with the <a href="http://www.kinesis-ergo.com/index.htm">Kinesis Advantage</a> &#8211; it works really well for me, and is the easiest keyboard for touch typing that I&#8217;ve ever used. But the keyboard layout search continued. The productivity hit during the learning period for <a href="http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard">Dvorak</a> or <a href="http://en.wikipedia.org/wiki/Colemak#Colemak">Colemak</a> was too great, and I quickly slid back to <a href="http://en.wikipedia.org/wiki/Qwerty">Qwerty</a>. </p>

<p>I could type as fast as I wanted in Qwerty, so I tried to figure out what was really bugging me about my typing. I realized it was the shift key &#8211; I was frustrated with the high percentage of characters I typed that involved shift. I primarily code in Ruby, which uses &#8216;_&#8217; much more often than &#8216;-&#8217; (about 14 times more often), &#8216;:&#8217; more than &#8216;;&#8217; (about 78 times more often!), and &#8216;{}&#8217; more than &#8216;[]&#8216; (or so I thought &#8211; more on that later). </p>

<p>I then decided to create a custom keyboard layout that would reduce the need for the shift key when coding. My goals were:</p>


<ul>
<li>no remapping of the letter keys, since my muscle memory knows where they all are</li>
<li>remap commonly used symbols to be available without the shift key</li>
<li>be easy to learn, so no remapping characters to new keys</li>
</ul>



<p>Using the <a href="http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;id=Ukelele">Ukelele</a> keyboard layout editing tool (for MacOS), I played around with some layout ideas before settling on the one I&#8217;ve been using since May 2009.</p>

<h3>The Layout</h3>

<p><img src="http://blog.tobiascrawley.net/wp-content/uploads/2009/12/covered-model-railway-layout-300x253.jpg" alt="" title="" width="300" height="253" class="alignright size-medium wp-image-252" />
Since I mostly code in Ruby, and mostly use symbols in code vs. email/chat/etc., I remapped the shifted symbols I used more often.<br />
I &#8216;shift-swapped&#8217; (meaning the symbol you get with or without the shift key depressed are reversed) the following character pairs:</p>


<ul>
<li>{ [</li>
<li>} ]</li>
<li>| \</li>
<li>~ `</li>
<li>: ;</li>
<li>_ -</li>
</ul>




<p>I assumed that I used most of the symbols on the top row number keys more than I used the numbers, so I shift-swapped the 1 &#8211; 0 number keys with the corresponding symbol. If caps-lock is on, number keys revert to normal, but all of the other symbol keys remain swapped (meaning when caps-lock is on, pressing the &#8217;1&#8242; key will give you a 1, but pressing the &#8216;[' key will give you a {). Since the Kinesis keyboard does not have a separate keypad, this makes entering number sequences easier. </p>

<p>The caps-lock key has been moved to the f1 key, and I use the original caps-lock as a control key (for <a href="http://en.wikipedia.org/wiki/Emacs">Emacs</a>). This mapping can't be done by <a href="http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;id=Ukelele">Ukelele</a>, since it cannot remap function or modifier keys, so I did this using the remapping functionality in the Kinesis keyboard itself.</p>

<h3>Analysis</h3>

<p>After six weeks or so of using the new layout, I decided to analyze a large ruby codebase to see what my shift pair ratios actually were (something I should have done <em>before</em> creating a new layout). Using <a href="http://gist.github.com/133750">this script</a>, I got the following results:</p>



<pre>
Analyzed 457 files, 25060 lines
` ~     25     58  2.320
1 !   1161    713  0.614
2 @    564   2700  4.787
3 #    416   1914  4.601
4 $    264     55  0.208
5 %    359    303  0.844
6 ^    257     44  0.171
7 &amp;    152    226  1.487
8 *    176    115  0.653
9 (    196   4479  22.852
0 )   1761   4485  2.547
- _   1559  21837  14.007
[ {   1385   1304  0.942
] }   1396   1306  0.936
\ |    144   1480  10.278
; :    108   8446  78.204
= +   5588    729  0.130
&#8216; &quot;   5585   3909  0.700
, &lt;   4737    791  0.167
. &gt;  10257   2067  0.202
/ ?   1077   1054  0.979
</pre>



<p>Columns one and two are the shift pairs. Columns three and four are the occurrence counts for each character in the pair. The last column shows the ratio of the second character (normally shifted) to the first character (normally not shifted).  So a higher number in that column indicates an advantage to swapping the shift pair.</p>

<p>I looked at the shift pairs I had swapped, along with the other symbol shift pairs that I did not swap (the last five lines above).  There are some big wins here with my current remapping, along with some loses. The '[]'/'{}' swap was a small mistake - looks like I access elements of collections slightly more often than I define inline blocks or explicit hashes (which is kind of obvious in hindsight. In fact, on reflection I would think that collection access would happen considerably more often than inline block creation). And some of the number key remaps are big loses based on the ratios, but the lowest ratio pairs there have generally low volume. After this analysis, I didn't undo any of the remappings, though I should have reversed (and still should reverse) the bracket/brace swap. </p>

<h3>Usage </h3>

<p><img src="http://blog.tobiascrawley.net/wp-content/uploads/2009/12/hat-usage-instructions-300x266.jpg" alt="" title="" width="300" height="266" class="alignleft size-medium wp-image-259" />
The name of this layout is 'rubyist'. If you are interested in giving it a try, download the MacOS keylayout file <a href="http://tobiascrawley.net/rubyist/rubyist.keylayout">here</a>, and put it in ~/Library/Keyboard Layouts/. </p>

<p>I don't expect this layout to work well for everyone, or really anyone other than me. I do think all of us could benefit from evaluating the text we type the most, and seeing if some keyboard layout tweaks could make us more efficient. If you do want to give your own layout a try, check out these platform specific tools:</p>


<ul>
<li>MacOS: <a href="http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&amp;id=Ukelele">Ukelele</a></li>
<li>Linux: <a href="http://www.linux.com/archive/articles/113715"><span class="caps">XKB</span></a></li>
<li>Windows: <a href="http://msdn.microsoft.com/en-us/goglobal/bb964665.aspx">Microsoft Keyboard Layout Creator</a></li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/12/05/the-quest-for-a-better-keyboard-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pomodoro, status updates, and a distributed team</title>
		<link>http://blog.tobiascrawley.net/2009/11/05/pomodoro-status-updates-and-a-distributed-team/</link>
		<comments>http://blog.tobiascrawley.net/2009/11/05/pomodoro-status-updates-and-a-distributed-team/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 15:47:31 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[campfire]]></category>
		<category><![CDATA[pomodoro]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=232</guid>
		<description><![CDATA[For the last few months, I&#8217;ve been playing with the pomodoro technique to manage my time and stay focused on the task at hand. It works best for me when I&#8217;m stressed and have an overwhelming workload. It helps me focus on the immediate task, and not get distracted too much by all of the [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.tobiascrawley.net/wp-content/uploads/2009/11/pomodoro_status.jpg" alt="pomodoro_status" title="pomodoro_status" width="545" height="151" class="aligncenter size-full wp-image-235" /></p>

<p>For the last few months, I&#8217;ve been playing with the <a href="http://www.pomodorotechnique.com/">pomodoro technique</a> to manage my time and stay focused on the task at hand. It works best for me when I&#8217;m stressed and have an overwhelming workload. It helps me focus on the immediate task, and not get distracted too much by all of the other stuff I need to do. </p>

<p>One issue with managing the technique is keeping interruptions to a minimum. When I start a pomodoro, I&#8217;ll quit email, twitter, and chat. But we are a distributed team, and I work from home 95% of the time. I want to let the rest of the team know I&#8217;m around, but also let them know that I&#8217;m in a pomodoro, and to only interrupt in emergencies. Since we primarily use <a href="http://campfirenow.com">Campfire</a> to communicate, I set up a &#8216;Status&#8217; room there that allows us to post what we are up to/where we are at/etc. Its not only useful for pomodoro updates, but also &#8216;off to lunch&#8217;, &#8216;gone for the day&#8217;, etc. (And here is a third sentence that ends in etc.) But manually entering those status updates means they won&#8217;t happen. So I wrote a simple update script using the lovely <a href="http://tinder.rubyforge.org/">tinder</a> gem. It consists of two files &#8211; the script itself:</p>

<script src="http://gist.github.com/227107.js"></script>

<p>and the config file (<code>~/.campfire_status</code>):</p>

<script src="http://gist.github.com/227109.js"></script>

<p>But pomodoro status updates still require a manual step to run the script. Enter <a href="http://pomodoro.ugolandini.com/">Pomodoro</a>, a MacOS pomodoro client by <a href="http://www.ugolandini.com/">Ugo Landini</a>. His client allows integration with growl, twitter, and applescript. So I added the following applescript snippets to update the status for me:</p>

<script src="http://gist.github.com/227129.js"></script>

<p>A couple of gotchas I ran in to:<br />
* the Pomodoro app does not allow copy &amp; paste in the applescript text areas, making it a bit of a pain to enter<br />
* the Pomodoro app also has a file selector next to each applescript text area, but I could not get it to recognize the saved applescripts<br />
* the Campfire <span class="caps">API </span>seems to ignore requests from users that are currently logged in(?), so the status updates come from another account (in our case, we have a &#8216;service-bot&#8217; account that posts messages from other services). That&#8217;s why there is a <code>USER_NAME</code> setting that is displayed with the message.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/11/05/pomodoro-status-updates-and-a-distributed-team/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rails_habitat: a simple rails plugin to make RAILS_ENV a bit friendlier</title>
		<link>http://blog.tobiascrawley.net/2009/10/13/rails_habitat-a-simple-rails-plugin-to-make-rails_env-a-bit-friendlier/</link>
		<comments>http://blog.tobiascrawley.net/2009/10/13/rails_habitat-a-simple-rails-plugin-to-make-rails_env-a-bit-friendlier/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 20:04:30 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=227</guid>
		<description><![CDATA[I just released a stupid simple plugin based on the idea behind Coda Hale&#8217;s rails_environments plugin. This plugin adds the following functionality to the Rails module to help with determining the current enviroment: &#62;&#62; Rails.environment # a convenience alias to Rails.env =&#62; &#34;development&#34; &#62;&#62; Rails.development? =&#62; true &#62;&#62; Rails.not_development? =&#62; false &#62;&#62; Rails.production? =&#62; false [...]]]></description>
			<content:encoded><![CDATA[<p>I just released a stupid simple plugin based on the idea behind Coda Hale&#8217;s <a href="http://blog.codahale.com/2006/04/09/rails-environments-a-plugin-for-well-rails/">rails_environments plugin</a>.</p>

<p>This plugin adds the following functionality to the Rails module to help with determining the current enviroment:</p>



<pre>
  &gt;&gt; Rails.environment       # a convenience alias to Rails.env
  =&gt; &quot;development&quot;
  &gt;&gt; Rails.development?
  =&gt; true
  &gt;&gt; Rails.not_development?
  =&gt; false
  &gt;&gt; Rails.production?
  =&gt; false
  &gt;&gt; Rails.not_production?
  =&gt; true
  &gt;&gt; Rails.test?
  =&gt; false
  &gt;&gt; Rails.not_test?
  =&gt; true
</pre>



<p>Not only does it provide <code>env?</code> and <code>not_env?</code> methods for the standard environments, it also provides those methods for any environment you define in config/environments/ (in fact that is how it learns about all of the environments, including the standard three). So if you define new environments in config/environments/ they will be picked up automatically. </p>

<p>Install with: <code>script/plugin install git://github.com/tobias/rails_habitat.git</code></p>

<p>It lives on <a href="http://github.com/tobias/rails_habitat">github</a>.</p>

<p><strong>Edit</strong>: see David&#8217;s comment below for the built in way to do this (in Rails &gt;= 2.2).</p>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/10/13/rails_habitat-a-simple-rails-plugin-to-make-rails_env-a-bit-friendlier/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>zendesk_remote_auth gem makes Zendesk SSO easy!</title>
		<link>http://blog.tobiascrawley.net/2009/09/19/zendesk_remote_auth-gem-makes-zendesk-sso-easy/</link>
		<comments>http://blog.tobiascrawley.net/2009/09/19/zendesk_remote_auth-gem-makes-zendesk-sso-easy/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 04:25:58 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[zendesk]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=217</guid>
		<description><![CDATA[I extracted how we are doing Zendesk remote authentication from an app at Dealer Ignition, and stuck it in a small gem for your enjoyment. You can find it on GitHub. Installation and Setup Install: gem install tobias-zendesk_remote_auth Setup: You will need to give the gem your token and authentication url, perhaps in an initializer: [...]]]></description>
			<content:encoded><![CDATA[<p>I extracted how we are doing <a href="http://www.zendesk.com/api/remote_authentication">Zendesk remote authentication</a> from an app at <a href="http://dealerignition.com">Dealer Ignition</a>, and stuck it in a small gem for your enjoyment. You can find it on <a href="http://github.com/tobias/zendesk_remote_auth">GitHub</a>.</p>

<h3>Installation and Setup</h3>

<p>Install:</p>


<pre>gem install tobias-zendesk_remote_auth</pre>


<p>Setup:</p>

<p>You will need to give the gem your token and authentication url, perhaps in an initializer:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#6666ff; font-weight:bold;">Zendesk::RemoteAuth</span>.<span style="color:#9900CC;">token</span> = <span style="color:#996600;">'YOUR-TOKEN'</span>
  <span style="color:#6666ff; font-weight:bold;">Zendesk::RemoteAuth</span>.<span style="color:#9900CC;">auth_url</span> = <span style="color:#996600;">'https://yourcompany.zendesk.com/access/remote/'</span></pre></div></div>




<p>and config the gem in environment.rb (if using rails):</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">'tobias-zendesk_remote_auth'</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'zendesk_remote_auth'</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> http:<span style="color:#006600; font-weight:bold;">//</span>gems.<span style="color:#9900CC;">github</span>.<span style="color:#9900CC;">com</span><span style="color:#996600;">'</span></pre></div></div>




<h3>Usage</h3>

<p>Mixin the Zendesk::RemoteAuthHelper module wherever needed, then call:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  zendesk_remote_auth_url<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'user name'</span>,
                          <span style="color:#ff3333; font-weight:bold;">:email</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'user email'</span>,
                          <span style="color:#006600; font-weight:bold;">&lt;</span>optional params<span style="color:#006600; font-weight:bold;">&gt;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>




<p>This will return a url you can redirect the user to to log them in to your zendesk account. </p>

<p>As a convenience, you can pass a user object to zendesk_remote_auth_url:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  zendesk_remote_auth_url<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>




<p>This user must <code>respond_to?</code> <code>:name</code> and <code>:email</code>, and its <code>:id</code> will be used as the <code>:external_id</code> (making it useless with user objects that return an ephemeral object_id, but works well with ActiveRecord and the like). If the user object responds to <code>:zendesk_organization</code>, that will be used as the <code> <img src='http://blog.tobiascrawley.net/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rganization</code> for the call.</p>

<p>This method will generate and include the hash of the parameters for you if necessary. </p>

<h3>Example Auth Controller</h3>

<p>Here is an example controller that handles login and logout for zendesk:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># Uses restful-authentication style auth. </span>
  <span style="color:#008000; font-style:italic;"># </span>
  <span style="color:#008000; font-style:italic;"># Define the following in routes.rb:</span>
  <span style="color:#008000; font-style:italic;"># map.with_options :controller =&gt; 'zendesk_auth' do |zd|</span>
  <span style="color:#008000; font-style:italic;">#   zd.connect '/zendesk/authorize', :action =&gt; 'authorize'</span>
  <span style="color:#008000; font-style:italic;">#   zd.connect '/zendesk/logout', :action =&gt; 'logout'</span>
  <span style="color:#008000; font-style:italic;"># end</span>
  <span style="color:#9966CC; font-weight:bold;">class</span> ZendeskAuthController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
    <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Zendesk::RemoteAuthHelper</span>
&nbsp;
    skip_before_filter <span style="color:#ff3333; font-weight:bold;">:login_required</span>, <span style="color:#ff3333; font-weight:bold;">:only</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:logout</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> authorize
      redirect_to zendesk_remote_auth_url<span style="color:#006600; font-weight:bold;">&#40;</span>current_user<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> logout
      redirect_to logout_url
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    protected
    <span style="color:#9966CC; font-weight:bold;">def</span> login_required
      <span style="color:#9966CC; font-weight:bold;">if</span> !logged_in?
        flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">'You must log in to access the support site.'</span>
        store_location
        redirect_to login_path
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/09/19/zendesk_remote_auth-gem-makes-zendesk-sso-easy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RAILS_ROOT/app Organization</title>
		<link>http://blog.tobiascrawley.net/2009/07/18/rails_rootapp-organization/</link>
		<comments>http://blog.tobiascrawley.net/2009/07/18/rails_rootapp-organization/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 19:52:52 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[organization]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=211</guid>
		<description><![CDATA[As an app grows, so does the amount of files in app/models. Here is a simple tip to help reduce the clutter: move mailers, observers, and sweepers out of app/models into app/mailers, app/observers, and app/sweepers, respectively. For rails to still load them, you will need to modify config/environment.rb: # clean up app/models a bit %w&#123;mailers [...]]]></description>
			<content:encoded><![CDATA[<p>As an app grows, so does the amount of files in <code>app/models</code>. Here is a simple tip to help reduce the clutter: move mailers, observers, and sweepers out of <code>app/models</code> into <code>app/mailers</code>, <code>app/observers</code>, and <code>app/sweepers</code>, respectively. For rails to still load them, you will need to modify <code>config/environment.rb</code>:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># clean up app/models a bit</span>
  <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#123;</span>mailers observers sweepers<span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>dir<span style="color:#006600; font-weight:bold;">|</span>
    config.<span style="color:#9900CC;">load_paths</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;#{RAILS_ROOT}/app/#{dir}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>




<p>As a bonus, you can now automatically record your observers with <code>ActiveRecord</code> instead of having to add them individually in <code>environment.rb</code>:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  config.<span style="color:#9900CC;">active_record</span>.<span style="color:#9900CC;">observers</span> = <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">glob</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{RAILS_ROOT}/app/observers/*.rb&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>filename<span style="color:#006600; font-weight:bold;">|</span>
    filename.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'/'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">last</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'.'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">first</span>.<span style="color:#9900CC;">to_sym</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>




One issue with this reorganization is that the generators will continue to create mailers, observers, and sweepers in <code>app/models</code>. For me, that is not a big deal &#8211; I don&#8217;t create them often, and manually move them after generation. I suspect it would be trivial to adjust the generators to use the new path, but have not looked in to it. <br />
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/07/18/rails_rootapp-organization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>server_remote gem</title>
		<link>http://blog.tobiascrawley.net/2009/03/31/server_remote-gem/</link>
		<comments>http://blog.tobiascrawley.net/2009/03/31/server_remote-gem/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 18:47:47 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[simplecli]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=187</guid>
		<description><![CDATA[I just re-released my server_remote plugin as a gem server_remote on github. I converted it to a gem to make it easier to use in multiple apps, and to make it easier to update (see here for the blog entry on the (now obselete) plugin). It is a gem that provides support for running commands [...]]]></description>
			<content:encoded><![CDATA[<p>I just re-released my server_remote plugin as a gem <a href="http://github.com/tobias/server_remote">server_remote</a> on github. I converted it to a gem to make it easier to use in multiple apps, and to make it easier to update (see <a href="http://blog.tobiascrawley.net/2009/01/10/server_remote-a-rails-plugin-for-easily-accessing-servers/">here</a> for the blog entry on the (now obselete) plugin). </p>

It is a gem that provides support for running commands on remote server. Once set up, it provides commands via <code>script/remote</code>:<br />
<ul>
  <li><code>remote shell</code> &#8211; same as ssh&#8217;ing to the server (this is the default command, so it can be called with just <code>remote</code>)</li>
  <li><code>remote console</code> &#8211; executes a <code>script/console</code> on the server</li>
  <li><code>remote logtail</code> &#8211; executes <code>tail -f log/&lt;environment&gt;.log</code> on the server</li>
  <li><code>remote cmd &lt;some command&gt;</code> executes command on the server, displaying the result. It <code>cd</code>&#8216;s to the remote app root first.</li>
  <li><code>remote scp &lt;local_file&gt; :&lt;remote_file&gt;</code> provides scp. Prefix remote files with &#8216;:&#8217;</li></ul>Configuration is in <code>config/server_remote.yml</code>, and is grouped into <em>profiles</em>. 

<p>Here is the output of <code>remote usage</code>:</p>


<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">Executes commands on a remote server over ssh. Configuration is in:
/Users/tobias/customers/DealerIgnition/dealer_ignition/script/../config/server_remote.yml
&nbsp;
You can override the profile used with -p profile. The default profile is: app
&nbsp;
Learn more in the readme:
/opt/local/lib/ruby/gems/1.8/gems/tobias-server_remote-0.2.0/lib/server_remote/../../README.textile
&nbsp;
remote commands are:
&nbsp;
    DEFAULT COMMAND   shell
&nbsp;
    cmd               executes an arbitrary command on the server after a cd to the app path
    commands          List all 'remote' commands
    console           executes remote console
    help              Provide help documentation for a command
    logtail           executes remote tail -f on the log
    scp               copies files over scp (prefix remote files with ':')
    shell             executes remote shell
    usage             prints usage message
&nbsp;
For help on a particular command, use 'remote help COMMAND'.</pre></div></div>




<p>It uses <a href="http://remi.org">remi&#8217;s</a> <a href="http://github.com/remi/simplecli">simplecli</a> gem. </p>

<p>I plan to add other commands as needed, or you can open up <code>Remote::Commands</code> and add your own. </p>

<h3>Installation</h3>

<p>You will need to install the gem (only once), then setup any apps where you want to use it.</p>



<pre>
  sudo gem install tobias-server_remote --source http://gems.github.com/
  server_remotify path_to_app
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/03/31/server_remote-gem/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>credit_card_validator gem</title>
		<link>http://blog.tobiascrawley.net/2009/03/19/credit_card_validator-gem/</link>
		<comments>http://blog.tobiascrawley.net/2009/03/19/credit_card_validator-gem/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 01:21:32 +0000</pubDate>
		<dc:creator>Tobias</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.tobiascrawley.net/?p=169</guid>
		<description><![CDATA[I recently published a gem that provides credit card validation. It is basically a ruby port of the javascript credit card validator by Thomas Fuchs (madrobby). Usage: CreditCardValidator::Validator.valid?&#40;'1111 2222 3333 4444'&#41; &#160; # allow test numbers to be valid (for development) CreditCardValidator::Validator.options&#91;:test_numbers_are_valid&#93; = true CreditCardValidator::Validator.valid?&#40;'1111 2222 3333 4444'&#41; &#160; # limit the card types you [...]]]></description>
			<content:encoded><![CDATA[<p>I recently published a gem that provides credit card validation. It is basically a ruby port of the <a href="http://github.com/madrobby/creditcard_js">javascript credit card validator</a> by <a href="http://mir.aculo.us/">Thomas Fuchs</a> (<a href="http://github.com/madrobby">madrobby</a>).</p>

<p>Usage:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">valid</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'1111 2222 3333 4444'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># allow test numbers to be valid (for development) </span>
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">options</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:test_numbers_are_valid</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">valid</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'1111 2222 3333 4444'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># limit the card types you allow</span>
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">options</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:allowed_card_types</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:visa</span>, <span style="color:#ff3333; font-weight:bold;">:mastercard</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">valid</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'1111 2222 3333 4444'</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>




<p>Supported card types:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#ff3333; font-weight:bold;">:amex</span>, <span style="color:#ff3333; font-weight:bold;">:discover</span>, <span style="color:#ff3333; font-weight:bold;">:diners_club</span>, <span style="color:#ff3333; font-weight:bold;">:master_card</span>, <span style="color:#ff3333; font-weight:bold;">:visa</span></pre></div></div>




<p>Whitespace is stripped from the number automatically.</p>

<p>The following things are tested:</p>

<p>1. does the luhn validation code add up? (see <a href="http://en.wikipedia.org/wiki/Luhn_algorithm">http://en.wikipedia.org/wiki/Luhn_algorithm</a>)<br />
2. does the number range and length seem right? (see <a href="http://en.wikipedia.org/wiki/Bank_card_number">http://en.wikipedia.org/wiki/Bank_card_number</a>)<br />
3. is it one of several well-known test numbers?</p>

<p>Note: this only validates that the number is of a valid format, it does not check if it is an actual credit card number. You will need to talk to your payment gateway to learn that.</p>

<p>You can also use the validator to learn about the type of the card:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#008000; font-style:italic;"># gives the type back as a string (visa, master_card, etc)</span>
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">card_type</span><span style="color:#006600; font-weight:bold;">&#40;</span>number<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">is_visa</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>number<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">is_master_card</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>number<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#008000; font-style:italic;"># etc. - works for all of the supported card types</span>
&nbsp;
  <span style="color:#6666ff; font-weight:bold;">CreditCardValidator::Validator</span>.<span style="color:#9900CC;">is_allowed_card_type</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>number<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>




<p>To Install:</p>



<pre>
  gem install tobias-credit_card_validator --source http://gems.github.com
</pre>




<p>The source is available on <a href="http://github.com/tobias/credit_card_validator">github</a></p>]]></content:encoded>
			<wfw:commentRss>http://blog.tobiascrawley.net/2009/03/19/credit_card_validator-gem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
