<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Mattenoble.com - Articles</title>
    <description>Writings and thoughts on Ruby, Rails and general Web Development.</description>
    <link>http://www.mattenoble.com</link>
    <item>
      <title>Ruby Blocks, Illustrated.</title>
      <description>&lt;div class="image-left"&gt;&lt;img src="/images/articles/blocks_illustrated.jpg" alt="ruby blocks"/&gt;&lt;/div&gt;

	&lt;p&gt;Blocks are sort of tricky when you first come to Ruby; I decided to make a quick little illustrated guide to using them.&lt;/p&gt;


	&lt;p&gt;&lt;span class="meta"&gt;buy_car&lt;/span&gt; accepts a block, denoted by the ampersand before the parameter &lt;span class="meta"&gt;&amp;#38;block&lt;/span&gt;. &lt;span class="meta"&gt;yield car&lt;/span&gt; passes the newly created car object to the block. The block then sets the color of that car object. Finally &lt;span class="meta"&gt;buy_car&lt;/span&gt; sets &lt;span class="meta"&gt;person.car&lt;/span&gt; to that newly colored car.&lt;/p&gt;


	&lt;p&gt;This is obviously a hugely simplified example, but hopefully it&amp;#8217;ll help someone understand blocks a little better.&lt;/p&gt;</description>
      <pubDate>Mon, 24 Aug 2009 23:54:41 +0000</pubDate>
      <link>http://blog.mattenoble.com/articles/ruby-blocks-illustrated</link>
    </item>
    <item>
      <title>Send Your Database With Your Commits.</title>
      <description>&lt;p&gt;Let me start off by saying, I like to have my development database full of data while working on a project. It lets me visualize the end result a lot easier. Whether that&amp;#8217;s good practice or not is another story.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m working on a project that has some pretty text heavy data. It became a huge pain in the ass to replicate the data I had on each machine I work on. So I came up with a super simple solution. I use Git and MySQL, so I combined the 2 into easy shell commands.&lt;/p&gt;


	&lt;p&gt;Add these to &lt;span class="meta"&gt;~/.bash_profile&lt;/span&gt;:&lt;/p&gt;&lt;pre class="railscasts"&gt;&lt;span class="line-numbers"&gt;  1  &lt;/span&gt; function &lt;span class="Source"&gt;&lt;span class="FunctionDefinition"&gt;gg&lt;/span&gt;&lt;span class="Source"&gt;()&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Source"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  2  &lt;/span&gt; &lt;span class="Source"&gt;  mysqldump -u user --skip-extended-insert database_name &lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt; ./sql/database_name.sql&lt;/span&gt;
&lt;span class="line-numbers"&gt;  3  &lt;/span&gt; &lt;span class="Source"&gt;  git commit -v -a -m &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;$&lt;/span&gt;*&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  4  &lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Source"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;&lt;span class="meta"&gt;Usage: gg message of the commit&lt;/span&gt;. First it dumps out the contents of your database into a file, &lt;span class="meta"&gt;./sql/database_name.sql&lt;/span&gt; then, assuming &lt;span class="meta"&gt;database_name.sql&lt;/span&gt; is already in your Git index, it will commit everything, database contents and all.&lt;/p&gt;


	&lt;p&gt;The next part of this is the component on the opposite end, the &lt;span class="meta"&gt;git pull&lt;/span&gt; part:&lt;/p&gt;&lt;pre class="railscasts"&gt;&lt;span class="line-numbers"&gt;  1  &lt;/span&gt; function &lt;span class="Source"&gt;&lt;span class="FunctionDefinition"&gt;gl&lt;/span&gt;&lt;span class="Source"&gt;()&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Source"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  2  &lt;/span&gt; &lt;span class="Source"&gt;  git pull&lt;/span&gt;
&lt;span class="line-numbers"&gt;  3  &lt;/span&gt; &lt;span class="Source"&gt;  mysql -u user database_name &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt; ./sql/database_name.sql&lt;/span&gt;
&lt;span class="line-numbers"&gt;  4  &lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Source"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Now you can call &lt;span class="meta"&gt;gl&lt;/span&gt; and it will first pull down any new stuff from your upstream Git repo, then apply the &lt;span class="meta"&gt;database_name.sql&lt;/span&gt; to your database.&lt;/p&gt;


	&lt;p&gt;This is a very dirty way of doing it, but it works pretty well for me.&lt;/p&gt;</description>
      <pubDate>Fri, 14 Aug 2009 03:29:06 +0000</pubDate>
      <link>http://blog.mattenoble.com/articles/send-your-database-with-your-commits</link>
    </item>
    <item>
      <title>Speccer: Bootstrapped Continuous Integration</title>
      <description>&lt;div class="image-left"&gt;&lt;img src="/images/articles/tm-speccer-command.jpg" alt="command setup" /&gt;&lt;/div&gt;

	&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous Integration&lt;/a&gt; is pretty awesome and there&amp;#8217;s a &lt;a href="http://cruisecontrolrb.thoughtworks.com/"&gt;few&lt;/a&gt; &lt;a href="http://cerberus.rubyforge.org/"&gt;options&lt;/a&gt; out there in the Ruby world. Most of them are more than what I want for my personal projects though, so I decided to hack together my own. I mainly use RSpec and all I wanted was something that would run my spec every time I save it or it&amp;#8217;s corresponding class/module. Enter, Speccer.&lt;/p&gt;


	&lt;p&gt;Speccer really has two parts, a TextMate command that replaces the normal Apple + S shortcut and the command line script that &amp;#8220;receives&amp;#8221; these saves. Set up your TextMate command like the image above, making sure to duplicate the settings exactly. Then copy in the code below.&lt;/p&gt;&lt;pre class="railscasts"&gt;&lt;span class="line-numbers"&gt;  1  &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;!/usr/bin/ruby&lt;/span&gt;
&lt;span class="line-numbers"&gt;  2  &lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Keyword"&gt;require&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;fileutils&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  3  &lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Keyword"&gt;require&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;ftools&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  4  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  5  &lt;/span&gt; logpath &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;expand_path&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;~/log&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt;  6  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  7  &lt;/span&gt; &lt;span class="Keyword"&gt;unless&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;directory?&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; logpath &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt;  8  &lt;/span&gt;     &lt;span class="Source"&gt;FileUtils&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;mkdir&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; logpath &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt;  9  &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt; 10 &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 11 &lt;/span&gt; log &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;open&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;join&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; logpath&lt;span class="Source"&gt;,&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;/spec.log&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;&lt;span class="Source"&gt;,&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;w&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt; 12 &lt;/span&gt; log&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;write&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;#{&lt;/span&gt;&lt;span class="StringInterpolation"&gt; &lt;/span&gt;&lt;span class="StringInterpolation"&gt;Time&lt;/span&gt;&lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;now&lt;/span&gt;&lt;/span&gt; &lt;span class="StringInterpolation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="StringInterpolation"&gt;\n&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 13 &lt;/span&gt; log&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;write&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;#{&lt;/span&gt;&lt;span class="StringInterpolation"&gt; &lt;/span&gt;&lt;span class="StringInterpolation"&gt;&lt;span class="ConstantOtherVariable"&gt;ENV&lt;/span&gt;[&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;TM_FILEPATH&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt; &lt;span class="StringInterpolation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="StringInterpolation"&gt;\n&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 14 &lt;/span&gt; log&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;write&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="ConstantOtherVariable"&gt;ENV&lt;/span&gt;[&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;TM_PROJECT_DIRECTORY&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;/span&gt;
&lt;span class="line-numbers"&gt; 15 &lt;/span&gt; log&lt;span class="Source"&gt;.&lt;/span&gt;close
&lt;/pre&gt;&lt;p&gt;Basically all this does is creates &lt;span class="meta"&gt;&lt;sub&gt;/log&lt;/span&gt; if it doesn&amp;#8217;t exist, opens &lt;span class="meta"&gt;&lt;/sub&gt;/log/spec.log&lt;/span&gt; and writes the time, file saved and the project directory to it, every time you hit Apple + S. This acts as a sort of Queue, but in reality the file only ever has one record in it at a time. This is how we let the script in the next part know about when we saved the file.&lt;/p&gt;


	&lt;p&gt;Create &lt;span class="meta"&gt;/usr/local/bin/speccer&lt;/span&gt; (or in whichever &lt;span class="meta"&gt;bin&lt;/span&gt; you want) and add the following:&lt;/p&gt;&lt;pre class="railscasts"&gt;&lt;span class="line-numbers"&gt;  1  &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt;!/usr/bin/ruby&lt;/span&gt;
&lt;span class="line-numbers"&gt;  2  &lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Keyword"&gt;require&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;ftools&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  3  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  4  &lt;/span&gt; log &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;open&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;expand_path&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;~/log/spec.log&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;&lt;span class="Source"&gt;,&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;r&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt;  5  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  6  &lt;/span&gt; &lt;span class="Keyword"&gt;loop&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
&lt;span class="line-numbers"&gt;  7  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  8  &lt;/span&gt;     &lt;span class="Source"&gt;&lt;span class="FunctionDefinition"&gt;trap&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;INT&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt; &lt;span class="Source"&gt;{&lt;/span&gt;&lt;span class="Source"&gt; &lt;/span&gt;&lt;span class="Source"&gt;|&lt;/span&gt;&lt;span class="Variable"&gt;this&lt;/span&gt;&lt;span class="Source"&gt;|&lt;/span&gt; puts &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;;&lt;/span&gt; exit this &lt;span class="Source"&gt;}&lt;/span&gt;
&lt;span class="line-numbers"&gt;  9  &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 10 &lt;/span&gt;     last_time &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;time&lt;/span&gt;
&lt;span class="line-numbers"&gt; 11 &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 12 &lt;/span&gt;     log&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;seek&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="Number"&gt;0&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;	
&lt;span class="line-numbers"&gt; 13 &lt;/span&gt;     record &lt;span class="Keyword"&gt;=&lt;/span&gt; log&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;read&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;split&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="StringInterpolation"&gt;\n&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt; 14 &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 15 &lt;/span&gt;     &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;time&lt;/span&gt;         &lt;span class="Keyword"&gt;=&lt;/span&gt; record&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;first&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 16 &lt;/span&gt;     &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;saved_file&lt;/span&gt;  &lt;span class="Keyword"&gt;=&lt;/span&gt; record&lt;span class="Source"&gt;[&lt;/span&gt;&lt;span class="Number"&gt;1&lt;/span&gt;&lt;span class="Source"&gt;]&lt;/span&gt;
&lt;span class="line-numbers"&gt; 17 &lt;/span&gt;     &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;proj_path&lt;/span&gt;  &lt;span class="Keyword"&gt;=&lt;/span&gt; record&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;last&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 18 &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 19 &lt;/span&gt;     &lt;span class="Keyword"&gt;begin&lt;/span&gt;
&lt;span class="line-numbers"&gt; 20 &lt;/span&gt; 	   
&lt;span class="line-numbers"&gt; 21 &lt;/span&gt;         &lt;span class="Keyword"&gt;unless&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;saved_file&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;include?&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;_spec.rb&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt; 22 &lt;/span&gt;             saved_file_array &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;saved_file&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;split&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;/&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt; 23 &lt;/span&gt;             lib_position       &lt;span class="Keyword"&gt;=&lt;/span&gt; saved_file_array&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;index&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;lib&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt; 
&lt;span class="line-numbers"&gt; 24 &lt;/span&gt;             spec_filename   &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Source"&gt;File&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;basename&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;saved_file&lt;/span&gt;&lt;span class="Source"&gt;,&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;.rb&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;_spec.rb&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 25 &lt;/span&gt;             spec_dir            &lt;span class="Keyword"&gt;=&lt;/span&gt; saved_file_array&lt;span class="Source"&gt;[&lt;/span&gt; lib_position&lt;span class="Keyword"&gt;+&lt;/span&gt;&lt;span class="Number"&gt;1&lt;/span&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="Source"&gt;.&lt;/span&gt;saved_file_array&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;length&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;-&lt;/span&gt;&lt;span class="Number"&gt;2&lt;/span&gt; &lt;span class="Source"&gt;]&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;join&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;/&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Source"&gt;)&lt;/span&gt;     
&lt;span class="line-numbers"&gt; 26 &lt;/span&gt;             &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;spec&lt;/span&gt;               &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;#{&lt;/span&gt;&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;proj_path&lt;/span&gt;&lt;span class="StringInterpolation"&gt;}&lt;/span&gt;&lt;/span&gt;/spec/&lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;#{&lt;/span&gt;spec_dir&lt;span class="StringInterpolation"&gt;}&lt;/span&gt;&lt;/span&gt;/&lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;#{&lt;/span&gt;spec_filename&lt;span class="StringInterpolation"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 27 &lt;/span&gt;         &lt;span class="Keyword"&gt;else&lt;/span&gt;
&lt;span class="line-numbers"&gt; 28 &lt;/span&gt;             &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;spec&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;saved_file&lt;/span&gt;
&lt;span class="line-numbers"&gt; 29 &lt;/span&gt;         &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt; 30 &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 31 &lt;/span&gt;         &lt;span class="Keyword"&gt;if&lt;/span&gt; last_time &lt;span class="Keyword"&gt;!=&lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;time&lt;/span&gt;
&lt;span class="line-numbers"&gt; 32 &lt;/span&gt;             &lt;span class="Source"&gt;&lt;span class="FunctionDefinition"&gt;system&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;clear&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt; 33 &lt;/span&gt;             puts &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;time&lt;/span&gt;
&lt;span class="line-numbers"&gt; 34 &lt;/span&gt;             &lt;span class="Source"&gt;&lt;span class="FunctionDefinition"&gt;system&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;spec &lt;span class="StringInterpolation"&gt;&lt;span class="StringInterpolation"&gt;#{&lt;/span&gt;&lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;spec&lt;/span&gt;&lt;span class="StringInterpolation"&gt;}&lt;/span&gt;&lt;/span&gt; -c -f specdoc&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;
&lt;span class="line-numbers"&gt; 35 &lt;/span&gt;         &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt; 36 &lt;/span&gt; 	
&lt;span class="line-numbers"&gt; 37 &lt;/span&gt;     &lt;span class="Keyword"&gt;rescue&lt;/span&gt;
&lt;span class="line-numbers"&gt; 38 &lt;/span&gt;     &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="line-numbers"&gt; 39 &lt;/span&gt; 
&lt;span class="line-numbers"&gt; 40 &lt;/span&gt;     sleep &lt;span class="Number"&gt;1&lt;/span&gt;
&lt;span class="line-numbers"&gt; 41 &lt;/span&gt; 	
&lt;span class="line-numbers"&gt; 42 &lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;This actual &lt;span class="meta"&gt;speccer&lt;/span&gt; script first opens the log file then just continuously checks to see if the Date is the same as the previous run through. If it is, it won&amp;#8217;t do anything, but if it&amp;#8217;s new it&amp;#8217;ll run the spec. The if-statement in the middle just figures out which spec is associated with the Class/Module file being saved by breaking apart the file&amp;#8217;s path and reconstructing it within the &lt;span class="meta"&gt;spec/&lt;/span&gt; folder. Speccer assumes you set up your &lt;span class="meta"&gt;spec/&lt;/span&gt; directory in the same structure as your &lt;span class="meta"&gt;lib/&lt;/span&gt; folder and name your specs &lt;span class="meta"&gt;classname_spec.rb&lt;/span&gt;. Save the script and &lt;span class="meta"&gt;chmod 755 speccer&lt;/span&gt; and you&amp;#8217;re set.&lt;/p&gt;


	&lt;p&gt;Now just run &lt;span class="meta"&gt;speccer&lt;/span&gt; then go writing your tests/specs and the file needed to make them pass. Every time you save one of them it&amp;#8217;ll automatically run. Quick and easy continuous integration for the solo developer.&lt;/p&gt;</description>
      <pubDate>Wed, 11 Mar 2009 04:47:05 +0000</pubDate>
      <link>http://blog.mattenoble.com/articles/speccer-bootstrapped-continuous-integration</link>
    </item>
    <item>
      <title>Be Your Own User</title>
      <description>&lt;p&gt;I constantly have ideas floating around in my head for cool and useful web-services or products, the problem is that they&amp;#8217;d never be useful to me. Most of them would be great for homeowners, teachers, etc. but I&amp;#8217;d probably never use them after launch. This is why I think a lot of web-based business fail so often, they aren&amp;#8217;t their own users.&lt;/p&gt;


	&lt;p&gt;Chris Wanstrath gave a great keynote at Startup Riot where he told &lt;a href="http://gist.github.com/67060"&gt;his tale of FamSpam and GitHub&lt;/a&gt;, which illustrates my point perfectly. He talks about a ton of other great things as well; check it out. In the end GitHub was what he loved to develop &lt;strong&gt;and use&lt;/strong&gt;, which made it better for everyone. For an idea to be successful (in any form of the word) it needs to be brilliant. I don&amp;#8217;t mean brilliant like having the most ridiculous algorithm in the world (although &lt;a href="http://www.google.com"&gt;sometimes&lt;/a&gt; that does work) or having all PhD&amp;#8217;s working for you. I mean a product that is 100% useful to it&amp;#8217;s audience and &lt;em&gt;continues&lt;/em&gt; to be a great experience for them.&lt;/p&gt;


	&lt;p&gt;Your high school teacher who told you that if you do what you love, you&amp;#8217;ll never work a day in your life, was so right. I forked that quote and changed it: if you &lt;strong&gt;create&lt;/strong&gt; what you love, you&amp;#8217;ll always have a user. What I mean by this is, create something that is useful to yourself and in the end it&amp;#8217;ll be a better product because of it. GitHub is what it is today because Chris and PJ use it themselves, everyday. You need to take it a step past just believing in what you&amp;#8217;re doing, you need to &lt;em&gt;use&lt;/em&gt; what you are doing.&lt;/p&gt;


	&lt;p&gt;Being your own user gives you a front row seat to see what could make it a better product. You can be selfish; develop features and fix bugs that bother you, as a user. You&amp;#8217;ll be making it better for yourself, but at the same time all your other users. From a user-experience point of view, it&amp;#8217;s easier to put yourself in the shoes of your customers, if you are one (obviously). You don&amp;#8217;t have to pretend to be part of them or try to speak their language, you naturally will and other users will appreciate that.&lt;/p&gt;</description>
      <pubDate>Tue, 03 Mar 2009 19:40:04 +0000</pubDate>
      <link>http://blog.mattenoble.com/articles/be-your-own-user</link>
    </item>
    <item>
      <title>Rock Your Own Dynamic Methods In Rails</title>
      <description>&lt;p&gt;&lt;span class="meta"&gt;method_missing&lt;/span&gt; is a piece of Ruby&amp;#8217;s meta-programming arsenal that&amp;#8217;s pretty powerful in my opinion. It allows you to call methods that don&amp;#8217;t actually exist, but still do something useful with it.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m trying to keep this short and sweet, so imagine you have a blog like this one. You have Article, Comment and Category models and you want a way to find all Articles/Comments/Categories by calling &lt;span class="meta"&gt;find_all_( articles | comments | categories)&lt;/span&gt;. So instead of create a &lt;span class="meta"&gt;find_all_*&lt;/span&gt; method for each resource, we&amp;#8217;ll let &lt;span class="meta"&gt;method_missing&lt;/span&gt; do the work for us:&lt;/p&gt;&lt;pre class="railscasts"&gt;&lt;span class="line-numbers"&gt;  1  &lt;/span&gt; &lt;span class="Source"&gt;&lt;span class="Source"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="ClassDefinition"&gt;ApplicationController&lt;span class="ClassDefinition"&gt; &lt;span class="ClassDefinition"&gt;&amp;lt;&lt;/span&gt; ActionController::Base&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  2  &lt;/span&gt; &lt;span class="Source"&gt;    &lt;/span&gt;
&lt;span class="line-numbers"&gt;  3  &lt;/span&gt; &lt;span class="Source"&gt;    &lt;span class="Keyword"&gt;private&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  4  &lt;/span&gt; &lt;span class="Source"&gt;    &lt;span class="Source"&gt;&lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="FunctionDefinition"&gt;method_missing&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="Source"&gt;method&lt;span class="Source"&gt;,&lt;/span&gt; &lt;span class="Keyword"&gt;*&lt;/span&gt;args&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  5  &lt;/span&gt; &lt;span class="Source"&gt;        resource &lt;span class="Keyword"&gt;=&lt;/span&gt; method&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;to_s&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;split&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;_&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;last&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  6  &lt;/span&gt; &lt;span class="Source"&gt;        &lt;span class="Keyword"&gt;if&lt;/span&gt; method&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;to_s&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;match&lt;/span&gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="String"&gt;^find_all_&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  7  &lt;/span&gt; &lt;span class="Source"&gt;            resource&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;singularize&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;camelize&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;constantize&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;&lt;span class="Source"&gt;.&lt;/span&gt;&lt;span class="FunctionDefinition"&gt;find&lt;/span&gt;&lt;/span&gt;&lt;span class="Source"&gt;(&lt;/span&gt;&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;all&lt;/span&gt;&lt;span class="Source"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  8  &lt;/span&gt; &lt;span class="Source"&gt;        &lt;span class="Keyword"&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  9  &lt;/span&gt; &lt;span class="Source"&gt;    &lt;span class="Keyword"&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 10 &lt;/span&gt; &lt;span class="Source"&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt; 11 &lt;/span&gt; &lt;span class="Source"&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;This is a very simple example of what &lt;span class="meta"&gt;method_missing&lt;/span&gt; can accomplish but it&amp;#8217;s a relevant one at least. &lt;span class="meta"&gt;method_missing&lt;/span&gt; takes two main arguments, the name of the method the user tried to call and the arguments passed through to that non-existent method.&lt;/p&gt;


	&lt;p&gt;If you follow a &lt;span class="meta"&gt;find_all_( model )&lt;/span&gt; naming convention the last word will always be the Model. In my example, first thing we do is set &lt;span class="meta"&gt;resource&lt;/span&gt; to that String representation of the Model (the last word of the find_all_* method). Next, we make sure the call is actually to a &lt;span class="meta"&gt;find_all_*&lt;/span&gt; method. The long &amp;#8220;-ize&amp;#8221; method chain makes the String singular ( &lt;span class="meta"&gt;&amp;#8220;comments&amp;#8221;.singularize #=&amp;gt; &amp;#8220;comment&amp;#8221;&lt;/span&gt; ), uppercases the first letter ( &lt;span class="meta"&gt;&amp;#8220;comment&amp;#8221;.camelize #=&amp;gt; &amp;#8220;Comment&amp;#8221;&lt;/span&gt; ), constantizes it ( &lt;span class="meta"&gt;&amp;#8220;Comment&amp;#8221;.constantize #=&amp;gt; Comment&lt;/span&gt; ) and finally calls a normal old &lt;span class="meta"&gt;find(:all)&lt;/span&gt; on it and returns the result. Now you can do this in your controllers:&lt;/p&gt;&lt;pre class="railscasts"&gt;&lt;span class="line-numbers"&gt;  1  &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; CommentsController.rb&lt;/span&gt;
&lt;span class="line-numbers"&gt;  2  &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;comments&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; find_all_comments
&lt;span class="line-numbers"&gt;  3  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  4  &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; ArticlesController.rb&lt;/span&gt;
&lt;span class="line-numbers"&gt;  5  &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;articles&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; find_all_articles
&lt;span class="line-numbers"&gt;  6  &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  7  &lt;/span&gt; &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; CategoriesController.rb&lt;/span&gt;
&lt;span class="line-numbers"&gt;  8  &lt;/span&gt; &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;categories&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; find_all_categories
&lt;/pre&gt;&lt;p&gt;My example only shows one &amp;#8220;magic method&amp;#8221; and is only a bit more readable, but you could extend it to check for &lt;span class="meta"&gt;find_recent_&lt;strong&gt;&lt;/span&gt; or maybe &lt;span class="meta"&gt;find_10_&lt;/strong&gt;&lt;/span&gt; pretty easily.&lt;/p&gt;</description>
      <pubDate>Wed, 25 Feb 2009 01:50:11 +0000</pubDate>
      <link>http://blog.mattenoble.com/articles/rock-your-own-dynamic-methods-in-rails</link>
    </item>
  </channel>
</rss>
